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