| // 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 |