// TODO: this doesn't work for IMXRT - no longer using predefined names | // TODO: this doesn't work for IMXRT - no longer using predefined names | ||||
extern "C" volatile uint32_t systick_millis_count; | extern "C" volatile uint32_t systick_millis_count; | ||||
extern "C" volatile uint32_t systick_cycle_count; | |||||
extern "C" uint32_t systick_safe_read; // micros() synchronization | |||||
extern "C" void systick_isr(void) | extern "C" void systick_isr(void) | ||||
{ | { | ||||
systick_cycle_count = ARM_DWT_CYCCNT; | |||||
systick_millis_count++; | systick_millis_count++; | ||||
MillisTimer::runFromTimer(); | MillisTimer::runFromTimer(); | ||||
} | } |
/* | |||||
IPAddress.cpp - Base class that provides IPAddress | |||||
Copyright (c) 2011 Adrian McEwen. All right reserved. | |||||
This library is free software; you can redistribute it and/or | |||||
modify it under the terms of the GNU Lesser General Public | |||||
License as published by the Free Software Foundation; either | |||||
version 2.1 of the License, or (at your option) any later version. | |||||
This library is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public | |||||
License along with this library; if not, write to the Free Software | |||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||||
*/ | |||||
#include <Arduino.h> | |||||
#include "IPAddress.h" | |||||
size_t IPAddress::printTo(Print& p) const | |||||
{ | |||||
int i=0; | |||||
while (1) { | |||||
p.print(_address.bytes[i], DEC); | |||||
if (++i >= 4) return 4; | |||||
p.write('.'); | |||||
} | |||||
} | |||||
bool IPAddress::fromString(const char *address) | |||||
{ | |||||
unsigned int acc = 0; // Accumulator | |||||
unsigned int dots = 0; | |||||
while (*address) { | |||||
char c = *address++; | |||||
if (c >= '0' && c <= '9') { | |||||
acc = acc * 10 + (c - '0'); | |||||
if (acc > 255) { | |||||
// Value out of [0..255] range | |||||
return false; | |||||
} | |||||
} else if (c == '.') { | |||||
if (dots == 3) { | |||||
// Too much dots (there must be 3 dots) | |||||
return false; | |||||
} | |||||
_address.bytes[dots++] = acc; | |||||
acc = 0; | |||||
} else { | |||||
// Invalid char | |||||
return false; | |||||
} | |||||
} | |||||
if (dots != 3) { | |||||
// Too few dots (there must be 3 dots) | |||||
return false; | |||||
} | |||||
_address.bytes[3] = acc; | |||||
return true; | |||||
} | |||||
#include "core_pins.h" | #include "core_pins.h" | ||||
#include "arm_math.h" // micros() synchronization | |||||
//volatile uint32_t F_CPU = 396000000; | //volatile uint32_t F_CPU = 396000000; | ||||
//volatile uint32_t F_BUS = 132000000; | //volatile uint32_t F_BUS = 132000000; | ||||
volatile uint32_t systick_millis_count = 0; | volatile uint32_t systick_millis_count = 0; | ||||
volatile uint32_t systick_cycle_count = 0; | |||||
uint32_t systick_safe_read; // micros() synchronization | |||||
// page 411 says "24 MHz XTALOSC can be the external clock source of SYSTICK" | // page 411 says "24 MHz XTALOSC can be the external clock source of SYSTICK" | ||||
// Testing shows the frequency is actually 100 kHz - but how? Did NXP really | // Testing shows the frequency is actually 100 kHz - but how? Did NXP really | ||||
// TODO... | // TODO... | ||||
} | } | ||||
uint32_t micros(void) | |||||
{ | |||||
uint32_t ccdelta, usec, smc, scc; | |||||
do { | |||||
__LDREXW(&systick_safe_read); | |||||
smc = systick_millis_count; | |||||
scc = systick_cycle_count; | |||||
} while ( __STREXW(1, &systick_safe_read)); | |||||
ccdelta = ARM_DWT_CYCCNT - scc; | |||||
usec = 1000*smc + (ccdelta/(F_CPU_ACTUAL/1000000)); | |||||
return usec; | |||||
} | |||||
#if 0 // kept to compare test to cycle count micro() | |||||
uint32_t micros(void) | uint32_t micros(void) | ||||
{ | { | ||||
uint32_t msec, tick, elapsed, istatus, usec; | uint32_t msec, tick, elapsed, istatus, usec; | ||||
prev_usec = usec; | prev_usec = usec; | ||||
return usec; | return usec; | ||||
} | } | ||||
#endif |
#define FLEXIO3_SHIFTBUFNIS1 (IMXRT_FLEXIO3_b.offset384) | #define FLEXIO3_SHIFTBUFNIS1 (IMXRT_FLEXIO3_b.offset384) | ||||
#define FLEXIO3_SHIFTBUFNIS2 (IMXRT_FLEXIO3_b.offset388) | #define FLEXIO3_SHIFTBUFNIS2 (IMXRT_FLEXIO3_b.offset388) | ||||
#define FLEXIO3_SHIFTBUFNIS3 (IMXRT_FLEXIO3_b.offset38C) | #define FLEXIO3_SHIFTBUFNIS3 (IMXRT_FLEXIO3_b.offset38C) | ||||
#define FLEXIO_CTRL_DOZEN ((uint16_t)(1<<31)) | |||||
#define FLEXIO_CTRL_DBGE ((uint16_t)(1<<30)) | |||||
#define FLEXIO_CTRL_FASTACC ((uint16_t)(1<<2)) | |||||
#define FLEXIO_CTRL_SWRST ((uint16_t)(1<<1)) | |||||
#define FLEXIO_CTRL_FLEXEN ((uint16_t)(1<<0)) | |||||
#define FLEXIO_SHIFTCTL_TIMSEL(n) ((uint16_t)(((n) & 0x03) << 24)) | |||||
#define FLEXIO_SHIFTCTL_TIMPOL ((uint16_t)(1<<23)) | |||||
#define FLEXIO_SHIFTCTL_PINCFG(n) ((uint16_t)(((n) & 0x03) << 16)) | |||||
#define FLEXIO_SHIFTCTL_PINSEL(n) ((uint16_t)(((n) & 0x1F) << 8)) | |||||
#define FLEXIO_SHIFTCTL_PINPOL ((uint16_t)(1<<7)) | |||||
#define FLEXIO_SHIFTCTL_SMOD(n) ((uint16_t)(((n) & 0x07) << 0)) | |||||
#define FLEXIO_SHIFTCFG_PWIDTH(n) ((uint16_t)(((n) & 0x1F) << 16)) | |||||
#define FLEXIO_SHIFTCFG_INSRC ((uint16_t)(1<<8)) | |||||
#define FLEXIO_SHIFTCFG_SSTOP(n) ((uint16_t)(((n) & 0x03) << 4)) | |||||
#define FLEXIO_SHIFTCFG_SSTART(n) ((uint16_t)(((n) & 0x03) << 0)) | |||||
#define FLEXIO_TIMCTL_TRGSEL(n) ((uint16_t)(((n) & 0x3F) << 24)) | |||||
#define FLEXIO_TIMCTL_TRGPOL ((uint16_t)(1<<23)) | |||||
#define FLEXIO_TIMCTL_TRGSRC ((uint16_t)(1<<22)) | |||||
#define FLEXIO_TIMCTL_PINCFG(n) ((uint16_t)(((n) & 0x03) << 16)) | |||||
#define FLEXIO_TIMCTL_PINSEL(n) ((uint16_t)(((n) & 0x1F) << 8)) | |||||
#define FLEXIO_TIMCTL_PINPOL ((uint16_t)(1<<7)) | |||||
#define FLEXIO_TIMCTL_TIMOD(n) ((uint16_t)(((n) & 0x03) << 0)) | |||||
#define FLEXIO_TIMCFG_TIMOUT(n) ((uint16_t)(((n) & 0x03) << 24)) | |||||
#define FLEXIO_TIMCFG_TIMDEC(n) ((uint16_t)(((n) & 0x03) << 20)) | |||||
#define FLEXIO_TIMCFG_TIMRST(n) ((uint16_t)(((n) & 0x07) << 16)) | |||||
#define FLEXIO_TIMCFG_TIMDIS(n) ((uint16_t)(((n) & 0x07) << 12)) | |||||
#define FLEXIO_TIMCFG_TIMENA(n) ((uint16_t)(((n) & 0x07) << 8)) | |||||
#define FLEXIO_TIMCFG_TSTOP(n) ((uint16_t)(((n) & 0x03) << 4)) | |||||
#define FLEXIO_TIMCFG_TSTART ((uint16_t)(1<<1)) | |||||
#define FLEXIO_CTRL_DOZEN ((uint32_t)(1<<31)) | |||||
#define FLEXIO_CTRL_DBGE ((uint32_t)(1<<30)) | |||||
#define FLEXIO_CTRL_FASTACC ((uint32_t)(1<<2)) | |||||
#define FLEXIO_CTRL_SWRST ((uint32_t)(1<<1)) | |||||
#define FLEXIO_CTRL_FLEXEN ((uint32_t)(1<<0)) | |||||
#define FLEXIO_SHIFTCTL_TIMSEL(n) ((uint32_t)(((n) & 0x03) << 24)) | |||||
#define FLEXIO_SHIFTCTL_TIMPOL ((uint32_t)(1<<23)) | |||||
#define FLEXIO_SHIFTCTL_PINCFG(n) ((uint32_t)(((n) & 0x03) << 16)) | |||||
#define FLEXIO_SHIFTCTL_PINSEL(n) ((uint32_t)(((n) & 0x1F) << 8)) | |||||
#define FLEXIO_SHIFTCTL_PINPOL ((uint32_t)(1<<7)) | |||||
#define FLEXIO_SHIFTCTL_SMOD(n) ((uint32_t)(((n) & 0x07) << 0)) | |||||
#define FLEXIO_SHIFTCFG_PWIDTH(n) ((uint32_t)(((n) & 0x1F) << 16)) | |||||
#define FLEXIO_SHIFTCFG_INSRC ((uint32_t)(1<<8)) | |||||
#define FLEXIO_SHIFTCFG_SSTOP(n) ((uint32_t)(((n) & 0x03) << 4)) | |||||
#define FLEXIO_SHIFTCFG_SSTART(n) ((uint32_t)(((n) & 0x03) << 0)) | |||||
#define FLEXIO_TIMCTL_TRGSEL(n) ((uint32_t)(((n) & 0x3F) << 24)) | |||||
#define FLEXIO_TIMCTL_TRGPOL ((uint32_t)(1<<23)) | |||||
#define FLEXIO_TIMCTL_TRGSRC ((uint32_t)(1<<22)) | |||||
#define FLEXIO_TIMCTL_PINCFG(n) ((uint32_t)(((n) & 0x03) << 16)) | |||||
#define FLEXIO_TIMCTL_PINSEL(n) ((uint32_t)(((n) & 0x1F) << 8)) | |||||
#define FLEXIO_TIMCTL_PINPOL ((uint32_t)(1<<7)) | |||||
#define FLEXIO_TIMCTL_TIMOD(n) ((uint32_t)(((n) & 0x03) << 0)) | |||||
#define FLEXIO_TIMCFG_TIMOUT(n) ((uint32_t)(((n) & 0x03) << 24)) | |||||
#define FLEXIO_TIMCFG_TIMDEC(n) ((uint32_t)(((n) & 0x03) << 20)) | |||||
#define FLEXIO_TIMCFG_TIMRST(n) ((uint32_t)(((n) & 0x07) << 16)) | |||||
#define FLEXIO_TIMCFG_TIMDIS(n) ((uint32_t)(((n) & 0x07) << 12)) | |||||
#define FLEXIO_TIMCFG_TIMENA(n) ((uint32_t)(((n) & 0x07) << 8)) | |||||
#define FLEXIO_TIMCFG_TSTOP(n) ((uint32_t)(((n) & 0x03) << 4)) | |||||
#define FLEXIO_TIMCFG_TSTART ((uint32_t)(1<<1)) | |||||
// 28.4.1: page 1354 | // 28.4.1: page 1354 | ||||
typedef struct { | typedef struct { |
case 0: flexpwm = &IMXRT_FLEXPWM1; break; | case 0: flexpwm = &IMXRT_FLEXPWM1; break; | ||||
case 1: flexpwm = &IMXRT_FLEXPWM2; break; | case 1: flexpwm = &IMXRT_FLEXPWM2; break; | ||||
case 2: flexpwm = &IMXRT_FLEXPWM3; break; | case 2: flexpwm = &IMXRT_FLEXPWM3; break; | ||||
case 3: flexpwm = &IMXRT_FLEXPWM4; | |||||
default: flexpwm = &IMXRT_FLEXPWM4; | |||||
} | } | ||||
flexpwmWrite(flexpwm, info->module & 0x03, info->channel, val); | flexpwmWrite(flexpwm, info->module & 0x03, info->channel, val); | ||||
} else if (info->type == 2) { | } else if (info->type == 2) { | ||||
case 0: qtimer = &IMXRT_TMR1; break; | case 0: qtimer = &IMXRT_TMR1; break; | ||||
case 1: qtimer = &IMXRT_TMR2; break; | case 1: qtimer = &IMXRT_TMR2; break; | ||||
case 2: qtimer = &IMXRT_TMR3; break; | case 2: qtimer = &IMXRT_TMR3; break; | ||||
case 3: qtimer = &IMXRT_TMR4; | |||||
default: qtimer = &IMXRT_TMR4; | |||||
} | } | ||||
quadtimerWrite(qtimer, info->module & 0x03, val); | quadtimerWrite(qtimer, info->module & 0x03, val); | ||||
} else { | } else { | ||||
case 0: flexpwm = &IMXRT_FLEXPWM1; break; | case 0: flexpwm = &IMXRT_FLEXPWM1; break; | ||||
case 1: flexpwm = &IMXRT_FLEXPWM2; break; | case 1: flexpwm = &IMXRT_FLEXPWM2; break; | ||||
case 2: flexpwm = &IMXRT_FLEXPWM3; break; | case 2: flexpwm = &IMXRT_FLEXPWM3; break; | ||||
case 3: flexpwm = &IMXRT_FLEXPWM4; | |||||
default: flexpwm = &IMXRT_FLEXPWM4; | |||||
} | } | ||||
flexpwmFrequency(flexpwm, info->module & 0x03, info->channel, frequency); | flexpwmFrequency(flexpwm, info->module & 0x03, info->channel, frequency); | ||||
} else if (info->type == 2) { | } else if (info->type == 2) { | ||||
case 0: qtimer = &IMXRT_TMR1; break; | case 0: qtimer = &IMXRT_TMR1; break; | ||||
case 1: qtimer = &IMXRT_TMR2; break; | case 1: qtimer = &IMXRT_TMR2; break; | ||||
case 2: qtimer = &IMXRT_TMR3; break; | case 2: qtimer = &IMXRT_TMR3; break; | ||||
case 3: qtimer = &IMXRT_TMR4; | |||||
default: qtimer = &IMXRT_TMR4; | |||||
} | } | ||||
quadtimerFrequency(qtimer, info->module & 0x03, frequency); | quadtimerFrequency(qtimer, info->module & 0x03, frequency); | ||||
} | } |
static void memory_copy(uint32_t *dest, const uint32_t *src, uint32_t *dest_end); | static void memory_copy(uint32_t *dest, const uint32_t *src, uint32_t *dest_end); | ||||
static void memory_clear(uint32_t *dest, uint32_t *dest_end); | static void memory_clear(uint32_t *dest, uint32_t *dest_end); | ||||
static void configure_systick(void); | static void configure_systick(void); | ||||
static void reset_PFD(); | |||||
extern void systick_isr(void); | extern void systick_isr(void); | ||||
extern void pendablesrvreq_isr(void); | extern void pendablesrvreq_isr(void); | ||||
void configure_cache(void); | void configure_cache(void); | ||||
for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); | for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); | ||||
SCB_VTOR = (uint32_t)_VectorsRam; | SCB_VTOR = (uint32_t)_VectorsRam; | ||||
reset_PFD(); | |||||
// Configure clocks | // Configure clocks | ||||
// TODO: make sure all affected peripherals are turned off! | // TODO: make sure all affected peripherals are turned off! | ||||
// PIT & GPT timers to run from 24 MHz clock (independent of CPU speed) | // PIT & GPT timers to run from 24 MHz clock (independent of CPU speed) | ||||
configure_cache(); | configure_cache(); | ||||
configure_systick(); | configure_systick(); | ||||
usb_pll_start(); | |||||
usb_pll_start(); | |||||
reset_PFD(); //TODO: is this really needed? | |||||
set_arm_clock(600000000); | set_arm_clock(600000000); | ||||
//set_arm_clock(984000000); Ludicrous Speed | //set_arm_clock(984000000); Ludicrous Speed | ||||
// the ARM clock to run at different speeds. | // the ARM clock to run at different speeds. | ||||
#define SYSTICK_EXT_FREQ 100000 | #define SYSTICK_EXT_FREQ 100000 | ||||
extern volatile uint32_t systick_cycle_count; | |||||
static void configure_systick(void) | static void configure_systick(void) | ||||
{ | { | ||||
_VectorsRam[14] = pendablesrvreq_isr; | _VectorsRam[14] = pendablesrvreq_isr; | ||||
SCB_SHPR3 = 0x20000000; // Systick = priority 32 | SCB_SHPR3 = 0x20000000; // Systick = priority 32 | ||||
ARM_DEMCR |= ARM_DEMCR_TRCENA; | ARM_DEMCR |= ARM_DEMCR_TRCENA; | ||||
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; // turn on cycle counter | ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; // turn on cycle counter | ||||
systick_cycle_count = ARM_DWT_CYCCNT; // compiled 0, corrected w/1st systick | |||||
} | } | ||||
} | } | ||||
} | } | ||||
__attribute__((section(".progmem"))) | |||||
void reset_PFD() | |||||
{ | |||||
//Reset PLL2 PFDs, set default frequencies: | |||||
CCM_ANALOG_PFD_528_SET = (1 << 31) | (1 << 23) | (1 << 15) | (1 << 7); | |||||
CCM_ANALOG_PFD_528 = 0x2018101B; // PFD0:352, PFD1:594, PFD2:396, PFD3:297 MHz | |||||
//PLL3: | |||||
CCM_ANALOG_PFD_480_SET = (1 << 31) | (1 << 23) | (1 << 15) | (1 << 7); | |||||
CCM_ANALOG_PFD_480 = 0x13110D0C; // PFD0:720, PFD1:664, PFD2:508, PFD3:454 MHz | |||||
} | |||||
// Stack frame | // Stack frame | ||||
// xPSR | // xPSR | ||||
// R2 | // R2 | ||||
// R1 | // R1 | ||||
// R0 | // R0 | ||||
__attribute__((weak)) | |||||
void unused_interrupt_vector(void) | void unused_interrupt_vector(void) | ||||
{ | { | ||||
// TODO: polling Serial to complete buffered transmits | // TODO: polling Serial to complete buffered transmits | ||||
printf(" %x\n", addr); | printf(" %x\n", addr); | ||||
#endif | #endif | ||||
#if 1 | #if 1 | ||||
if ( F_CPU_ACTUAL >= 600000000 ) | |||||
set_arm_clock(100000000); | |||||
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5; // pin 13 | IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5; // pin 13 | ||||
IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7); | IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7); | ||||
GPIO2_GDIR |= (1<<3); | GPIO2_GDIR |= (1<<3); | ||||
while (1) { | while (1) { | ||||
volatile uint32_t n; | volatile uint32_t n; | ||||
GPIO2_DR_SET = (1<<3); //digitalWrite(13, HIGH); | GPIO2_DR_SET = (1<<3); //digitalWrite(13, HIGH); | ||||
for (n=0; n < 2000000; n++) ; | |||||
for (n=0; n < 2000000/6; n++) ; | |||||
GPIO2_DR_CLEAR = (1<<3); //digitalWrite(13, LOW); | GPIO2_DR_CLEAR = (1<<3); //digitalWrite(13, LOW); | ||||
for (n=0; n < 1500000; n++) ; | |||||
for (n=0; n < 1500000/6; n++) ; | |||||
} | } | ||||
#else | #else | ||||
if ( F_CPU_ACTUAL >= 600000000 ) | |||||
set_arm_clock(100000000); | |||||
while (1) { | while (1) { | ||||
} | } | ||||
#endif | #endif |