Teensy 4.0 First Beta Test

Status
Not open for further replies.
@defragster

My guess is that the ribbon cable/connector is lower your the temp of the board. If you are running at 49-50C and your panic temp is 50C probably wont trip - not above the threshold - try setting the panic at about 47C and see what happens. From pg1273-4:
The panic threshold is a special programmable threshold in that if the temperature increases above this value and the temperature-panic-reset interrupt is enabled in the System Reset Controller, the hardware will assume that software no longer has control over the thermal situation and will initiate a reset of the chip
and
In order to avoid false panic temperature initiated resets, the panic alarm will not fire until the temperature panic condition has been met for four consecutive conversion cycles.

As for the 20.8.3 SRC Reset Status Register (SRC_SRSR) please note:
For bit[6-0] - writing zero does not have any effect. Writing one will clear the corresponding bit. The individual bits can be cleared by writing one to that bit. When the system comes out of reset, this register will have bits set corresponding to all the reset sources that occurred during system reset. Software has to take care to clear this register by writing one after every reset that occurs so that the register will contain the information of recently occurred reset

if you check bit 8 of the register it will tell you whether the reset occurred due the temperature sensor.

If the register is just reading a "1" that probably just indicate the " reset was the result of ipp_reset_b pin (Power-up sequence)".
 
Indeed the ribbon cable unit is heat sunk lower it seems - but funny thing the code on that one is showing this:
Code:
@micros>>131967969 [ms>>131967] Time is Fri Jul 12 20:40:45 2019
C=49C=50C=51
Repeatedly reading out 51 degrees and staying alive. That loop only shows increases - then resets 'max' every 10 seconds if it happens to drop. So current code is constant reading and the 'four consecutive' must be

The other one does go missing - will leave the set point there for now as I get feedback code into the _isr()'s. I'll drop it down then.

Thanks for opening the manual again - I looked some time ago … just edited startup.c to this for now:
Code:
void ResetHandler(void)
{
	unsigned int i;
	uint32_t WIPstartup_reset_SRSR = SRC_SRSR; // WIP
	SRC_SRSR=1; // WIP

Just got a PANIC and powered on restart still shows #1 - so that didn't do it:
Code:
@micros>>120960209 [ms>>120960] Time is Fri Jul 12 21:03:45 2019
C=50C=51
@micros>>131960166 [ms>>131960] Time is Fri Jul 12 21:03:56 2019
C=49C=50C=51
@micros>>142960123 [ms>>142960] Time is Fri Jul 12 21:04:07 2019
C=50C=51Compile Time:: T:\tCode\T4\ShowTimeTemp\ShowTimeTemp.ino Jul 12 2019 20:56:11
M[B]Y_startup_reset_SRSR == 1[/B]

 F_CPU=600000000	deg  C=46

Start setup():: E_HOOK us>>1514 [ii3#>>1] E_hook millis is 1
Start setup():: L_HOOK us>>45363 [ii2#>>5] L_hook millis is 45
Start setup():: @us>>300000 [static ii ms>>300] setup millis is 300
@micros>>337022 [ms>>337] Time is Tue Jan  1 00:00:00 2019

BTW - that print is the HEX value of the register showing == 1, no indication of TEMP

That's why I'm wondering if the bootloader MCU triggers a reset somehow …
 
@defragster

Couldn't sleep thinking about this so I had to give it a test. I must have a very unique T4 with the ribbon cable on it because when it resets due to temp it resets but then doesn't continue the start up it freezes - I loose seeing the board in tycommander or the ide - no port etc. if I reset it with a power off and the on it continues unless the temp stays high? This is not what you are seeing or what I saw in my previous tests..... Same thing happens on the T4B2 with the white wire on the bottom?

Strange.
 
[mjs513@just read your cross post - no it doesn't reset - on PANIC trigger it goes to a stop - as noted above 3.3V section and POWER active - but no execution ... also noted below]
Okay both _isr()'s firing and showing up - it does give PANIC_ISR before it dies - must fire ISR on any measure over PANIC threshold - but need 4 readings to restart:

Below is sketch output with these tempmon vars not-static so I could 'extern C' tweak them:
uint32_t highAlarmTemp = 46U; // 85U
uint32_t lowAlarmTemp = 45U; // 25U
uint32_t panicAlarmTemp = 48U; //90U

LOW triggers - I print and push 'sketch reference' down a degree on each print so it stops, alarm level not changed - just print threshold.
HIGH triggers as it heats - and I push 'sketch reference' up a degree on each print so it stops, alarm level not changed - just print threshold.
PANIC triggers as it heats - and I push 'sketch reference' up a degree on print so it stops, alarm level not changed - just print threshold.
>> It heats one more degree and the PANIC STOPS the CPU
>> it does not RESET to running! - it just goes 'missing' when the four PANIC measures are made
>> as noted still has 3.3V power alive for Power button, and does a code upload on Teensy Button push.
Code:
Compile Time:: T:\tCode\T4\ShowTimeTemp\ShowTimeTemp.ino Jul 12 2019 22:50:16
MY_startup_reset_SRSR == 1

 F_CPU=600000000	deg  C=40

Start setup():: E_HOOK us>>1483 [ii3#>>1] E_hook millis is 1
Start setup():: L_HOOK us>>45367 [ii2#>>5] L_hook millis is 45
Start setup():: @us>>300000 [static ii ms>>300] setup millis is 300
@micros>>396033 [ms>>396] Time is Tue Jan  1 00:00:00 2019

LOW Temperature [45] Alarm 40.7. 
40° [COLOR="#FF0000"]LOW Temperature [44] Alarm 40.7.[/COLOR] 
41° [COLOR="#FF0000"]LOW Temperature [43] Alarm 41.4.[/COLOR] 
[COLOR="#FF0000"]LOW Temperature [42] Alarm 41.4.[/COLOR] 
[COLOR="#FF0000"]LOW Temperature [41] Alarm 40.7.[/COLOR] 
42° 43° 44° 45° 
@micros>>10936724 [ms>>10936] Time is Tue Jan  1 00:00:00 2019
45° 46° 	[COLOR="#FF0000"][B]HIGH Temperature [46] Alarm 46.6.[/B][/COLOR] 

@micros>>21936677 [ms>>21936] Time is Tue Jan  1 00:00:11 2019
45° 46° 47° 	[COLOR="#FF0000"][B]HIGH Temperature [47] Alarm 47.2.[/B][/COLOR] 

@micros>>32936629 [ms>>32936] Time is Tue Jan  1 00:00:22 2019
46° 47° 
@micros>>65936475 [ms>>65936] Time is Tue Jan  1 00:00:55 2019
47° 
@micros>>76936414 [ms>>76936] Time is Tue Jan  1 00:01:06 2019
47° 48° 	[COLOR="#FF0000"][B][U]PANIC Temperature [48]  Alarm 48.6.[/U][/B][/COLOR] 

@micros>>87936374 [ms>>87936] Time is Tue Jan  1 00:01:17 2019
47° 48° 
@micros>>98936324 [ms>>98936] Time is Tue Jan  1 00:01:28 2019
47° 48° 
@micros>>109936273 [ms>>109936] Time is Tue Jan  1 00:01:39 2019
47° 
@micros>>230935729 [ms>>230935] Time is Tue Jan  1 00:03:40 2019
48° 49° 	[COLOR="#FF0000"][B][U]PANIC Temperature [49]  Alarm 49.2[/U][/B][/COLOR]. 
	HIGH Temperature [48] Alarm 48.6. 
	HIGH Temperature [49] Alarm 49.2.

Just turned on window fan so room is cooling - no longer hitting the high just now - stalled at 47°C - took some time but hit 48 to show PANIC - but still running as it failed four over value test so far. Turning it off even one second to restart drops the temp 2 degrees C.

@mjs513 :: In the DEMO tempMon.ino the 3 temp values were passed in as params. Would it make sense to provide a method for user sketch to set those values? In my sample sketch I stop printing - but the _isr()'s are still firing like crazy. While a USER won't be doing THIS - they may have the need to easily adjust the threshold values at startup for a given environment.

Here is the sketch code - given the non-STATIC vars above - and it uses the startup_hooks - though they are not required for this test {though temp _isr()'s are activated in EARLY} - it was just the open sketch I started with. Also added startup_reset_hook() as I thought I would be working from there not in sketch - but this worked:
Code:
#include <time.h>
time_t tt;
uint32_t  jj, kk, ii = millis();
uint32_t  jj2, kk2, ii2 = 1;
uint32_t  jj3, kk3, ii3 = 2;
extern "C" uint32_t startup_reset_SRSR;
extern "C" uint32_t highAlarmTemp;
extern "C" uint32_t lowAlarmTemp;
// ttt static uint32_t panicAlarmTemp  = 90U;
extern "C" uint32_t panicAlarmTemp;
uint32_t MY_startup_reset_SRSR;
elapsedMillis ems = 0;

volatile bool TempAlarm = false;

void High_Low_Temp_isr(void)
{
	NVIC_DISABLE_IRQ(IRQ_TEMPERATURE);
	digitalWriteFast( LED_BUILTIN, LOW );
	TempAlarm = true;
}

void Panic_Temp_isr(void)
{
	NVIC_DISABLE_IRQ(IRQ_TEMPERATURE_PANIC);
	digitalWriteFast( LED_BUILTIN, LOW );
	TempAlarm = true;
}


#ifdef __cplusplus
extern "C" {
#endif
PROGMEM void [B]startup_early_hook(void)[/B] {
	pinMode( LED_BUILTIN, OUTPUT);
	digitalWrite( LED_BUILTIN, HIGH );
	//digitalWriteFast( LED_BUILTIN, HIGH ); // This works too!
	delayMicroseconds(10);
	delayNanoseconds(10);
	jj3 = micros();
	kk3 = millis();
	ii3--;
[COLOR="#FF0000"]	attachInterruptVector(IRQ_TEMPERATURE, &High_Low_Temp_isr);
	NVIC_ENABLE_IRQ(IRQ_TEMPERATURE);
	attachInterruptVector(IRQ_TEMPERATURE_PANIC, &Panic_Temp_isr);
	NVIC_ENABLE_IRQ(IRQ_TEMPERATURE_PANIC);[/COLOR]
}

PROGMEM void startup_late_hook(void) {
	jj2 = micros();
	kk2 = millis();
	delay( 100 );
	while (millis() < 280) {
		if ( ems > 40 ) {
			ems = 0;
			ii2++;
			digitalWriteFast( LED_BUILTIN, !digitalReadFast( LED_BUILTIN ) );
		}
	}
}

PROGMEM void startup_reset_hook(void) {
	MY_startup_reset_SRSR = startup_reset_SRSR;
}
#ifdef __cplusplus
} // extern "C"
#endif
void ShowTimes() {
	char szWhen[2][20] = { "Start setup()", "setup() was" };
	static int iiW=0;
#if defined(__IMXRT1062__)
	Serial.printf("\n F_CPU=%u", F_CPU_ACTUAL );
	Serial.printf( "\tdeg  C=%u\n" , (uint32_t)tempmonGetTemp() );
#endif
	Serial.printf("\n%s:: E_HOOK us>>%u [ii3#>>%u] E_hook millis is %u", szWhen[iiW], jj3, ii3, kk3);
	Serial.printf("\n%s:: L_HOOK us>>%u [ii2#>>%u] L_hook millis is %u", szWhen[iiW], jj2, ii2, kk2);
	Serial.printf("\n%s:: @us>>%u [static ii ms>>%u] setup millis is %u", szWhen[iiW], jj, ii, kk);
	Serial.printf("\n@micros>>%u [ms>>%u] Time is %s\n", micros(), millis(), ctime(&tt));
	iiW=1;
}

void setup() {
	jj = micros();
	kk = millis();
	while (millis() < 300) {
		if ( ems > 20 ) {
			ems = 0;
			digitalWriteFast( LED_BUILTIN, !digitalReadFast( LED_BUILTIN ) );
		}
	}
	Serial.begin(115200);
	while (!Serial && millis() < 4000 );
	Serial.println("Compile Time:: " __FILE__ " " __DATE__ " " __TIME__);
	Serial.print( "MY_startup_reset_SRSR == " );
	Serial.println(MY_startup_reset_SRSR , HEX);
	tt = rtc_get();
	ShowTimes();
}
uint32_t cnt;
uint32_t ltmp = 0;
void loop() {
	tt = rtc_get();
	while ( tt + 10 >= rtc_get() ) {
		jj = micros();
		if (TempAlarm)
			ShowTempAlarm();
		if ( ltmp < (uint32_t)tempmonGetTemp() ) {
			ltmp = (uint32_t)tempmonGetTemp();
			Serial.printf( "%u° " , (uint32_t)tempmonGetTemp() );
		}
	}
	ltmp = (uint32_t)tempmonGetTemp();
	Serial.printf("\n@micros>>%u [ms>>%u] Time is %s", jj, millis(), ctime(&tt));
	Serial.printf( "%u° " , (uint32_t)tempmonGetTemp() );

	++cnt;
	if ( !(cnt % 10) ) ShowTimes();
}

void ShowTempAlarm() {
	float temperature = tempmonGetTemp();
	tempmon_Stop();
	if (TempAlarm && (temperature - panicAlarmTemp >= 0) ) {
		Serial.printf("\tPANIC Temperature [%u]  Alarm %.1f. \r\n", panicAlarmTemp, temperature);
		TempAlarm = false;
		panicAlarmTemp++;
		NVIC_ENABLE_IRQ(IRQ_TEMPERATURE_PANIC);
	}
	if (TempAlarm && ((temperature - highAlarmTemp > 0)) && (temperature - panicAlarmTemp < 0) ) {
		Serial.printf("\tHIGH Temperature [%u] Alarm %.1f. \r\n", highAlarmTemp, temperature);
		TempAlarm = false;
		highAlarmTemp++;
		NVIC_ENABLE_IRQ(IRQ_TEMPERATURE);
	}
	if (TempAlarm && (temperature - lowAlarmTemp < 0)) {
		Serial.printf("LOW Temperature [%u] Alarm %.1f. \r\n", lowAlarmTemp, temperature);
		TempAlarm = false;
		lowAlarmTemp--;
		NVIC_ENABLE_IRQ(IRQ_TEMPERATURE);
	}
	tempmon_Start();
}
 
Last edited:
Oh - and some direction toward a conclusion on TempMon awareness/usage:: …. It seems the current TempMon.c code is working and good as is, a user can use _isr()'s to trap and respond to temp issues with the given tempmon_init(); interface in place - and if they fail to do that and the CPU goes into PANIC mode - it does a hard HALT. This should not require any change to Startup,c with added CallBack() as the _isr()'s exist.

I don't see the CPU saying when it shutdown for over temp when it is restarted, but when it satisfies the "4X" PANIC test the MCU is HALTed - with triggered _isr()'s on any single PANIC temp read, and on HIGH or LOW temp it fires an _isr().

The code posted #3679 shows how those _isr()'s can be attached and enabled for user handling. Though as noted the artificial thresholds in place are ignored for subsequent user notice and resulting SPEW that brings.

Proper handling might include dropping FCPU_ACTUAL - or otherwise signaling the loop() to reduce MCU loading until cooling is improved?

If there were a runtime way to adjust the threshold values perhaps when HIGH temp is reached the LOW temp could be set somewhere below that and the MCU speed/load throttled down until the LOW_isr() fires then the LOW threshold could go DOWN and the throttling could be removed without having to add constant monitoring in the loop().

Sketch above does not do anything but watch RTC seconds and temp - so not processor intensive.

And a correction I did use the startup_early_hook(void) - to enable the _isr()'s for TempMon and they should be active and responsive before ever entering setup().
 
Decided to see how many _isr()'s came in - with the print silenced they were left disabled - so re-enabled them and counted them for display.

The PANIC_isr() was commented out in code I found - and shared a common Boolean, the temp as read was over PANIC temp and reported in the common test code - but that _isr() had not actually fired.

When differentiation was added in print of alarms (High/Low) share an _isr() vector - now PANIC was unique it does fire with enough warning to print before the T4 locks - seems that is why it was commented out?

Waited for it to PANIC once more with IDE SerMon - because ODDLY it no longer goes missing on TyComm - but disaperates and closes the text window without a trace. SerMon IDE just froze as expected - but before it could print - because I re-enabled the _isr too quickly so it never got a chance.

Again with PANIC_isr() disabled and set_arm_clock(300000000); in the _isr() {effect unsure} … it never gets a print out - not sure if LED goes HIGH or not the instant it has before going offline.

Need to enable and hook up Serial4 debug -
 
Tried the "switch off" via software - seems to work, the LED on the new board is off, too, and the pressing power-button for power-on works.
Maybe we can add a little macro to the core?
Code:
#define SWITCH_CORE_OFF {SNVS_LPCR |= (1<<6);}
Or, maybe, as a function (should help the compiler whitch optimizing, because of "noreturn") - not sure what is more efficient.
Code:
PROGMEM __attribute__((noreturn))
void switch_core_off(void) {SNVS_LPCR |= (1<<6);exit(0);}
However, i've not measured the current consumption so far - is there is a difference to the power-switch?
 
Last edited:
Update on Red Alert #3662...

I have done a lot of tests today. There is something VERY ODD about GPT2. I think its a design fault in the chip itself (either that or I am not understanding the way it is supposed to work).

I have managed to "go backwards" and change the high frequency clock back to 24 MHz from 150 MHz, but to do this, I have had to write specifically to register CCM_CSCMR1 and set bit6 to a '1'. It did not reset by default, which I would have expected.

I have also run the sketch https://github.com/manitou48/teensy4...er/gpt_isr.ino successfully and got it to print in increments of 20,000 in Serial Monitor. This is another very useful test for GPT2, for it proves the selected clock rate to be back at 24 MHz.

From these two facts, I don't think that I broke anything in changing clock speed to 150 MHz.

But the ODD THING about GPT2 is...
... that you write to "Compare 1" register OCR1 when you want to toggle the output timing for "Compare 3". In fact writing to OCR3 (the Compare 3 register) does not seem to do anything in terms of controlling "Compare 3" timing output. The same is true for "Compare 2" - you need to write to "Compare 1" to control the width of a toggle pulse on the "Compare 2" output.

This behaviour seems at odds with the diagram on RM page 3074 - the GPT Block Diagram. This shows all three Compare outputs to be independant. Why should there be any interaction in "Compare 3" performance by changing the value held in "Compare 1" register OCR1 ??? (Ditto for "Compare 2" also).

===

This issue is important when you want to bring out the hardware signal from either "Compare 3" or "Compare 2" as a square wave.

If you include the setup line (IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07 = 8) then the output "Compare 3" becomes available at Teensy4 pin 16. By setting bits 28,27,26 in GPT2_CR to "001", then the output will toggle as a square wave. (By the way, you can also bring "Compare 2" output to Teensy4 pin 17 by using the statement IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06 = 8, and you need to change bits 25,24,23 of GPT2_CR).

But the period/frequency of this square wave is not determined by the "Compare 3" register OCR3. It is determined solely by "Compare 1" OCR1. I have tested this as an observation on my scope.

Another quirk is the fact that you must write SOMETHING into the "Compare 3" register, or else you will not get a square wave at all. But the value you write in there seems to be academic - it has no bearing on the width of the output mark/space durations.

This certainly looks to me like a design fault with the microcode in the chip itself.

What would be useful is if someone else could check out this behaviour, and prove that it behaves the same in their beta T4 as it does mine. Preferably too, someone who has not altered the high speed clock to 150 MHz. It would be great to show that this has not affected my findings.
 
... And by the way, the value you need to put into "Compare 3" OCR3 or "Compare 2" OCR2 to get the square wave appear must be less than or equal to the value that you put into "Compare 1" OCR1. You can use a value of zero in these two registers, but you cannot omit them. If you use a value greater than "Compare 1" OCR1, then you won't get the square wave.
 
... And by the way, the value you need to put into "Compare 3" OCR3 or "Compare 2" OCR2 to get the square wave appear must be less than or equal to the value that you put into "Compare 1" OCR1. You can use a value of zero in these two registers, but you cannot omit them. If you use a value greater than "Compare 1" OCR1, then you won't get the square wave.

can you provide one or more sketches that demonstrate the strange GPT2 behavior? Does the "compare 3" interrupt fire, independent of toggling the compare3 output pin? The core hardware/teensy/avr/cores/teensy4/startup.c explicitly sets CCM_CSCMR1 to use 24mhz oscillator during start up, yes?
CCM_CSCMR1 = (CCM_CSCMR1 & ~CCM_CSCMR1_PERCLK_PODF(0x3F)) | CCM_CSCMR1_PERCLK_CLK_SEL;
Have you printed out some of the registers of interest: CCM_CSCMR1, GPT2_CR, GPT2_IR, GPT2_OCR3


EDIT: i have confirmed strange counts when trying to use OCR2 or OCR3 for the interrupt compare. I only get 1 interrupt. To get proper ISR counts for OCR2 or OCR3, I have to put the same compare value in OCR1. Behavior is same on either GPT1 or GPT2

EDIT2: strange behavior may be a "feature", 1060 manual 51.5.1.1 says For the other two compare channels, when the compare event occurs the counter is not reset. I don't know if there is a way to zero the counter in the ISR ??
 
Last edited:
Adafruit_gfx, adafruit_ili9341, adafruit_st7735 and st7735_t3

None of these compile on T4...

I did some changes to Adafruit_gfx - https://github.com/KurtE/Adafruit-GFX-Library/tree/T4_Beta

That I was able to build and run graphicstest example app on T4 using PJRC ILI9341 display using pins (CS=10, DC=9, reset=23) ...

Anyway if anyone wishes to try it out before I try issuing a PR to Adafruit that would be great.

Hi All,
I just received my Teensy 4.0 Beta2 unit the other day.
I was able to compile and run the Adafruit SSD1306 library for an SSD1306 128x32 I2C OLED display.
Its using pins SCL0(19) and SDA0(18)
I used KurtE's modified GFX library referred to in Post #3349
https://github.com/KurtE/Adafruit-GFX-Library
DSC02453.jpg
--Wozzy

Edit: It also works with Wire1 on SCL1(16) and SDA1(17)
Not tried with Wire2
 
Last edited:
@TelephoneBill :: RE clocks - seems this was linked the other day for CLOCK ref info from @mjs513 :: https://github.com/mjs513/WIP/tree/master/T4%20helpers
>> May have good coverage or get expansion?

@Wozzy:: SSD1306 is fun and easy to connect! - Nice it works with the KurtE AdafruitGFX as I think they did an update based on his changes? I have the square version tested before - but not with the latest GFX

@mjs513 :: simple i2c SSD1306 is what I mentioned for your breakout board 'open space' when TFT (other shield) isn't in place - long or square - just 4 pins - quick display and usable debug text area. Or other i2c(2) add on - maybe AdaF short headers.
 
@Wozzy:: SSD1306 is fun and easy to connect! - Nice it works with the KurtE AdafruitGFX as I think they did an update based on his changes? I have the square version tested before - but not with the latest GFX

@defragster, Thanks for letting me know about the update.

I can confirm that the SSD1306 for I2C works under the latest Adafruit GFX Library downloaded today: https://github.com/adafruit/Adafruit-GFX-Library
 
Here is a sketch which illustrates the quirky behaviour of GPT2 Compare3 and Compare2.

Notice that it is only GPT2_OCR1 that determines the period/frequency of the output sq wave on a scope.

Any value in GPT2_OCR3 (or GPT2_OCR2 when uncommented) between zero and the exact value in OCR1 will still allow a sq wave output, but a value just one unit larger will stop it. Also, those values don't affect the frequency.

I think that the T4 microcode has an error and that NXP have enabled the wrong register for OF3 and OF2. Looks like they have enabled OCR1 for OF3 and OF2, where it should be OCR3 and OCR2.

Code:
//TESTT4005 - GPT2 SQ WAVE TEST PROGRAM for T4
//============================================
//Author: TelephoneBill
//Date: 13 JUL 2019
//NOTES: Using GPT2 as timer. Using GPT Compare3 (T4 pin 16), Compare2 (T4 pin 17) as sq wave outputs.
//Compare3 is engaged when running. Remove "comment lines" for GPT2_OCR2 = 0; then Compare2 will also be running.

//definitions
bool TestCount, TestLoop;
byte Byte1;
volatile uint32_t ISRTicks = 0, LastISRTicks = 0, Save1GPT2SR, Save2GPT2SR;

//SETUP CODE
//==========
void setup() {
  //initialise general hardware
  Serial.begin(115200);                       //setup serial port
  pinMode(13, OUTPUT);                        //pin 13 as digital output
  FlashLED(4);                                //flash four times, just for confident startup

  //configure clocks for GPT modules
  CCM_CCGR0 |= 0x0F000000;                    //enable clocks to GPT2 (CG12,CG13)
  CCM_CCGR1 |= 0x00F00000;                    //enable clocks to GPT1 (CG10,CG11)

  //configure GPT1 for test
  GPT2_CR = 0;                                //clear the control register, FRR = 0 means restart after Compare
  GPT2_SR = 0x3F;                             //clear all prior status
  GPT2_PR = 0;                                //prescale register set divide by 1
  GPT2_CR |= GPT_CR_CLKSRC(1);                //clock selection
  GPT2_CR |= GPT_CR_ENMOD;                    //reset count to zero before enabling
  GPT2_CR |= GPT_CR_EN_24M;                   //enable the 24 MHz clock option
  GPT2_CR |= 0x04800000;                      //Compare3 = toggle mode, Compare2 = toggle mode
  
  //Note - only value in GPT2_OCR1 affects the frequency of the sq wave on Compare3 and Compare2
  GPT2_OCR1 = 0x00002EE0;                     //Compare1 value (0x00002EE0 gives 1 KHz @ 24 MHz, 0x000493E0 gives 500 Hz @ 24 MHz)
  //GPT2_OCR2 = 0;                              //Compare2 value - uncomment to see sq wave on pin 17
  GPT2_OCR3 = 0;                              //Compare3 value - anything from 0 to 0x00002EE0 works. 0x00002EE1 does not work.
  GPT2_IR = 0x00000004;                       //enable interrupt for Compare flag 
  
  GPT2_CR |= GPT_CR_EN;                       //enable GPT2 counting

  //configure Teensy pin 16 as Compare3 output, configure Teensy pin 17 as Compare2 output
  IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07 = 8;    // GPT2 Compare3 is now on pin 16
  IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06 = 8;    // GPT2 Compare2 is now on pin 17
  
  //enable GPT1 interrupt within NVIC table
  attachInterruptVector(IRQ_GPT2, GPT2_isr);  //declare which routine performs the ISR function
  NVIC_ENABLE_IRQ(IRQ_GPT2);
}


//ISR ROUTINE FOR GPT1
//====================
//FASTRUN puts this code into RAM to run fast on T3
//(but maybe not required for T4 using TCM memory)
FASTRUN void GPT2_isr(void) {
  digitalWriteFast(13, 1);
  Save1GPT2SR = GPT2_SR;
  ISRTicks++;
  GPT2_SR = 0x00000004;                       //reset the interrupt flags in status register
  Save2GPT2SR = GPT2_SR;
  asm volatile("dsb");
}


//MAIN LOOP
//=========
void loop() {
  //call KeyInput() routine
  KeyInput();                                 //type "G" to see values of GPT2_SR before and after interrupt flag reset
  if (ISRTicks>LastISRTicks) {
    LastISRTicks = ISRTicks;
    digitalWriteFast(13, 0);                  //used to reset LED. Timing from sq wave edge to LED edge indicates ISR latency (maybe? depends)
  }
}

//SUBROUTINES
//===========
//Flash LED routine
void FlashLED(int m) {
  for (int n=0;n<m;n++) {
    digitalWriteFast(13, 1);          //set pin 13 high
    delay(100);
    digitalWriteFast(13, 0);          //set pin 13 low
    delay(100);
  }
}

void KeyInput() {
  //process any keystrokes available
  if (Serial.available()>0) {
    //read the incoming byte
    Byte1 = Serial.read();
    if (Byte1>0x20) {
      switch (Byte1) {
      case 'G':  //print the saved GPT2_SR register values
        //task goes here...
        Serial.print("Save1GPT2SR = "); Serial.println(Save1GPT2SR);       
        Serial.print("Save2GPT2SR = "); Serial.println(Save2GPT2SR);       
        break;
      }
    }
  }
}
 
Here is a sketch which illustrates the quirky behaviour of GPT2 Compare3 and Compare2.

Notice that it is only GPT2_OCR1 that determines the period/frequency of the output sq wave on a scope.

Any value in GPT2_OCR3 (or GPT2_OCR2 when uncommented) between zero and the exact value in OCR1 will still allow a sq wave output, but a value just one unit larger will stop it. Also, those values don't affect the frequency.

I think that the T4 microcode has an error and that NXP have enabled the wrong register for OF3 and OF2. Looks like they have enabled OCR1 for OF3 and OF2, where it should be OCR3 and OCR2.

Note, i added some edits to my post #3685 that suggests for simple compare interrupts, OCR1 differs from OCR2 and OCR3 (in restart mode, FRR = 0) ref 51.5.1.1
 
Last edited:
EDIT: i have confirmed strange counts when trying to use OCR2 or OCR3 for the interrupt compare. I only get 1 interrupt. To get proper ISR counts for OCR2 or OCR3, I have to put the same compare value in OCR1. Behavior is same on either GPT1 or GPT2

EDIT2: strange behavior may be a "feature" manual 50.5.1.1 says For the other two compare channels, when the compare event occurs the counter is not reset. I don't know if there is a way to zero the counter in the ISR ??

Thankyou for your diligence, and well spotted on the comment 51.1.1 and 51.1.2. I had missed that.

Looks like you are correct - it is a "feature". On the diagram of Fig 51-1, it too shows a line only from Compare1 into FRR "AND" gate to reset the timer. Could this be a "feature" where the manual is catching up with what actually happened on the silicon?

This certainly "threw me out" when used to the toggle behaviour of T3x. I think it will to others :)
 
In order to compare Teensy processor speeds I ported a couple of CPU-intensive programs to T4b2.
The first is a ray-tracing program which does a *lot* of single precision floating point calculations to generate a 512x512 PPM-format image on the audio board's uSD card. I originally had it running on a T3.1 which took all night to generate one image. I have now run it on T3.6 and T4b2.
Code:
 96MHz T3.1 took 8 hours and 53 minutes.
180MHz T3.6 took 42.6 minutes
396MHz T4b2 took 3.5 minutes

The second program is one I wrote which I call ASAP - A Simple Algebraic Parser - which uses double precision floating point. The parser generates a Reverse Polish Notation string from an algebraic expression which can include functions and variables as well as arithmetic operators. The RPN string can then be evaluated. From that I developed code to do numeric integration using various methods, one of which uses Simpson's Rule. As a "benchmark" of sorts I evaluate two integrals and time how long they take.
The first is the integral from zero to pi of the expression sin(x*x) using 66640 intervals.

Code:
 96MHz T3.2 - 4.9 secs
180MHz T3.6 - 1.7 secs
396MHz T4b2 - 187 milliseconds

The second is the integral from -1 to +1 of exp(-x*x/2)/sqrt(2*pi) using 500 intervals.

Code:
 96MHz T3.2 - 45.4 ms
180MHz T3.6 - 15.7 ms
396MHz T4b2 -  2.0 ms

Pete
 
Re post #3691 on GPT2 Compare behaviour, once the "penny" has dropped, then the design implemented becomes much more comprehensible.

The three Compare channels are not completely independant in "function", but may be so in "time". An example might be in TOGGLE mode, where Compare1 could be used to define a certain sq wave, and then Compare2 and Compare3 could be used to create different "phases" of the same frequency. It may be possible to create a 3-phase signal (each at 120 degrees w.r.t. each other), but in T4 we only have Compare2 and Compare3 out on ALT8 to pins 17 and 16. Maybe the XBAR can help out here to get at Compare1's GPT2 output? Something to investigate.

I am happy that this behaviour is not chip damage due to switching to 150 MHz. A co-incidence that I had done this just prior to these GPT2's discoveries. Phew, that's a relief!
 
Kurt, Paul,

in SPI.h, we have:
Code:
    // If SPI is to used from within an interrupt, this function registers
    // that interrupt with the SPI library, so beginTransaction() can
    // prevent conflicts.  The input interruptNumber is the number used
    // with attachInterrupt.  If SPI is used from a different interrupt
    // (eg, a timer), interruptNumber should be 255.
    void usingInterrupt(uint8_t n) {
        if (n >= CORE_NUM_DIGITAL) return;
        volatile uint32_t *gpio = portOutputRegister(n);
        switch((uint32_t)gpio) {
            case (uint32_t)&GPIO1_DR:
                usingInterrupt(IRQ_GPIO1_0_15);
                usingInterrupt(IRQ_GPIO1_16_31);
                break;
            case (uint32_t)&GPIO2_DR:
                usingInterrupt(IRQ_GPIO2_0_15);
                usingInterrupt(IRQ_GPIO2_16_31);
                break;
            case (uint32_t)&GPIO3_DR:
                usingInterrupt(IRQ_GPIO3_0_15);
                usingInterrupt(IRQ_GPIO3_16_31);
                break;
            case (uint32_t)&GPIO4_DR:
                usingInterrupt(IRQ_GPIO4_0_15);
                usingInterrupt(IRQ_GPIO4_16_31);
                break;
        }
    }
This needs to be fixed, because (a) we are using GPIO6..9 and (b) these errors in GCC 8 (I guess, the older GCC do not recognoize this and can produce wrong code)
Code:
"C:\\Arduino\\hardware\\teensy/../tools/arm8/bin/arm-none-eabi-g++" -c -O2 -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=147 -DARDUINO=10809 -DF_CPU=600000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH "-Ic:\\temp\\arduino_build_719683/pch" "-IC:\\Arduino\\hardware\\teensy\\avr\\cores\\teensy4" "-IC:\\Arduino\\hardware\\teensy\\avr\\libraries\\Audio" "-IC:\\Arduino\\hardware\\teensy\\avr\\libraries\\SPI" "-IC:\\Arduino\\hardware\\teensy\\avr\\libraries\\SD" "-IC:\\Arduino\\hardware\\teensy\\avr\\libraries\\SerialFlash" "-IC:\\Arduino\\hardware\\teensy\\avr\\libraries\\Wire" "c:\\temp\\arduino_build_719683\\sketch\\PT8211Sine.ino.cpp" -o "c:\\temp\\arduino_build_719683\\sketch\\PT8211Sine.ino.cpp.o"
In file included from C:\Arduino\hardware\teensy\avr\cores\teensy4/core_pins.h:32,
                 from C:\Arduino\hardware\teensy\avr\cores\teensy4/wiring.h:38,
                 from C:\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:45,
                 from c:\temp\arduino_build_719683\pch\Arduino.h:6:
C:\Arduino\hardware\teensy\avr\libraries\SPI/SPI.h: In member function 'void SPIClass::usingInterrupt(uint8_t)':
C:\Arduino\hardware\teensy\avr\cores\teensy4/imxrt.h:4967:33: error: expression '((IMXRT_REGISTER32_t*)1075544064)->IMXRT_REGISTER32_t::offset000' has side-effects
 #define GPIO1_DR   (IMXRT_GPIO1.offset000)
                    ~~~~~~~~~~~~~^~~~~~~~~~
C:\Arduino\hardware\teensy\avr\libraries\SPI/SPI.h:1123:20: note: in expansion of macro 'GPIO1_DR'
    case (uint32_t)&GPIO1_DR:
                    ^~~~~~~~
C:\Arduino\hardware\teensy\avr\cores\teensy4/imxrt.h:4966:24: error: 'reinterpret_cast<IMXRT_REGISTER32_t*>(1075544064)' is not a constant expression
 #define IMXRT_GPIO1  (*(IMXRT_REGISTER32_t *)0x401B8000)
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Arduino\hardware\teensy\avr\cores\teensy4/imxrt.h:4967:21: note: in expansion of macro 'IMXRT_GPIO1'
 #define GPIO1_DR   (IMXRT_GPIO1.offset000)
                     ^~~~~~~~~~~
C:\Arduino\hardware\teensy\avr\libraries\SPI/SPI.h:1123:20: note: in expansion of macro 'GPIO1_DR'
    case (uint32_t)&GPIO1_DR:
                    ^~~~~~~~
C:\Arduino\hardware\teensy\avr\cores\teensy4/imxrt.h:4967:42: error: conversion from pointer type 'volatile uint32_t*' {aka 'volatile long unsigned int*'} to arithmetic type 'uint32_t' {aka 'long unsigned int'} in a constant expression
 #define GPIO1_DR   (IMXRT_GPIO1.offset000)
                                          ^
C:\Arduino\hardware\teensy\avr\libraries\SPI/SPI.h:1123:20: note: in expansion of macro 'GPIO1_DR'
    case (uint32_t)&GPIO1_DR:

....
In interrupt.c is a similar constuction.
 
I'd suggest to extend this struct in pins_arduino.h
Code:
struct digital_pin_bitband_and_config_table_struct { // not really bitband, old name from Teensy3
    volatile uint32_t *reg;
    volatile uint32_t *mux;
    volatile uint32_t *pad;
    uint32_t mask;
};
with a new value "portnum" with values 0..3 (+offset 3 for 1062, 0 for 1052).
It would simplify many things - and GCC has not to compare (-> register loads) registersadresses in functions like these (in SPI.h and interrupt.c)
 
Last edited:
Hi @Frank B and @Paul - These are parts of SPI and Interrupt that I have not touched. Sort of beyond my pay grade ;)

But you might try out what you suggested and see if it works, and does not adversely effect current GCC builds... Then I think Paul would probably take a PR...
 
Sorry, haven't had much time lately to keep up.

Generally I'm ok with adding more fields to the hardware description structs which are (or should be) stored in PROGMEM.
 
@PaulStoffregen (@mjs513, @defragster) - As has been mentioned in the thread: https://forum.pjrc.com/threads/5573...3-x-and-beyond?p=210184&viewfull=1#post210184

There is a sketch that if include @defragsters debug library the app (uncannyeyes) runs. But without it, the app dies and disables USB. Earlier with this one, after that happened I could not reprogram either with simple push button. But later did get it to recover...

When I was debugging it earlier, If I added Serial.print at start of setup(), even waiting: while (!Serial && millis()< 5000) ; Serial.begin(115200);

And if I put in a delay... still the Serial terminal never was valid nothing printed... And then later Message from windows saying Serial device is invalid...


A few posts up from there @mjs513 posted the sketch.

Wondering in cases like this, Would posting a zip file of the build directory help. Which contains the hex file, elf file, list file,

Some different outputs from objdump? But one can get these from using the objdump installed with arduino on the elf file...
 
@Paul - I'm editing in place for now p#361 to get stable repro steps : https://forum.pjrc.com/threads/55735-ILI9488_t3-Support-for-the-ILI9488-on-T3-x-and-beyond?p=210184&viewfull=1#post210184

Will update here when I can see that clearly.

re KurtE p#3699:
@PaulStoffregen (@mjs513, @defragster) - As has been mentioned in the thread: https://forum.pjrc.com/threads/55735...l=1#post210184

There is a sketch that if include @defragsters debug library the app (uncannyeyes) runs. But without it, the app dies and disables USB. Earlier with this one, after that happened I could not reprogram either with simple push button. But later did get it to recover...
 
Status
Not open for further replies.
Back
Top