Skip to content
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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

mguetschow
Copy link
Contributor

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 and nrf52840dk (for the external flash).

  • Check generated documentation for the board.

@github-actions github-actions bot added Area: doc Area: Documentation Area: boards Area: Board ports Area: Kconfig Area: Kconfig integration labels Nov 13, 2024
@mguetschow mguetschow marked this pull request as draft November 13, 2024 10:19
@mguetschow
Copy link
Contributor Author

  • 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.

Currently failing tests:

$ find results -name "*.failed"
results/seeedstudio-xiao-nrf52840/tests/sys/congure_test/test.failed
results/seeedstudio-xiao-nrf52840/tests/sys/pthread_flood/test.failed
results/seeedstudio-xiao-nrf52840/tests/sys/congure_quic/test.failed
results/seeedstudio-xiao-nrf52840/tests/sys/usbus/test.failed
results/seeedstudio-xiao-nrf52840/tests/sys/shell/test.failed
results/seeedstudio-xiao-nrf52840/tests/core/thread_msg/test.failed
results/seeedstudio-xiao-nrf52840/tests/core/msg_queue_print/test.failed
results/seeedstudio-xiao-nrf52840/tests/riotboot/test.failed
results/seeedstudio-xiao-nrf52840/tests/turo/test.failed
results/seeedstudio-xiao-nrf52840/tests/cpu/mpu_noexec_ram/test.failed
results/seeedstudio-xiao-nrf52840/tests/cpu/mpu_stack_guard/test.failed
results/seeedstudio-xiao-nrf52840/tests/riotboot_hdr/test.failed
results/seeedstudio-xiao-nrf52840/tests/pkg/libschc/test.failed

@benpicco
Copy link
Contributor

Most of those are software-only and won't depend on the board.
compile_and_test_for_board.py isn't the greatest way to test a board, there are tests/periph/spi, tests/periph/uart and tests/drivers/mtd_raw that come with a test command but that requires RX/TX / MISO/MOSI to be connected or a writable MTD device (in case the board exposes MTD). ``tests/periph/i2calso includesi2c_scan`, but that can be included everywhere with `shell_cmd_i2c_scan`.

(Thinking of it, we should probably add a general board test app that makes it easier to evaluate a newly ported board)

@mguetschow
Copy link
Contributor Author

Most of those are software-only and won't depend on the board.

True, but I've still managed to find some issues which are at least board-related :)

there are tests/periph/spi, tests/periph/uart and tests/drivers/mtd_raw

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.

(Thinking of it, we should probably add a general board test app that makes it easier to evaluate a newly ported board)

Or even better!

@mguetschow
Copy link
Contributor Author

tests/periph/uart: ✔️ SUCCESS

with UART pins connected (TX to RX)

make -C tests/periph/uart BOARD=seeedstudio-xiao-nrf52840 flash term
make: Entering directory '/home/mikolai/TUD/Code/RIOT-build/tests/periph/uart'
Building application "tests_uart" for "seeedstudio-xiao-nrf52840" with CPU "nrf52".

"make" -C /home/mikolai/TUD/Code/RIOT-build/pkg/cmsis/ 
"make" -C /home/mikolai/TUD/Code/RIOT-build/boards/common/init
"make" -C /home/mikolai/TUD/Code/RIOT-build/boards/seeedstudio-xiao-nrf52840
"make" -C /home/mikolai/TUD/Code/RIOT-build/core
"make" -C /home/mikolai/TUD/Code/RIOT-build/core/lib
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/cortexm_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/cortexm_common/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52/vectors
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf5x_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf5x_common/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers/periph_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/auto_init
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/auto_init/usb
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/div
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/event
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/fmt
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/frac
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/isrpipe
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/libc
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/luid
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/malloc_thread_safe
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/newlib_syscalls_default
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/preprocessor
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/shell
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/stdio
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/tsrb
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb/usbus
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb/usbus/cdc/acm
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb_board_reset
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/ztimer
   text    data     bss     dec     hex filename
  28324     132    6324   34780    87dc /home/mikolai/TUD/Code/RIOT-build/tests/periph/uart/bin/seeedstudio-xiao-nrf52840/tests_uart.elf
