Teensy 4.0 First Beta Test

Status
Not open for further replies.
ADAFTUIT MOTOR SHIELD V2 LIBRARY

Ok. I picked up another Adafruit v2 motorshield that I modified for 3.3v and hooked up a stepper motor. The shield is unique in that it uses I2C for the control of the motors so I didn't doubt that they would work. Now have figure where that other library Accel/.Stepper came from so I can test that one.

EDIT: Accel/Stepper Library
Found the PJRC page discussing the hardware. It references the Pololu A4988 Drivers unfortunately don't have any of them. I do have a Adafruit TB6612 driver. Does anyone know if I can use this as a substitute?
 
Last edited:
Hi Frank,

It would be great to take a look at your code... I have some stuff started, but not yet tested.

My library can (or at least used to, but I have not tested it out for awhile), do autorefresh...

That is my functions are:
Code:
	void	setFrameBuffer(uint16_t *frame_buffer);
	uint8_t useFrameBuffer(boolean b);		// use the frame buffer?  First call will allocate
	void	freeFrameBuffer(void);			// explicit call to release the buffer
	void	updateScreen(void);				// call to say update the screen now. 
	bool	updateScreenAsync(bool update_cont = false);	// call to say update the screen optinoally turn into continuous mode. 
	void	waitUpdateAsyncComplete(void);
	void	endUpdateAsync();			 // Turn of the continueous mode fla
	void	dumpDMASettings();
The code only allocates a frame buffer if ask to use one: useFrameBuffer called with TRUE. You can turn on and off as my test code does.
You can in theory pass in frame buffer, so for those who wanted everything preallocated, they call allocate it and then pass in pointer.

The: updateScreen()
does a one shot update screen, which is the same as: writeRect from Frame buffer to screen. Does not use DMA.

Then there is the updateScreenAsync - which can either update the screen once using DMA or can do continuous, where you can then use the endUpdateAsync to turn off and you can call wait to wait until a dma operation has completed...

My work flow when using this, is either just the updateScreen Or sometimes I use the Async one shot and then continue to do whatever computations are needed and then call wait for the last update to complete before I then start updating my display (frame buffer...) Not sure if that makes sense.

Side Note:

Currently if I try to define static buffer like:
Code:
uint16_t tft_frame_buffer[ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT];

The link fails:
Code:
Compiling library "SPIN"
Using previously compiled file: C:\Users\kurte\AppData\Local\Temp\arduino_build_162945\libraries\SPIN\SPIN.cpp.o
Compiling core...
Using precompiled core: C:\Users\kurte\AppData\Local\Temp\arduino_cache_734367\core\core_teensy_avr_teensy4b_usb_serial,opt_o2std,keys_en-us_86f260b7ebc565879a7e32f9efe1770a.a
Linking everything together...
"D:\\arduino-1.8.8\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-gcc" -O2 -Wl,--gc-sections,--relax "-TD:\\arduino-1.8.8\\hardware\\teensy\\avr\\cores\\teensy4/imxrt.ld" -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -o "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945/Kurts_ILI9341_t3n_FB_and_clip_tests.ino.elf" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\sketch\\Kurts_ILI9341_t3n_FB_and_clip_tests.ino.cpp.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\libraries\\ili9341_t3n\\ILI9341_t3n.cpp.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\libraries\\ili9341_t3n\\glcdfont.c.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\libraries\\ili9341_t3n\\ili9341_t3n_font_Arial.c.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\libraries\\ili9341_t3n\\ili9341_t3n_font_ArialBold.c.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\libraries\\SPI\\SPI.cpp.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945\\libraries\\SPIN\\SPIN.cpp.o" "C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945/..\\arduino_cache_734367\\core\\core_teensy_avr_teensy4b_usb_serial,opt_o2std,keys_en-us_86f260b7ebc565879a7e32f9efe1770a.a" "-LC:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_162945" -larm_cortexM7lfsp_math -lm -lstdc++
d:/arduino-1.8.8/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: address 0x200302c0 of C:\Users\kurte\AppData\Local\Temp\arduino_build_162945/Kurts_ILI9341_t3n_FB_and_clip_tests.ino.elf section `.bss' is not within region `DTCM'

d:/arduino-1.8.8/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: address 0x200302c0 of C:\Users\kurte\AppData\Local\Temp\arduino_build_162945/Kurts_ILI9341_t3n_FB_and_clip_tests.ino.elf section `.bss' is not within region `DTCM'

collect2.exe: error: ld returned 1 exit status
Maybe need some qualifier now like DMAMEM?
 
I've sent you a Mail.. could have posted it here too, it was less than expected :)
Yes, you need DMAMEM - or just use malloc. The heap is in OCRAM now - like DMAMEM.

Good night.
 
Paul's been a bit under the weather the last day or two, so development progress has slowed down while he tries to rest up and not get any worse.

Paul, any news RE:Audio ? Or are you working on something ?
I'd try audio, then...
 
Paul's been a bit under the weather the last day or two, so development progress has slowed down while he tries to rest up and not get any worse.

Hope he feels better soon - just got over a something that kick my you know what - tell him get lots of rest and drink lots of fluids. And feel better soon.
 
