| @@ -336,8 +336,11 @@ void MillisTimer::runFromTimer() | |||
| // 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_cycle_count; | |||
| extern "C" uint32_t systick_safe_read; // micros() synchronization | |||
| extern "C" void systick_isr(void) | |||
| { | |||
| systick_cycle_count = ARM_DWT_CYCCNT; | |||
| systick_millis_count++; | |||
| MillisTimer::runFromTimer(); | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| /* | |||
| 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; | |||
| } | |||
| @@ -1,8 +1,11 @@ | |||
| #include "core_pins.h" | |||
| #include "arm_math.h" // micros() synchronization | |||
| //volatile uint32_t F_CPU = 396000000; | |||
| //volatile uint32_t F_BUS = 132000000; | |||
| 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" | |||
| // Testing shows the frequency is actually 100 kHz - but how? Did NXP really | |||
| @@ -61,6 +64,20 @@ void delay(uint32_t msec) | |||
| // 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 msec, tick, elapsed, istatus, usec; | |||
| @@ -118,4 +135,4 @@ uint32_t micros(void) | |||
| prev_usec = usec; | |||
| return usec; | |||
| } | |||
| #endif | |||
| @@ -2945,35 +2945,35 @@ typedef struct { | |||
| #define FLEXIO3_SHIFTBUFNIS1 (IMXRT_FLEXIO3_b.offset384) | |||
| #define FLEXIO3_SHIFTBUFNIS2 (IMXRT_FLEXIO3_b.offset388) | |||
| #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 | |||
| typedef struct { | |||
| @@ -162,7 +162,7 @@ void analogWrite(uint8_t pin, int val) | |||
| case 0: flexpwm = &IMXRT_FLEXPWM1; break; | |||
| case 1: flexpwm = &IMXRT_FLEXPWM2; break; | |||
| case 2: flexpwm = &IMXRT_FLEXPWM3; break; | |||
| case 3: flexpwm = &IMXRT_FLEXPWM4; | |||
| default: flexpwm = &IMXRT_FLEXPWM4; | |||
| } | |||
| flexpwmWrite(flexpwm, info->module & 0x03, info->channel, val); | |||
| } else if (info->type == 2) { | |||
| @@ -172,7 +172,7 @@ void analogWrite(uint8_t pin, int val) | |||
| case 0: qtimer = &IMXRT_TMR1; break; | |||
| case 1: qtimer = &IMXRT_TMR2; break; | |||
| case 2: qtimer = &IMXRT_TMR3; break; | |||
| case 3: qtimer = &IMXRT_TMR4; | |||
| default: qtimer = &IMXRT_TMR4; | |||
| } | |||
| quadtimerWrite(qtimer, info->module & 0x03, val); | |||
| } else { | |||
| @@ -196,7 +196,7 @@ void analogWriteFrequency(uint8_t pin, float frequency) | |||
| case 0: flexpwm = &IMXRT_FLEXPWM1; break; | |||
| case 1: flexpwm = &IMXRT_FLEXPWM2; break; | |||
| case 2: flexpwm = &IMXRT_FLEXPWM3; break; | |||
| case 3: flexpwm = &IMXRT_FLEXPWM4; | |||
| default: flexpwm = &IMXRT_FLEXPWM4; | |||
| } | |||
| flexpwmFrequency(flexpwm, info->module & 0x03, info->channel, frequency); | |||
| } else if (info->type == 2) { | |||
| @@ -206,7 +206,7 @@ void analogWriteFrequency(uint8_t pin, float frequency) | |||
| case 0: qtimer = &IMXRT_TMR1; break; | |||
| case 1: qtimer = &IMXRT_TMR2; break; | |||
| case 2: qtimer = &IMXRT_TMR3; break; | |||
| case 3: qtimer = &IMXRT_TMR4; | |||
| default: qtimer = &IMXRT_TMR4; | |||
| } | |||
| quadtimerFrequency(qtimer, info->module & 0x03, frequency); | |||
| } | |||
| @@ -21,6 +21,7 @@ void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void); | |||
| 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 configure_systick(void); | |||
| static void reset_PFD(); | |||
| extern void systick_isr(void); | |||
| extern void pendablesrvreq_isr(void); | |||
| void configure_cache(void); | |||
| @@ -60,6 +61,8 @@ void ResetHandler(void) | |||
| for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128); | |||
| SCB_VTOR = (uint32_t)_VectorsRam; | |||
| reset_PFD(); | |||
| // Configure clocks | |||
| // TODO: make sure all affected peripherals are turned off! | |||
| // PIT & GPT timers to run from 24 MHz clock (independent of CPU speed) | |||
| @@ -74,8 +77,9 @@ void ResetHandler(void) | |||
| configure_cache(); | |||
| configure_systick(); | |||
| usb_pll_start(); | |||
| usb_pll_start(); | |||
| reset_PFD(); //TODO: is this really needed? | |||
| set_arm_clock(600000000); | |||
| //set_arm_clock(984000000); Ludicrous Speed | |||
| @@ -111,6 +115,7 @@ void ResetHandler(void) | |||
| // the ARM clock to run at different speeds. | |||
| #define SYSTICK_EXT_FREQ 100000 | |||
| extern volatile uint32_t systick_cycle_count; | |||
| static void configure_systick(void) | |||
| { | |||
| _VectorsRam[14] = pendablesrvreq_isr; | |||
| @@ -121,6 +126,7 @@ static void configure_systick(void) | |||
| SCB_SHPR3 = 0x20000000; // Systick = priority 32 | |||
| ARM_DEMCR |= ARM_DEMCR_TRCENA; | |||
| ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; // turn on cycle counter | |||
| systick_cycle_count = ARM_DWT_CYCCNT; // compiled 0, corrected w/1st systick | |||
| } | |||
| @@ -236,6 +242,16 @@ void usb_pll_start() | |||
| } | |||
| } | |||
| __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 | |||
| // xPSR | |||
| @@ -246,6 +262,7 @@ void usb_pll_start() | |||
| // R2 | |||
| // R1 | |||
| // R0 | |||
| __attribute__((weak)) | |||
| void unused_interrupt_vector(void) | |||
| { | |||
| // TODO: polling Serial to complete buffered transmits | |||
| @@ -285,6 +302,8 @@ void unused_interrupt_vector(void) | |||
| printf(" %x\n", addr); | |||
| #endif | |||
| #if 1 | |||
| if ( F_CPU_ACTUAL >= 600000000 ) | |||
| set_arm_clock(100000000); | |||
| IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5; // pin 13 | |||
| IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7); | |||
| GPIO2_GDIR |= (1<<3); | |||
| @@ -292,11 +311,13 @@ void unused_interrupt_vector(void) | |||
| while (1) { | |||
| volatile uint32_t n; | |||
| 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); | |||
| for (n=0; n < 1500000; n++) ; | |||
| for (n=0; n < 1500000/6; n++) ; | |||
| } | |||
| #else | |||
| if ( F_CPU_ACTUAL >= 600000000 ) | |||
| set_arm_clock(100000000); | |||
| while (1) { | |||
| } | |||
| #endif | |||