stty -F /dev/ttyACM0 raw ispeed 1200 ospeed 1200 cs8 -cstopb ignpar eol 255 eof 255
sleep 10
/home/mikolai/TUD/Code/RIOT-build/dist/tools/uf2/uf2conv.py -f 0xADA52840 /home/mikolai/TUD/Code/RIOT-build/tests/periph/uart/bin/seeedstudio-xiao-nrf52840/tests_uart.hex --base 0x1000
Converted to uf2, output size: 57344, start address: 0x1000
Flashing /media/mikolai/XIAO-SENSE (Seeed_XIAO_nRF52840_Sense)
Wrote 57344 bytes to /media/mikolai/XIAO-SENSE/NEW.UF2
sleep 2
/home/mikolai/TUD/Code/RIOT-build/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "115200" -ln "/tmp/pyterm-mikolai" -rn "2024-11-25_16.37.17-tests_uart-seeedstudio-xiao-nrf52840"  
Twisted not available, please install it if you want to use pyterm's JSON capabilities
2024-11-25 16:37:17,369 # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2024-11-25 16:37:18,371 #  data 
2024-11-25 16:37:18,372 # being printed to STDOUT
2024-11-25 16:37:18,372 # 
2024-11-25 16:37:18,373 # NOTE: all strings need to be '\n' terminated!
2024-11-25 16:37:18,373 # 
2024-11-25 16:37:18,373 # 
2024-11-25 16:37:18,373 # UART INFO:
2024-11-25 16:37:18,374 # Available devices:               1
> test 0
2024-11-25 16:37:20,905 # test 0
2024-11-25 16:37:20,905 # [START]
2024-11-25 16:37:20,935 # warning: unsupported baudrate 48000
2024-11-25 16:37:20,939 # warning: unsupported baudrate 67200
2024-11-25 16:37:20,942 # warning: unsupported baudrate 86400
2024-11-25 16:37:20,943 # warning: unsupported baudrate 96000
2024-11-25 16:37:20,944 # warning: unsupported baudrate 105600
2024-11-25 16:37:20,944 # [SUCCESS]
> /exit
2024-11-25 16:37:55,158 # Exiting Pyterm
make: Leaving directory '/home/mikolai/TUD/Code/RIOT-build/tests/periph/uart'

@mguetschow
Copy link
Contributor Author

tests/periph/spi: ✔️ SUCCESS

with SPI pins connected (MOSI to MISO)

make -C tests/periph/spi BOARD=seeedstudio-xiao-nrf52840 flash term
make: Entering directory '/home/mikolai/TUD/Code/RIOT-build/tests/periph/spi'
Building application "tests_spi" for "seeedstudio-xiao-nrf52840" with CPU "nrf52".

"make" -C /home/mikolai/TUD/Code/RIOT-build/pkg/cmsis/ 
"make" -C /home/mikolai/TUD/Code/RIOT-build/boards/common/init
"make" -C /home/mikolai/TUD/Code/RIOT-build/boards/seeedstudio-xiao-nrf52840
"make" -C /home/mikolai/TUD/Code/RIOT-build/core
"make" -C /home/mikolai/TUD/Code/RIOT-build/core/lib
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/cortexm_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/cortexm_common/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52/vectors
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf5x_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf5x_common/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers/periph_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/auto_init
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/auto_init/usb
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/div
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/event
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/fmt
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/frac
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/isrpipe
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/libc
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/luid
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/malloc_thread_safe
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/newlib_syscalls_default
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/preprocessor
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/schedstatistics
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/shell
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/shell/cmds
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/stdio
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/tsrb
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb/usbus
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb/usbus/cdc/acm
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb_board_reset
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/ztimer
   text    data     bss     dec     hex filename
  30272     168    5704   36144    8d30 /home/mikolai/TUD/Code/RIOT-build/tests/periph/spi/bin/seeedstudio-xiao-nrf52840/tests_spi.elf
stty -F /dev/ttyACM0 raw ispeed 1200 ospeed 1200 cs8 -cstopb ignpar eol 255 eof 255
sleep 10
/home/mikolai/TUD/Code/RIOT-build/dist/tools/uf2/uf2conv.py -f 0xADA52840 /home/mikolai/TUD/Code/RIOT-build/tests/periph/spi/bin/seeedstudio-xiao-nrf52840/tests_spi.hex --base 0x1000
Converted to uf2, output size: 60928, start address: 0x1000
Flashing /media/mikolai/XIAO-SENSE (Seeed_XIAO_nRF52840_Sense)
Wrote 60928 bytes to /media/mikolai/XIAO-SENSE/NEW.UF2
sleep 2
/home/mikolai/TUD/Code/RIOT-build/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "115200" -ln "/tmp/pyterm-mikolai" -rn "2024-11-25_16.46.30-tests_spi-seeedstudio-xiao-nrf52840"  
Twisted not available, please install it if you want to use pyterm's JSON capabilities
2024-11-25 16:46:30,424 # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2024-11-25 16:46:31,426 # -board-xiao-nrf52840)
2024-11-25 16:46:31,427 # Manual SPI peripheral driver test (see README.md)
2024-11-25 16:46:31,428 # There are 2 SPI devices configured for your platform.
init 0 0 0
2024-11-25 16:46:38,372 # init 0 0 0
2024-11-25 16:46:38,373 # Trying to initialize SPI_DEV(0): mode: 0, clk: 0, cs_port: 0, cs_pin: 0
2024-11-25 16:46:38,383 # (if below the program crashes with a failed assertion, then it means the configuration is not supported)
2024-11-25 16:46:38,383 # Success.
> send hello
2024-11-25 16:46:43,524 # send hello
2024-11-25 16:46:43,525 # Sent bytes
2024-11-25 16:46:43,533 #    0    1    2    3    4 
2024-11-25 16:46:43,534 #   0x68 0x65 0x6c 0x6c 0x6f
2024-11-25 16:46:43,534 #     h    e    l    l    o 
2024-11-25 16:46:43,534 # 
2024-11-25 16:46:43,535 # Received bytes
2024-11-25 16:46:43,535 #    0    1    2    3    4 
2024-11-25 16:46:43,536 #   0x68 0x65 0x6c 0x6c 0x6f
2024-11-25 16:46:43,536 #     h    e    l    l    o 
2024-11-25 16:46:43,536 # 
> 

