Yes, this is possible.
A walk through, not.
Last edited by Frank B; 01-03-2021 at 02:31 PM.
Try this:
Not sure if the optimization plays a role - I used "fast". You'll see >250 Cycles difference (60Mhz vs. 133Mhz) for these RANDOM readsCode:PROGMEM const char lorem[]="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."; volatile char x; void setup() { while(!Serial); delay(10); unsigned long t = ARM_DWT_CYCCNT; for (int i = 0; i < 20; i+=1) x = lorem[i*8]; t = ARM_DWT_CYCCNT - t; Serial.println(t); Serial.println(x); } void loop() {}
Edit: it is a littly tricky to get around the cache AND the gcc optimization... therefore the funny loop.
Not sure if this is the best thread to ask this, but I have been having fun seeing what I can screw up![]()
Or more specifically trying out stuff using some new stuff like FS.h, LittleFS, SD, MTP... And playing around with how one might use some of this stuff, to see where maybe it makes sense to expand some of the stuff for example in FS.h.
Example suppose I wish have an MTP aware sketch, which for example suppose that the sketch maybe generates log files and the like and the program may be controlled by some form of configuration file.
What other things might I want?
a) I might want to know if MTP is connected and that there is an MTP session. Not sure exactly when the best trigger point is? On Start Session? Don't know at what granularity you may wish to know things.
Example if You have two storages installed, maybe you wish to know that the 2nd storage you added, if at least the top level of this storage has been enumerated or not...
b) You might want to know if the host PC updated anything as maybe you wish to reflect this on the Teensy. Example suppose your Teensy is running a sketch and maybe has a larger display like RA8875 running sort of a tablet sketch. Maybe one of the modes that sketch may run is showing your local file system and allow you to locally create new files, delete files... This is where that code needs to notify the host about the changes (some of the stuff I have been playing with). But likewise if the host deletes some files, you would like to know that to update your list on the screen...
Maybe you simply have some notification per storage, of has something changed?
c) Sort of part of b) but suppose you have a configuration file you store in your storage, that somehow controls your sketch, maybe a set of sound files or color for LEDS, or maybe a new python script to run...
How would I detect this? Suppose I have a file at the root of my storage called teensy.ini And I want to know when this file changes? How? On many systems there might be a file change notify you might setup?
But other times, you might at start up time read the file and remember the Modify Date of the file. And then later if you see that date has changed? Then you know you may need to do something...
So then I wondered, does our high level FS.h file know anything about dates? I don't think so. Should it? Obviously Fat File systems support dates, but not sure of our Interface? I do see in some of the SDFat system there are apis to print the date, but not sure if there are any to retrieve it? LittleFS, does it support dates? I did not notice any. Is it worth doing anything? My guess (default answer) Punt.
Thoughts? Maybe main brain is just wondering too much
Edit: Note: I mention this in this thread, as to see if we should extend any of the new features before the official 1.54 is released with FS.h, LittleFS, Hopefully MTP...
+1
And I like to see a doc and some examples how all this new things work, including the new FS.h
Tried that and saw the change with the clock:
Then did this:Code:T:\tCode\Memory\FlashMemSpeed\FlashMemSpeed.ino Dec 30 2020 12:56:41 1416 u T:\tCode\Memory\FlashMemSpeed\FlashMemSpeed.ino Dec 30 2020 13:00:54 1676 u
takes even longer but the ~250 offset is the same - though time in loop nearly doubles running backwards through FLASH string:Code:PROGMEM const char lorem[592] = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."; volatile char x; void setup() { while (!Serial && millis() < 4000 ); Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__); delay(10); unsigned long t = ARM_DWT_CYCCNT; for (int i = 0; i < 20; i += 1) x = lorem[591-(i * 8)]; t = ARM_DWT_CYCCNT - t; Serial.println(t); Serial.println(x); } void loop() {}
Then making the backward index '20' instead of 8 is more significant :: for (int i = 0; i < 20; i += 1) x = lorem[591-(i * 20)];Code:T:\tCode\Memory\FlashMemSpeed\FlashMemSpeed.ino Dec 30 2020 13:02:47 2986 m T:\tCode\Memory\FlashMemSpeed\FlashMemSpeed.ino Dec 30 2020 13:03:11 2627 m
It hits a SPACE so printed (BYTE) to see it was indeed '32' {that changes with index [591- ...]}:: Serial.println((byte)x);Code:T:\tCode\Memory\FlashMemSpeed\FlashMemSpeed.ino Dec 30 2020 13:08:11 6026 32 T:\tCode\Memory\FlashMemSpeed\FlashMemSpeed.ino Dec 30 2020 13:08:35 6897 32
Good example : that does easily show diff in time that the faster Program Flash can make. Even if just a 250 cycle wait.
If the loop is changed to just "for (int i = 0; i < 2; i += 1)" the diff of 250 goes away ... down to 3 cycles.
I've re-run coremark on the new GCC10.2.1 - still slower than GCC5.4.1 -O3 , and it crashes - even with "Blink"
:-(
"opt: faster" CoreMark 1.0 : 2313.57 / GCC5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496] (flags unknown) / STACK
"opt: faster" CoreMark 1.0 : 2431.32 / GCC9.3.1 20200408 (release) (flags unknown) / STACK
"opt: faster" CoreMark 1.0 : 2406.93 / GCC10.2.1 20201103 (release) (flags unknown) / STACK
"opt: fastest" CoreMark 1.0 : 2476.27 / GCC5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496] (flags unknown) / STACK
"opt: fastest" CoreMark 1.0 : 2398.46 / GCC9.3.1 20200408 (release) (flags unknown) / STACK
"opt: fastest" Crashes with GCC10.2.1 20201103
Edit: No, of course the flash-speed has NO influence - it runs in RAM, and even if it would run in flash: it fits into the cache.
I wonder what the GCC folks does... seems to ignore ARM-Cortex Mx somehow, regarding optimizations.. there is a constant regression since GCC 5 (with "-O3")
Edit: added the -O3 flags manually:
-O2 -fgcse-after-reload -fipa-cp-clone -floop-interchange -floop-unroll-and-jam -fpeel-loops -fpredictive-commoning -fsplit-loops -fsplit-paths -ftree-loop-distribution -ftree-loop-vectorize -ftree-partial-pre -ftree-slp-vectorize -funswitch-loops -fvect-cost-model -fvect-cost-model=dynamic -fversion-loops-for-strides
This does not crash (so, the documentation is not complete) - but not worth to use it.., as it is slower than -O2 alone.
Code:CoreMark 1.0 : 2382.09 / GCC10.2.1 20201103 (release) (flags unknown) / STACK
Last edited by Frank B; 12-31-2020 at 10:35 AM.
Echo'ing what WMXZ already said, my main issue is that emulated serial doesn't work outside of the Arduino Serial Monitor that is my biggest issue.
Additionally, I also have a problem caused by me having some custom classes holding a pointer to what is assumed to be that Serial connection. I know that I should be assuming that it is simply a "Stream", but I wanted to attempt to use some of the dtr() functionality that is enabled if I keep its type as "usb_serial_class". When I want to use this class along with MTP, the use of emulated serial breaks all of this (because usb_serial_class doesn't exist and is replaced instead with usb_seremu_class).
With some trickier programming on my part, I'm sure that I can make the usb_serial_class / usb_seremu_class problem go away. Therefore, it is only a secondary concern; my primary issue is that emulated serial doesn't work outside of the Arduino Serial Monitor.
Chip
imxrt-size:
@Paul, not sure if you're following the other thread, so I ask here.
It's almost done. Works for linux and Windows now - and I see no reason why it shouldn't work with a MAC.
Which output-format do you want? I can change it today. Luni proposed a good one.
I found a racecondition with the _vector table.
It is not declared volatile, so if a interrupts occurs near writing a new vector to table, it calls the old interrupt.
I'll issue a PR.
@Paul @WMXZ @mjs513 @defragster... and all:
As has been mentioned up in the MTP thread, it would probably be a good thing, that when possible MTP would be able to tell the Host the dates and times for the files it is showing.
The MTP protocol does have the ability to give this information to the host in a standard format: YYYYMMDDThhmmsss.s
And does have the ability for the two values:
#define MTP_PROPERTY_DATE_CREATED 0xDC08
#define MTP_PROPERTY_DATE_MODIFIED 0xDC09
Which we are not doing.
But so far I don't see any way to do this currently with our current libraries:
Things like:
a) Does LittleFS have any concept of Date and Time? I have not seen it in my looking through the docs, but maybe it is some how encoded in the data?
b) SDFat - The fat file system does have date/time stamps that are set for the files. There is a callback function, that can be defined that defines the correct dates and times that is called when the file is created, modified...
But: so far the only methods to access these values are by some print methods, like: printModifyDateTime()
There is an issue up on the SDFat project: https://github.com/greiman/SdFat/issues/223
Where someone has raised the issue and provided code that they were doing and appears like there will be a solution:
And @greiman commented on this issue:
c) Our new FS.h classes FS and FILE do not provide any way to get this information. So maybe we should add these to the FILE class and maybe try to add the implementation to SD class?Code:greiman commented on Nov 23, 2020 • I will provide these functions in the next release: bool getAccessDateTime( uint16_t * pdate, uint16_t * ptime ); bool getCreateDateTime( uint16_t * pdate, uint16_t * ptime ); bool getModifyDateTime( uint16_t * pdate, uint16_t * ptime ); FAT32/FAT16 only has access date so I will return zero for time.
As for LittleFS if it has no idea of date/time return 0s...
Thoughts?
I've added a PR that adds printing hardfaults, temperature panic and unused interrupts.
It first does as soft reset to put the Teensy in a clean state, then prints the messages.
After 10 seconds, setup() and the rest of the program restarts.
Examples:
prints:Code:uint8_t *p = nullptr; *p = 5;
A Stackfault looks like this:Code:Hardfault. Return Address: 0x16A (DACCVIOL) Data Access Violation (MMARVALID) Accessed Address: 0x0 (nullptr)
All other hardfaults are printed, too.Code:Hardfault. Return Address: 0x14A0 (DACCVIOL) Data Access Violation (MMARVALID) Accessed Address: 0x200032C8 (Stack problem) Check for stack overflows, array bounds, etc.
For unused interrupts:
it printsCode:NVIC_ENABLE_IRQ(IRQ_Reserved5); NVIC_STIR = IRQ_Reserved5;
Code:Fault. Unused ISR No. 128 called
In case of a temperature panic, it prints "Temperature Panic." and switches the Teensy off as before (without 10 secs wait)
With other IDEs, you can disable it (use SHOW_HARDFAULTS 0), or use an other Serial:
Code:#ifndef SHOW_HARDFAULTS #define SHOW_HARDFAULTS 1 #endif #ifndef HARDFAULTSOUT #define HARDFAULTSOUT Serial #endif
Hint:
If you want hardfaults for division by zero, you can add this to your program:
SCB_CCR = 0x10; //Enable "Div By Zero" Hardfaults
(But I think this does not work for floats)
Last edited by Frank B; 01-11-2021 at 07:51 PM.
Paul, I have done PR for Teensy-LC / Audiolibrary.
Would you merge them?
No more silent passing away... (in most cases)
@Paul or others:
In WavFilePlayer we have patches like
I think I(??) have added them a long time ago, to fix something..Code:#if defined(HAS_KINETIS_SDHC)
I cant' remember what it was good for.. any Ideas? is it still needed?
Edit: Has anyone tested the WavFilePlayer with littleFs?
Edit: Has anyone tested the Teensy LC with littleFs?
I found it. It was 2016:
https://github.com/PaulStoffregen/Au...4a3d146f2de739
As we now have more sources for files, and with the abstractions we need a better fix..
Edit: FS needs a addtion that says if SPI is used or not. bool usesSPI()
The WavFilePlayer has an other problem, at least on LC , too: Sometimes it consumes 2 blocks more than needed.
I couldn't find out why this happens.
You'll see it if you leave the WavFilePlayer example running, and add a print Serial.println(AudioMemoryUsageMax());
It is reproducable. When a new file starts, it jumps von 2 block to 4 blocks.
Sometimes it happens on the first start, too.
Edit: it is for a short time only. Print AudioMemoryUsageMax() always reports 2.
Last edited by Frank B; 01-13-2021 at 02:18 PM.
Hi. Please, can you explain how we can uninstall Teensyduino 1.54 Beta #5 correctly? I have tried to delete all the Teensy folder in the Arduino folder, but when I try to re-install 1.53 version, I stay lock during the installation process in the chose folder and can't continue anymore. it-will be one good thing if you place this process on the Teensyduino web page.
Another thing, do you plan to add MSC support in Teensyduino like discuss in https://forum.pjrc.com/threads/55821...l=1#post266492?
As for best way to uininstall a version.
First I reboot to make sure I don't have any Arduino things opened up and running.
I will often just delete the arduino (actually I rename it to some other directory just in case). Then install fresh copy of Arduino. I don't typically install into the standard program files... So I actually have several different versions on my machine. Then I install which ever version of Teensyduino I wish to use.
Don't know what the issue you are running into that stay lock... But that is what I do when things get stuck.
I just saw that - if no DMA channel is available, Teensy just hardfaults.
If there was a intention to put the hardfault handling into the core, i'd try to add something like printing an errormessage for problems like this![]()
Well I started playing with the wavFilePlayer code but run into a problem how to handle pointing the to constructor for each type of FLASH (QSPI, SPI, FRAM) in the play_sd_xxx files in the audio library.
Right how SD has:
and so you don't have to go digging:Code:extern SDClass SD;
In littleFS we have something similar:Code:class SDClass : public FS { public: SDClass() { } bool begin(uint8_t csPin = 10) { #ifdef BUILTIN_SDCARD if (csPin == BUILTIN_SDCARD) { return sdfs.begin(SdioConfig(FIFO_SDIO)); //return sdfs.begin(SdioConfig(DMA_SDIO)); } #endif return sdfs.begin(SdSpiConfig(csPin, SHARED_SPI, SD_SCK_MHZ(16))); //return sdfs.begin(csPin, SD_SCK_MHZ(24)); } File open(const char *filepath, uint8_t mode = FILE_READ) { oflag_t flags = O_READ; if (mode == FILE_WRITE) flags = O_RDWR | O_CREAT | O_AT_END; else if (mode == FILE_WRITE_BEGIN) flags = O_RDWR | O_CREAT; SDFAT_FILE file = sdfs.open(filepath, flags); if (file) return File(new SDFile(file)); return File(); } bool exists(const char *filepath) { return sdfs.exists(filepath); } bool mkdir(const char *filepath) { return sdfs.mkdir(filepath); } bool rename(const char *oldfilepath, const char *newfilepath) { return sdfs.rename(oldfilepath, newfilepath); } bool remove(const char *filepath) { return sdfs.remove(filepath); } bool rmdir(const char *filepath) { return sdfs.rmdir(filepath); } uint64_t usedSize() { return (uint64_t)(sdfs.clusterCount() - sdfs.freeClusterCount()) * (uint64_t)sdfs.bytesPerCluster(); } uint64_t totalSize() { return (uint64_t)sdfs.clusterCount() * (uint64_t)sdfs.bytesPerCluster(); } public: // allow access, so users can mix SD & SdFat APIs SDFAT_BASE sdfs; }; extern SDClass SD;
Just adding a extern LittleFS FLASH does not work since we have to do this for each type of FLASH:Code:class LittleFS : public FS { public: LittleFS() { configured = false; mounted = false; config.context = nullptr; } bool quickFormat(); bool lowLevelFormat(char progressChar=0); uint32_t formatUnused(uint32_t blockCnt, uint32_t blockStart); File open(const char *filepath, uint8_t mode = FILE_READ) { //Serial.println("LittleFS open"); if (!mounted) return File(); if (mode == FILE_READ) { struct lfs_info info; if (lfs_stat(&lfs, filepath, &info) < 0) return File(); //Serial.printf("LittleFS open got info, name=%s\n", info.name); if (info.type == LFS_TYPE_REG) { //Serial.println(" regular file"); lfs_file_t *file = (lfs_file_t *)malloc(sizeof(lfs_file_t)); if (!file) return File(); if (lfs_file_open(&lfs, file, filepath, LFS_O_RDONLY) >= 0) { return File(new LittleFSFile(&lfs, file, filepath)); } free(file); } else { // LFS_TYPE_DIR //Serial.println(" directory"); lfs_dir_t *dir = (lfs_dir_t *)malloc(sizeof(lfs_dir_t)); if (!dir) return File(); if (lfs_dir_open(&lfs, dir, filepath) >= 0) { return File(new LittleFSFile(&lfs, dir, filepath)); } free(dir); } } else { lfs_file_t *file = (lfs_file_t *)malloc(sizeof(lfs_file_t)); if (!file) return File(); if (lfs_file_open(&lfs, file, filepath, LFS_O_RDWR | LFS_O_CREAT) >= 0) { if (mode == FILE_WRITE) { // FILE_WRITE opens at end of file lfs_file_seek(&lfs, file, 0, LFS_SEEK_END); } // else FILE_WRITE_BEGIN return File(new LittleFSFile(&lfs, file, filepath)); } } return File(); } bool exists(const char *filepath) { if (!mounted) return false; struct lfs_info info; if (lfs_stat(&lfs, filepath, &info) < 0) return false; return true; } bool mkdir(const char *filepath) { if (!mounted) return false; if (lfs_mkdir(&lfs, filepath) < 0) return false; return true; } bool rename(const char *oldfilepath, const char *newfilepath) { if (!mounted) return false; if (lfs_rename(&lfs, oldfilepath, newfilepath) < 0) return false; return true; } bool remove(const char *filepath) { if (!mounted) return false; if (lfs_remove(&lfs, filepath) < 0) return false; return true; } bool rmdir(const char *filepath) { return remove(filepath); } uint64_t usedSize() { if (!mounted) return 0; int blocks = lfs_fs_size(&lfs); if (blocks < 0 || (lfs_size_t)blocks > config.block_count) return totalSize(); return blocks * config.block_size; } uint64_t totalSize() { if (!mounted) return 0; return config.block_count * config.block_size; } protected: bool configured; bool mounted; lfs_t lfs; lfs_config config; };
All that is in the play_sd_xxx files are SD.open(filename)?????Code:LittleFS_SPIFlash FLASH;
So anyone with how to do this would be appreciated![]()
Hm i did not read about that, but I thought FS.h was a wrapper for all kinds of FS?
I guess it just needs an info which FS is used.
But I have _no_ knowlage about all this stuff. I wait for someone who writes a "Howto"I don't think this all will be builtin without any information for the users
I was hoping that it is transparent, and old software would be able to use all this automagically.
If not, we have to rewrite a lot of old stuff... ?
I guess we need Windows-like drive-letters or devices..or canonical paths... ?
Like "//littlefs/flash0/MyFantasticFile.txt"
But, really, I don't know what the plan is.
Edit: With "SD" as default - "Builtin" for teensies with SD Socket, SPI for others..
Last edited by Frank B; 01-16-2021 at 09:38 PM.