@KurtE

Ok that got it - used wrong branch the ding bat that i am. Anyway now it works like a charm. Just for comparisons at this point i updated the benchmark table that i generated earlier, post #827. Big difference in most cases.

Code:
                         T3.5(120)                   T4
Benchmark                             Time (microseconds)
                                                           PODF(2)       PODF(6)      _t3n
Screen fill              993332           885880           888130        993390       245580
Text                     59506            43820            44620         48940        11680
Lines                    551647           416280           424020        464270       68780
Horiz/Vert Lines         81940            72440            72680         81230        20110
Rectangles (outline)     52453            46120            46300         51700        12810
Rectangles (filled)      2061753          1838640          1843310       2061770      504870
Circles (filled)         252396           208710           211020        233870       77500
Circles (outline)        240152           182130           184900        203190       63140
Triangles (outline)      124360           94820            96410         105790       16500
Triangles (filled)       683284           597780           600630        670140       168510      
Rounded rects (outline)  109180           86970            87990         97200        27860
Rounded rects (filled)   2055773          1828310          1833510       2050110      551660
Rectangles (filled) FB                                                                51800
Rounded rects (filled) FB                                                             55210
Looks like your trickery worked !

What is the clock setting in your table for first T4 column? I thought default was PODF(6)??
 
Maybe Ethernet? I just tried to compile Ethernet udpntp example, i get compile errors, undefined reference to `vtable for IPAddress', but I have other domestic chores in the next few hours ...

OK, got Ethernet (wiznet 5500) to work on Teensy 4. To eliminate vtable error had to copy teensy3/IPAddress.cpp to teensy4/. Here are my results from beta7 with Kurt's SPI FIFO lib. Speed of wiznet Ethernet will be limited to MCU SPI clock rate. Here are some results measuring time to write/read 1024 bytes to wiznet buffer area. T4 SPI peripheral clock is running at 528/7 MHz, so max SPI speed is 37.5 MHz.
Code:
      LPSPI4_CCR 204 12.571 MHz   DBT 2
      write 700 us mbs 11.70
      read 690 us  mbs 11.87
      wrt/rd errors 0

      LPSPI4_CCR 4 12.571 MHz    DBT 0
      write 670 us mbs 12.23
      read 670 us  mbs 12.23
      wrt/rd errors 0

      LPSPI4_CCR 2 18.857 MHz
      write 460 us mbs 17.81
      read 470 us  mbs 17.43
      wrt/rd errors 0

      LPSPI4_CCR 1 25.143 MHz
      write 370 us mbs 22.14
      read 370 us  mbs 22.14
      wrt/rd errors 0

      LPSPI4_CCR 0 37.714 MHz
      write 290 us mbs 28.25
      read 290 us  mbs 28.25
      wrt/rd errors 0
I tested TCP client and server, UDP client and server, ping, ARP.
 
Last edited:
What is the clock setting in your table for first T4 column? I thought default was PODF(6)??
Default settings used for all PDOF(6) except for the column marked PDOF(2) was curious what kind of performance improvement we would see if it was changed.
 
Pull request completed for a micros() based on CycleCounter extension of millis() systick_isr :: github.com/PaulStoffregen/cores/pull/330 Looks to be about 30 added lines if anyone cares to check my work :)

New micros() does not disable nor restore interrupts and has resolution to the single us based on ARM_DWT_CYCCNT changes between systick_isr()

There is now a "#define MAGIC_VAL 5 // empiric start value syncs sig digits to millis()" to start the systick_isr. This was not needed before I did the last CORES sync before merging the code? Quite a puzzle to change to have the significant digits of millis() match - is that needed? They will diverge for every systick millis misses it will lose time - micros() will not as that accumulates in the CycCnt diff value - until it wraps? It could be changed to reset on each systick_isr - and it would vary by the delay in the interrupt?

The timing works out to be the about the same old and new: 100K micros. Took cycles# 3278637 .vs. 100K OLD micros. Took cycles# 3275656 <includes 10K for loop overhead in both>

Just updated for fear of _isr change not being caught - runs 1 clock cycle faster now:: 100K micros. Took cycles# 3166733 .vs. 100K OLD micros. Took cycles# 3276379

… comments … <edit> pull request updated to make test version based on Paul's feedback there and post #964 ...
 
Last edited:
@defragster - Sounds like great stuff. Will be great to have a millis that works that does not muck with interrupts! I have not looked at that part of the system yet, so probably not much help in questions, but hopefully others...
 
Testing since the post has completed the 4th wrap of micros() value. with no detected errors running and testing all return values for batches of 4096 milliseconds for all micros() to be sequential.
Updated PULL to add ccmicros and leave micros() unchanged for testing.

There seems to be times it will start up with odd offsets.
> systick_millis_count can start at ZERO when execution starts
> but the same can't be done for :: systick_cycle_count = ARM_DWT_CYCCNT until after it is started, and then has to wait for the first systick_isr to synchronize the two.
Something in the latest cores updates as I see them on my machine made a difference in the math to make that right.

As written CycCnt micros() will be absolute increments of :: systick_cycle_count += F_CPU_ACTUAL/1000;
And any missed systick_isr will be ignored ( for 7.1 seconds of loss ) and will be incorporated in math against that SCC :: ccdelta = ARM_DWT_CYCCNT - scc;
Perhaps it should be written to not do that but incorporate the 'jitter' and loss of systick_isr to stay in sync with millis() and that may make it correct across the startup?

Have made a ccelapsedMicros to test with as well - perhaps another with GPT1_CNT would help …

There is also perhaps the 'atomic' concern that I attempted to incorporate to allow for systick_isr to fire during the call to micros()

Recent days brings to mind a movie quote: 'This will not be over quickly. You will not enjoy this' <that is when she turns the tables>
 
FYI - looks like @Paul pulled in the current SPI changes both in core and SPI :D

Now back to playing with SPI and ILI and ...
 
Temperature Monitoring

With everything else going on, forgot to tell you all that since the incorporation of tempmon function in the core/startup that if you want to monitor the chip temp all you have to do is print the out of tempmonGetTemp(), its a float.
 
Temperature Monitoring

With everything else going on, forgot to tell you all that since the incorporation of tempmon function in the core/startup that if you want to monitor the chip temp all you have to do is print the out of tempmonGetTemp(), its a float.

Indeed it is in the CORES I have :: temp 46.588783 … which seems to be off from the GERMAN Fahrenheit by some odd F=(9/5)C+32 factor? It should read 115.9 :)
 
Funny = its degrees C. You need to do you own conversion :)

Mine typically starts out at about 36C and climbs and stabilizes around 48C under minimal load.
 
Hardwareserial addStorageForRead/Write should be called only one time.. i'd add some code to prevent a issues with a second/third... call
 
Hardwareserial addStorageForRead/Write should be called only one time.. i'd add some code to prevent a issues with a second/third... call

Make sure it resets that on .end or .begin - in case the user changes the buffer?

Time to build a wall... :rolleyes: ? (to protect the world against minority fahrenheit... )

Temperature knows no borders. Dropped mine 3+° with some liquid cooling - my (fluid filled) finger. Went from 48.55 to 45.28 - then back to 48.55-49.20 running a micros test.

To get micros from CycCnt it uses two volatile vars [local copies abbreviated smc and scc] from systick_isr() does this code make it interrupt safe to use both of them after testing them?
Code:
	do {
		smc = systick_millis_count;
		scc = systick_cycle_count;
	} while ( smc != systick_millis_count || scc != systick_cycle_count ); // repeat if systick_isr
 
Temperature knows no borders. Dropped mine 3+° with some liquid cooling - my (fluid filled) finger. Went from 48.55 to 45.28 - then back to 48.55-49.20 running a micros test.
Hey Tim,
Yeah - I did that test to (liquid cooling :) ) when I was playing with the standalone sketch - couldn't resist - I should have put the heat sink on it to see what would happen :)
 
Way more boring/trivial - but just doing this:
Code:
extern "C" void systick_isr(void)
{
	systick_cycle_count [B]= ARM_DWT_CYCCNT[/B];  // was > [U]+= F_CPU_ACTUAL/1000;[/U]
	systick_millis_count++;
	MillisTimer::runFromTimer();
}

Avoids a recurring division in systick_isr . And micros() will always track millis() [no need for _sync code _isr swap]- tracking includes its jitter on handling the _isr and jumps for lost counts. But for 1 MHz timing with 600 MHz CycCnt the jitter should go away in rounding error - i.e. more accurate than currently on T_3.6.

Now just need a sanity check on that code in post #971 is interrupt detect/safe
 
Code:
    do {
        smc = systick_millis_count;
        scc = systick_cycle_count;
    } while ( smc != systick_millis_count || scc != systick_cycle_count ); // repeat if systick_isr

I think, the "||" inside the while can be wrong, if an interrupt occurs inside the while()
But I can't help much with ldrex/strex or the gcc builtins for atomic accesses (<- can they be used for two variables, too?) - never used that.
ldrex/strex: (both inside core_cminstr.h)
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html
 
Code:
    } while ( smc != systick_millis_count || scc != systick_cycle_count ); // repeat if systick_isr

I think, the "||" inside the while can be wrong, if an interrupt occurs inside the while()
But I can't help much with ldrex/strex or the gcc builtins for atomic accesses (<- can they be used for two variables, too?) - never used that.
ldrex/strex: (both inside core_cminstr.h)
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html

That seems a valid catch Frank - depending on the order the _isr changes <chosen by the compiler> them - if the interrupt comes between tests for both completing. The result would be adding or losing 600,000 clock ticks for that one call of micros - i.e. +/- 1 ms?

Is there a way to control/prevent that other than disable interrupts? Web search found this on ldrex/strex_CLREX - not sure if that says _isr will break it or it will work there?

This has example code - but would need to introduce an ordered flag (non-blocking to _isr) variable to use it on as it only covers a single load instruction - and two values are needed. Micros() just needs to detect interrupt changing either before both are used together. <opps edit>: missed reading your 'doc' link for myself
 
Status
Not open for further replies.
Back
Top