@mguetschow
Copy link
Contributor Author

tests/drivers/mtd_raw: ✔️ SUCCESS

make -C tests/drivers/mtd_raw BOARD=seeedstudio-xiao-nrf52840 flash term
make: Entering directory '/home/mikolai/TUD/Code/RIOT-build/tests/drivers/mtd_raw'
Building application "tests_mtd_raw" for "seeedstudio-xiao-nrf52840" with CPU "nrf52".

"make" -C /home/mikolai/TUD/Code/RIOT-build/pkg/cmsis/ 
"make" -C /home/mikolai/TUD/Code/RIOT-build/boards/common/init
"make" -C /home/mikolai/TUD/Code/RIOT-build/boards/seeedstudio-xiao-nrf52840
"make" -C /home/mikolai/TUD/Code/RIOT-build/core
"make" -C /home/mikolai/TUD/Code/RIOT-build/core/lib
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/cortexm_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/cortexm_common/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf52/vectors
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf5x_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/cpu/nrf5x_common/periph
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers/mtd
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers/mtd_spi_nor
"make" -C /home/mikolai/TUD/Code/RIOT-build/drivers/periph_common
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/auto_init
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/auto_init/usb
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/div
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/event
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/fmt
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/isrpipe
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/libc
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/luid
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/malloc_thread_safe
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/newlib_syscalls_default
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/od
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/preprocessor
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/shell
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/shell/cmds
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/stdio
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/test_utils/interactive_sync
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/test_utils/print_stack_usage
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/tsrb
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb/usbus
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb/usbus/cdc/acm
"make" -C /home/mikolai/TUD/Code/RIOT-build/sys/usb_board_reset
   text    data     bss     dec     hex filename
  30980     172    4664   35816    8be8 /home/mikolai/TUD/Code/RIOT-build/tests/drivers/mtd_raw/bin/seeedstudio-xiao-nrf52840/tests_mtd_raw.elf
stty -F /dev/ttyACM0 raw ispeed 1200 ospeed 1200 cs8 -cstopb ignpar eol 255 eof 255
sleep 10
/home/mikolai/TUD/Code/RIOT-build/dist/tools/uf2/uf2conv.py -f 0xADA52840 /home/mikolai/TUD/Code/RIOT-build/tests/drivers/mtd_raw/bin/seeedstudio-xiao-nrf52840/tests_mtd_raw.hex --base 0x1000
Converted to uf2, output size: 62464, start address: 0x1000
Flashing /media/mikolai/XIAO-SENSE (Seeed_XIAO_nRF52840_Sense)
Wrote 62464 bytes to /media/mikolai/XIAO-SENSE/NEW.UF2
sleep 2
/home/mikolai/TUD/Code/RIOT-build/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "115200" -ln "/tmp/pyterm-mikolai" -rn "2024-11-25_16.52.18-tests_mtd_raw-seeedstudio-xiao-nrf52840"  
Twisted not available, please install it if you want to use pyterm's JSON capabilities
2024-11-25 16:52:18,148 # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2024-11-25 16:52:19,150 # main(): This is RIOT! (Version: 2025.01-devel-193-g72f9f-board-xiao-nrf52840)
2024-11-25 16:52:19,151 # Manual MTD test
2024-11-25 16:52:19,151 # init MTD_0… OK (2 MiB)
info
2024-11-25 16:52:24,740 # info
2024-11-25 16:52:24,741 # mtd devices: 1
2024-11-25 16:52:24,741 #  -=[ MTD_0 ]=-
2024-11-25 16:52:24,742 # sectors: 512
2024-11-25 16:52:24,742 # pages per sector: 16
2024-11-25 16:52:24,742 # page size: 256
2024-11-25 16:52:24,743 # total: 2 MiB
> test 0
2024-11-25 16:52:27,891 # test 0
2024-11-25 16:52:27,891 # [START]
2024-11-25 16:52:28,207 # [SUCCESS]
> 

@mguetschow
Copy link
Contributor Author

mguetschow commented Nov 26, 2024

Status update on tests that have been failing previously:

Some of them fail with stdio_cdc_acm but not with stdio_uart. In some cases this is expected, in others not really.

Comment on lines +31 to +34
.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,
Copy link
Contributor

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

Copy link
Contributor Author

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:

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

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,

https://www.macronix.com/Lists/Datasheet/Attachments/8868/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.6.pdf p.71


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.

Copy link
Contributor

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: boards Area: Board ports Area: build system Area: Build system Area: doc Area: Documentation Area: Kconfig Area: Kconfig integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants