-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
boards/seeedstudio-xiao-nrf52840: initial board support #20980
base: master
Are you sure you want to change the base?
Conversation
Currently failing tests:
|
Most of those are software-only and won't depend on the board. (Thinking of it, we should probably add a general board test app that makes it easier to evaluate a newly ported board) |
True, but I've still managed to find some issues which are at least board-related :)
Great, I'll have a look! Do we have a list of such useful test applications for new boards somewhere? May be good to add a pointer to the documentation.
Or even better! |
4e1d250
to
f4709f9
Compare
f4709f9
to
72f9fb0
Compare
|
|
|
Status update on tests that have been failing previously:
Some of them fail with |
.wait_chip_erase = 20LU * US_PER_SEC, | ||
.wait_32k_erase = 20LU *US_PER_MS, | ||
.wait_sector_erase = 20LU * US_PER_MS, | ||
.wait_chip_wake_up = 35LU * US_PER_MS, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure which flash device is used on the Xiao nRF52840 (the schematic says DNP), but if it's the same as the one on the RP2040 (GD25Q16CEIG [1]), some of the timing parameters should be changed.
The chip erase time is good, the datasheet says up to 20s.
20ms for the block (32k) erase is not enough, the datasheet says 150-1200ms.
The sector erase is between 45-300ms. Setting it to 300ms would bring a significant performance penalty for LittleFS, but I'd set it at least to 45ms.
I didn't find a reliable value for the wake up (the datasheet does not include the word "wake" :D ). The time from Deep Powerdown to normal operation is supposed to be t_RES1/t_RES2 = 20µs. That seems a bit low.
[1] https://www.mouser.com/datasheet/2/870/gd25q16c_v3_2_20210513-1668164.pdf p.47f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @crasbe, but it seems to be a 2MB P25Q16H according to what I could find online:
- https://devzone.nordicsemi.com/f/nordic-q-a/88361/xiao-ble-qspi-flash-p25q16h-with-nordic-nrf-connect-sdk
- https://devzone.nordicsemi.com/f/nordic-q-a/101385/xiao-ble-sense-external-flash-p25q16h-not-detecting-all-the-time
This is the datasheet I found online which I derived the values from: https://files.seeedstudio.com/wiki/github_weiruanexample/Flash_P25Q16H-UXH-IR_Datasheet.pdf
But I would appreciate you double-checking again, since I'm not very familiar with flash parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good detective work, I didn't find that :D
This is a bit of a dilemma. On one hand it would be right to implement what's in the datasheet, however I can't really believe that 20ms statement. Usually Chip Erase takes multiple seconds, block erase usualy a couple hundred milliseconds too, and so does the sector erase:
Some examples:
IS25LP016D https://www.issi.com/WW/pdf/25LP-WP016D.pdf p. 96: Chip: 4-12s, Block: 100-500ms, Sector: 70-300ms
MX25F1635F https://www.mxic.com.tw/Lists/Datasheet/Attachments/8702/MX25R1635F,%20Wide%20Range,%2016Mb,%20v1.6.pdf p.75: Chip: 13-38s, Block: 0.24-1.5s, Sector: 40-240ms
MX25L1636E https://www.mxic.com.tw/Lists/Datasheet/Attachments/8596/MX25L1636E,%203V,%2016Mb,%20v1.3.pdf p.29: Chip 6-30s, Block: 0.4-2.2s, Sector: 60-300ms
W25Q16JV https://docs.rs-online.com/fce0/0900766b81622f8c.pdf p.63 Chip: 5-25s, Block: 120-1600ms, Sector: 45-400ms
Currently the MTD_NOR_SPI driver does not implement a timeout for these timing values ( https://github.com/RIOT-OS/RIOT/blob/master/drivers/mtd_spi_nor/mtd_spi_nor.c#L356-L403 ), but that will change in the future (as soon as I find time for it..). No timeout means that it will wait the period specified initially, but it'll retry again and again and again and...
The waiting function is quite verbose, so it will tell you how long a certain operation actually took. It would be interesting to see how long a chip erase takes for example. However I'm not sure if there's currently any program that actually issues a chip erase (LittleFS format
does not).
I ordered a Xiao-nRF52840 for testing, but it'll take some days to arrive. However given the fact that the datasheet values are most likely incorrect, we'd have to find substitution values anyway. The tests will give a ballpark figure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep in mind that these are only minimal values, it's basically the polling interval of the status register after the respective operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The datasheet specifies 20ms as maximum. Typical value is 8ms, which seems even more unrealistic. "Typical" is typically a lie and the truth is always somewhere between minimum and maximum, but often not at "typical".
The definition of the MX25R6435F on the nRF52840DK for example uses the "typical" values from the datasheet:
https://github.com/RIOT-OS/RIOT/blob/master/boards/nrf52840dk/mtd.c#L32-L35
.wait_chip_erase = 50LU * US_PER_SEC,
.wait_32k_erase = 240LU *US_PER_MS,
.wait_sector_erase = 40LU * US_PER_MS,
.wait_chip_wake_up = 35LU * US_PER_MS,
Of course, you are right. At the moment it really doesn't matter what the waiting time is. The program will just poll the register 50-100 times and eventually it will flip. However, when a timeout will be implemented ( #20769 ), there has to be a threshold. Consider this threshold to be 10-30x the time specified by the "typical" value (this would probably require a small datasheet survey to determine the usual factor between typical and maximum).
That timeout would immediately break things for this board because the specified wait times are way shorter than what they really are.
Perhaps even worse: it would fail sometimes. Because depending on what the internal state is or how full the flash device/sector/block is, the operation takes different amounts of time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My Xiao-nrf52840 arrived today and I did some testing on this with a hacked together test of the mtd_spi_nor test from my #20589 PR and these are the results:
~2ms for a page write,
~17ms for a sector erase,
~17ms for a 32k block erase,
~135ms for a chip erase
The test wrote 0x00 to all memory cells affected because that's the most amount of energy required to get back to 0xFF.
Therefore I think that the original values that @mguetschow assumed are not too far off except for the chip erase time. That can be significantly reduced from 20s to something like 200ms.
Honestly I am quite surprised that the chip is that quick.
Log of the test case with the relevant timings highlighted
=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2024.12.18 22:15:24 =~=~=~=~=~=~=~=~=~=~=~=
s is RIOT! (Version: 2025.01-devel-193-g72f9f-board-xiao-nrf52840)
tests/mtd_spi_nor: 1 MTD devices present, selected device: 0
.test_mtd_init: Initializing the Device
mtd_spi_nor_init: 0x20000200
mtd_spi_nor_init: -> spi: 1, cs: 19, opcodes: 0x885c
mtd_spi_nor_init: init pins
mtd_spi_nor_init: power up MTD device
mtd_spi_cmd: 0x20000200, ab
mtd_spi_read_jedec_id: rdid=0x9f
mtd_spi_cmd_read: 0x20000200, 9f, 0x20000e30, 13
mtd_spi_read_jedec_id: bank=1 manuf=0x85
mtd_spi_read_jedec_id: device=0x60, 0x15
mtd_spi_read_jedec_id: rdid=0x9f
mtd_spi_cmd_read: 0x20000200, 9f, 0x20000e48, 13
mtd_spi_read_jedec_id: bank=1 manuf=0x85
mtd_spi_read_jedec_id: device=0x60, 0x15
mtd_spi_nor_init: Found chip with ID: (1, 0x85, 0x60, 0x15)
mtd_spi_nor_init: 2097152 bytes (512 sectors, 4096 bytes/sector, 8192 pages, 16 pages/sector, 256 bytes/page)
mtd_spi_nor_init: Using 3 byte addresses
mtd_spi_cmd_read: 0x20000200, 05, 0x20000e7f, 1
mtd_spi_nor_init: device status = 0x00
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd: 0x20000200, 98
mtd_spi_nor_init: page_addr_mask = 0xffffff00, page_addr_shift = 8
mtd_spi_nor_init: sec_addr_mask = 0xfffff000, sec_addr_shift = 12
mtd_spi_nor_init: 0x20000200
mtd_spi_nor_init: -> spi: 1, cs: 19, opcodes: 0x885c
mtd_spi_nor_init: init pins
mtd_spi_nor_init: power up MTD device
mtd_spi_cmd: 0x20000200, ab
mtd_spi_read_jedec_id: rdid=0x9f
mtd_spi_cmd_read: 0x20000200, 9f, 0x20000e30, 13
mtd_spi_read_jedec_id: bank=1 manuf=0x85
mtd_spi_read_jedec_id: device=0x60, 0x15
mtd_spi_read_jedec_id: rdid=0x9f
mtd_spi_cmd_read: 0x20000200, 9f, 0x20000e48, 13
mtd_spi_read_jedec_id: bank=1 manuf=0x85
mtd_spi_read_jedec_id: device=0x60, 0x15
mtd_spi_nor_init: Found chip with ID: (1, 0x85, 0x60, 0x15)
mtd_spi_nor_init: 2097152 bytes (512 sectors, 4096 bytes/sector, 8192 pages, 16 pages/sector, 256 bytes/page)
mtd_spi_nor_init: Using 3 byte addresses
mtd_spi_cmd_read: 0x20000200, 05, 0x20000e7f, 1
mtd_spi_nor_init: device status = 0x00
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd: 0x20000200, 98
mtd_spi_nor_init: page_addr_mask = 0xffffff00, page_addr_shift = 8
mtd_spi_nor_init: sec_addr_mask = 0xfffff000, sec_addr_shift = 12
mtd_spi_cmd_read: 0x20000200, 05, 0x20000eae, 1
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_read: 0x20000200, 05, 0x20000eaf, 1
mtd_spi_nor: wait device status = 0x02, waiting WEL-Flag
mtd_spi_cmd_write: 0x20000200, 01, 0x20000eae, 1
.test_mtd_erase: Erasing the first sector
mtd_spi_nor_write_page: 0x20000200, 0x20000d98, 0x0, 0x0, 0x100
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_addr_write: 0x20000200, 02, (000000), 0x20000d98, 256
mtd_spi_cmd_addr_write: addr: 00 00 00
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 4 times, yield 4 times, total wait 1990us
....
mtd_spi_nor_write_page: 0x20000200, 0x20000d98, 0xf, 0x0, 0x100
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_addr_write: 0x20000200, 02, (000f00), 0x20000d98, 256
mtd_spi_cmd_addr_write: addr: 00 0f 00
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d0f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 4 times, yield 4 times, total wait 1992us
==================================== PERFORMING THE SECTOR ERASE =======================================
mtd_spi_nor_erase: 0x20000200, 0x0, 0x1000
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_addr_write: 0x20000200, 20, (000000), 0, 0
mtd_spi_cmd_addr_write: addr: 00 00 00
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d3f, 1
mtd_spi_nor: wait device status = 0x03
...
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d3f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d3f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 34 times, yield 0 times, total wait 17386us <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
mtd_spi_nor_read: 0x20000200, 0x20000d98, 0x0, 0x100
mtd_spi_cmd_addr_read: 0x20000200, 03, (000000), 0x20000d98, 256
mtd_spi_cmd_addr_read: addr: 00 00 00
mtd_spi_nor_read: 0x20000200, 0x20000d98, 0x100, 0x100
mtd_spi_cmd_addr_read: 0x20000200, 03, (000100), 0x20000d98, 256
...
mtd_spi_nor_read: 0x20000200, 0x20000d98, 0xf00, 0x100
mtd_spi_cmd_addr_read: 0x20000200, 03, (000f00), 0x20000d98, 256
mtd_spi_cmd_addr_read: addr: 00 0f 00
==================================== PERFORMING THE BLOCK ERASE =======================================
mtd_spi_nor_erase: 0x20000200, 0x0, 0x8000
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_addr_write: 0x20000200, 52, (000000), 0, 0
mtd_spi_cmd_addr_write: addr: 00 00 00
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d3f, 1
mtd_spi_nor: wait device status = 0x03
...
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d3f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d3f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 33 times, yield 0 times, total wait 17162us <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.mtd_spi_nor_write_page: 0x20000200, 0x20000db8, 0x0, 0x0, 0x100
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_addr_write: 0x20000200, 02, (000000), 0x20000db8, 256
mtd_spi_cmd_addr_write: addr: 00 00 00
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 4 times, yield 4 times, total wait 2071us
...
mtd_spi_nor_write_page: 0x20000200, 0x20000db8, 0x1fff, 0x0, 0x100
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd_addr_write: 0x20000200, 02, (1fff00), 0x20000db8, 256
mtd_spi_cmd_addr_write: addr: 1f ff 00
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d2f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 4 times, yield 4 times, total wait 1994us
============================================= PERFORMING THE CHIP ERASE ===================================
mtd_spi_nor_erase: 0x20000200, 0x0, 0x200000
mtd_spi_cmd: 0x20000200, 06
mtd_spi_cmd: 0x20000200, c7
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d5f, 1
mtd_spi_nor: wait device status = 0x03
...
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d5f, 1
mtd_spi_nor: wait device status = 0x03
mtd_spi_cmd_read: 0x20000200, 05, 0x20000d5f, 1
mtd_spi_nor: wait device status = 0x00
wait loop 203 times, yield 0 times, total wait 134996us <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.test_mtd_block_protect: No security features enabled, skip test.
OK (4 tests)
Contribution description
Initial board support for the tiny Seed Studio XIAO nRF52840. It uses the same bootloader as the Adafruit nrf52840 Feather (Sense) boards.
Testing procedure
I'm still in the process of running
BUILD_IN_DOCKER=1 dist/tools/compile_and_test_for_board/compile_and_test_for_board.py . seeedstudio-xiao-nrf52840
locally and will report back with the result later.Look through the header and configuration files. I've mostly followed the example from
feather-nrf52840-sense
andnrf52840dk
(for the external flash).Check generated documentation for the board.