8000 H7 QSPI Transfer Error · Issue #5441 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

H7 QSPI Transfer Error #5441

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

Open
iabdalkader opened this issue Dec 19, 2019 · 7 comments
Open

H7 QSPI Transfer Error #5441

iabdalkader opened this issue Dec 19, 2019 · 7 comments

Comments

@iabdalkader
Copy link
Contributor
iabdalkader commented Dec 19, 2019

QSPI transfer error flag (TEF) is set while reading a certain block in qspi_read_cmd_qaddr_qdata this happens exactly when the host (in this case arch/Linux) mounts the storage. I tested a lot of things (disabling cache, IRQs, changing timing etc..) nothing works except if I clear the error flag and restart the transfer it works. There must be something different in the way the host reads/requests blocks because this issue does Not happen on Windows. Unfortunately I don't have any other board with a QSPI flash to test with, the flash I'm using right now is W25Q256JV. This is gdb backtrace from where it gets stuck, thought it might be helpful.

EDIT: forgot to mention that the QSPI is used for the internal storage/filesystem.

0x0813e9e6 in qspi_read_cmd_qaddr_qdata (self_in=0x81dc220 <qspi_bus>, cmd=235 '\353', addr=16642048, len=4096, 
    dest=0x2407ac00 '\377' <repeats 200 times>...) at qspi.c:293
293	            while (!(QUADSPI->SR & QUADSPI_SR_FTF)) {
(gdb) backtrace 
#0  0x0813e9e6 in qspi_read_cmd_qaddr_qdata (self_in=0x81dc220 <qspi_bus>, cmd=235 '\353', addr=16642048, len=4096, 
    dest=0x2407ac00 '\377' <repeats 200 times>...) at qspi.c:293
#1  0x081956c6 in mp_spiflash_read_data (self=0x30003d4c <spi_bdev>, addr=16642048, len=4096, 
    dest=0x2407ac00 '\377' <repeats 200 times>...) at ../../drivers/memory/spiflash.c:117
#2  0x08195a70 in mp_spiflash_cached_read (self=0x30003d4c <spi_bdev>, addr=16642048, len=4096, 
    dest=0x2407ac00 '\377' <repeats 200 times>...) at ../../drivers/memory/spiflash.c:316
#3  0x08137d38 in spi_bdev_readblocks (bdev=0x30003d4c <spi_bdev>, dest=0x2407ac00 '\377' <repeats 200 times>..., block_num=32504, 
    num_blocks=8) at spibdev.c:64
#4  0x0813818e in storage_read_blocks (dest=0x2407ac00 '\377' <repeats 200 times>..., block_num=32760, num_blocks=8) at storage.c:192
#5  0x08136bca in FLASH_STORAGE_Read (lun=0 '\000', buf=0x2407ac00 '\377' <repeats 200 times>..., blk_addr=32760, blk_len=8)
    at usbd_msc_storage.c:136
#6  0x08171478 in SCSI_ProcessRead (pdev=0x300016e4 <usb_device+4>, lun=0 '\000') at usbdev/class/src/usbd_msc_scsi.c:716
#7  0x081711e6 in SCSI_Read10 (pdev=0x300016e4 <usb_device+4>, lun=0 '\000', params=0x3000192f <usb_device+591> "(")
    at usbdev/class/src/usbd_msc_scsi.c:552
#8  0x08170b02 in SCSI_ProcessCmd (pdev=0x300016e4 <usb_device+4>, lun=0 '\000', params=0x3000192f <usb_device+591> "(")
    at usbdev/class/src/usbd_msc_scsi.c:166
#9  0x08170836 in MSC_BOT_CBW_Decode (pdev=0x300016e4 <usb_device+4>) at usbdev/class/src/usbd_msc_bot.c:257
#10 0x0817078e in MSC_BOT_DataOut (pdev=0x300016e4 <usb_device+4>, epnum=3 '\003') at usbdev/class/src/usbd_msc_bot.c:207
#11 0x081703de in USBD_CDC_MSC_HID_DataOut (pdev=0x300016e4 <usb_device+4>, epnum=3 '\003') at usbdev/class/src/usbd_cdc_msc_hid.c:957
#12 0x0816ed3c in USBD_LL_DataOutStage (pdev=0x300016e4 <usb_device+4>, epnum=3 '\003', pdata=0x3000193f <usb_device+607> "\313USBS\"")
    at usbdev/core/src/usbd_core.c:330
#13 0x0813580a in HAL_PCD_DataOutStageCallback (hpcd=0x30003844 <pcd_fs_handle>, epnum=3 '\003') at usbd_conf.c:211
#14 0x08050a8c in PCD_EP_OutXfrComplete_int (hpcd=0x30003844 <pcd_fs_handle>, epnum=3) at src/stm32h7xx_hal_pcd.c:2152
#15 0x0804fbc0 in HAL_PCD_IRQHandler (hpcd=0x30003844 <pcd_fs_handle>) at src/stm32h7xx_hal_pcd.c:1077
#16 0x08135242 in OTG_FS_IRQHandler () at stm32_it.c:311
#17 <signal handler called>
#18 mp_hal_stdin_rx_chr () at mphalport.c:23
#19 0x08155e0e in readline (line=0x3003fcd0, prompt=0x81a5b8c ">>> ") at ../../lib/mp-readline/readline.c:425
#20 0x081496d6 in pyexec_friendly_repl () at ../../lib/utils/pyexec.c:476
#21 0x08066184 in main () at main.c:656
(gdb) p /x *QUADSPI
$1 = {CR = 0x311, DCR = 0x170100, SR = 0x1, FCR = 0x0, DLR = 0xfff, CCR = 0x710edeb, AR = 0xfdf000, ABR = 0x0, DR = 0x0, PSMKR = 0x0, 
  PSMAR = 0x0, PIR = 0x0, LPTR = 0x0}

Note SR=0x1

Edit2: Clearing the flag and setting the address again allows the transfer to finish:

295	    if (((uintptr_t)dest & 3) == 0) {
1: /x *QUADSPI = {CR = 0x311, DCR = 0x170100, SR = 0x1, FCR = 0x0, DLR = 0xfff, CCR = 0x710edeb, AR = 0xfdf000, ABR = 0x0, DR = 0x0, 
  PSMKR = 0x0, PSMAR = 0x0, PIR = 0x0, LPTR = 0x0}

(gdb) set QUADSPI->FCR |= QUADSPI_FCR_CTEF
(gdb) set QUADSPI->AR=0xfdf000
(gdb) p /x *QUADSPI

$4 = {CR = 0x311, DCR = 0x170100, SR = 0x1f24, FCR = 0x0, DLR = 0xfff, CCR = 0x710edeb, AR = 0xfdf000, ABR = 0x0, DR = 0xffffffff, 
  PSMKR = 0x0, PSMAR = 0x0, PIR = 0x0, LPTR = 0x0}

Edit 3: So this makes it work, meaning I don't get a TEF if I do the following:

    QUADSPI->CR &= ~(1 << QUADSPI_CR_EN_Pos);
    QUADSPI->AR = addr; // addres to read from
    QUADSPI->CR |= (1 << QUADSPI_CR_EN_Pos);
    QUADSPI->AR = addr; // re-write address
@iabdalkader
Copy link
Contributor Author

Found this in the Errata (DM00368411), not sure if it's related:

2.6.1 First nibble of data is not written after a dummy phase
Description
The first nibble of data to be written to the external Flash memory is lost in the following
conditions:
• The QUADSPI is used in the Indirect write mode,
• and at least one dummy cycle is used.

@iabdalkader
Copy link
Contributor Author

I have another update on this, I changed qspi_read_cmd_qaddr_qdata to follow the HAL exact sequence in command/receive functions, and it fixed this issue for me. The HAL code first sets FMODE to indirect write, sets the address, then sets FMODE to indirect read and re-writes the address register (AR), so basically this:

    QUADSPI->CCR =
    0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled
    | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction
    | 0 << QUADSPI_CCR_FMODE_Pos // indirect write mode
    ...
    ...
    QUADSPI->ABR = 0; // alternate byte: disable continuous read mode
    QUADSPI->AR = addr; // address to read from
    QUADSPI->CCR |= (1 << QUADSPI_CCR_FMODE_Pos); // indirect read mode
    QUADSPI->AR = addr; // re-write the address to read from

@dpgeorge
Copy link
Member

@iabdalkader do you have any further updates on this, is it still working ok with the fix mentioned just above (rewrite AR after setting indirect read mode)?

On our boards we only use QSPI in memory-mapped mode and have not seen this issue.

Do you have the MPU enabled and configured for the QSPI memory-mapped region (it should be if you use the default QSPI code). It could be that the CPU is doing speculative fetch and writing to AR. Although if the bug is 100% reproducible with the same sequence of events then it's unlikely to be speculative fetch.

Reading the H7 errata, it doesn't seem any of the QSPI errata apply to our driver, although some are very close...

In the end I'd be happy to apply the patch you suggest because it looks harmless.

@iabdalkader
Copy link
Contributor Author
iabdalkader commented Jan 12, 2020

Hi, yes that patch is still working as far as I can tell the QSPI is working normally. The QSPI is used for internal flash storage (so it's not memory-mapped, and the MMU is not used). Note: the bug is reproducible, it happens with the exact same sequence and the same address, but only on Linux, my guess is the requested blocks are different between win/linux when mounting the storage.

@dpgeorge
Copy link
Member

so it's not memory-mapped, and the MMU is not used

You should be using the MPU. It should be enabled to disallow access to the QSPI region starting at 0x90000000.

@iabdalkader
Copy link
Contributor Author

I see now that I'm using an older qspi.c revision (MicroPython-1.11 + some recent patches) that predates this 8da39fd so maybe that's the issue here. I'll pull the MPU code and try again. Thanks for the hint.

@iabdalkader
Copy link
Contributor Author

Hi I just tested the QSPI again with MPU enabled and without that patch, and it still gets stuck at the same address, in Linux when the storage is mounted...

Program received signal SIGTRAP, Trace/breakpoint trap.
0x0812d2fc in qspi_read_cmd_qaddr_qdata (self_in=0x81eda48 <qspi_bus>, cmd=235 '\353', addr=16642048, len=2048, 
    dest=0x2407ac00 '\377' <repeats 200 times>...) at qspi.c:314
314	            while (!(QUADSPI->SR & QUADSPI_SR_FTF)) {

tannewt pushed a commit to tannewt/circuitpython that referenced this issue Oct 13, 2021
…100-update

changing MICROPY_HW_BOARD_NAME from Dongle to DK
iabdalkader added a commit to iabdalkader/micropython that referenced this issue Apr 13, 2022
* See issue micropython#5441.
* This issue is now reproducible with upstream Micropython
on the Arduino Portenta H747, QSPI flash PN MX25L12833F.
iabdalkader added a commit to iabdalkader/micropython that referenced this issue Apr 13, 2022
* See issue micropython#5441.
* This issue is now reproducible with upstream Micropython
on the Arduino Portenta H747, QSPI flash PN MX25L12833F.
iabdalkader added a commit to iabdalkader/micropython that referenced this issue Apr 13, 2022
* See issue micropython#5441.
* This issue is now reproducible with upstream Micropython
on the Arduino Portenta H747, QSPI flash PN MX25L12833F.
iabdalkader added a commit to iabdalkader/micropython that referenced this issue Apr 19, 2022
* See issue micropython#5441.
* This issue is now reproducible with upstream Micropython
on the Arduino Portenta H747, QSPI flash PN MX25L12833F.
iabdalkader added a commit to iabdalkader/micropython that referenced this issue Apr 19, 2022
* See issue micropython#5441.
* This issue is now reproducible with upstream Micropython
on the Arduino Portenta H747, QSPI flash PN MX25L12833F.
iabdalkader added a commit to iabdalkader/micropython that referenced this issue Apr 20, 2022
* See issue micropython#5441.
* This issue is now reproducible with upstream Micropython
on the Arduino Portenta H747, QSPI flash PN MX25L12833F.
dpgeorge pushed a commit that referenced this issue Apr 26, 2022
See issue #5441.  This issue is now reproducible on the Arduino Portenta
H747, QSPI flash PN MX25L12833F.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants
0