Skip to content

Feather STM32F405 intermittent exception on close() and flush() #6082

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
RealAbsurdity opened this issue Feb 23, 2022 · 4 comments
Open

Feather STM32F405 intermittent exception on close() and flush() #6082

RealAbsurdity opened this issue Feb 23, 2022 · 4 comments
Milestone

Comments

@RealAbsurdity
Copy link

CircuitPython version

Adafruit CircuitPython 7.1.1 on 2022-01-14; Adafruit Feather STM32F405 Express with STM32F405RG
Board ID:feather_stm32f405_express

Code/REPL

# can't so the entire program... the code in the traceback is here, line 223 is the last line  

            if SDWRITE:
                # save the data to the data_log.txt file
                with open(DFN, "a") as dl:
                    dl.write(ds)
                    dl.write('\n')
                    dl.close()   # error on line 223

Behavior

Traceback (most recent call last):
File "code.py", line 223, in
OSError: [Errno 5] Input/output error

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

Description

  • Exception after writing data to a file on the local microsd card using sdioio and closing it
  • Exception is intermittent and can be caught with an exception handler
  • Error occurs intermittently when calling close() on a file
  • Same error occurs intermittently when using flush() on same file
  • Only occurs on Adafruit Feather STM32F405 Express with STM32F405RG

Additional information

Can be resolved by removing the call to close() or flush() but possibly an issue with the io.BytesIO methods

@tannewt tannewt added the stm label Feb 23, 2022
@tannewt tannewt added this to the Long term milestone Feb 23, 2022
@tannewt
Copy link
Member

tannewt commented Feb 23, 2022

Please provide a full test program that shows the issue. It's much easier to fix a full example.

dhalbert pushed a commit to dhalbert/circuitpython that referenced this issue Feb 24, 2022
Prior to this commit IRQs on STM32F4 could be lost because SR is cleared by
reading SR then reading DR.  For example, if both RXNE and IDLE IRQs were
active upon entry to the IRQ handler, then IDLE is lost because the code
that handles RXNE comes first and accidentally clears SR (by reading SR
then DR to get the incoming character).

This commit fixes this problem by making the IRQ handler more atomic in the
following operations:
- get current IRQ status flags
- deal with RX character
- clear remaining status flags
- call user handler

On the STM32F4 it's very hard to get this right because the only way to
clear IRQ status flags is to read SR then DR, but the read of DR may read
some data which should remain in the register until the user wants to read
it.  And it won't work to cache the read because RTS/CTS flow control will
then not work.  So instead the new code disables interrupts if the DR is
full and waits for the user to read it before reenabling the interrupts.

Fixes issue mentioned in adafruit#4599 and adafruit#6082.

Signed-off-by: Damien George <damien@micropython.org>
@RealAbsurdity
Copy link
Author

I will attempt to recreate with a test program that includes most of the major modules in the original program.

@RealAbsurdity
Copy link
Author

Here is a test program that replicates the issue. The exception occurs on line 33 when .close() is called.

import board
import time
import sdioio
import storage

print("Initializing Data Storage...")
# data storage setup #

# initialize sdcard and storage
sdcard = sdioio.SDCard(clock=board.SDIO_CLOCK,
                        command=board.SDIO_COMMAND,
                        data=board.SDIO_DATA,
                        frequency=25000000)

vfs = storage.VfsFat(sdcard)
# mount the storage device
storage.mount(vfs, "/sd")
print("SD card present and mounted")

DFN = "/sd/data_log.txt"
print("Saving data to:", DFN)

ds = "0000000000000000000000000000000000000000000000000000000000000000"
dc = 0

while True:

    dc += 1

    with open(DFN, "a") as dl:
        dl.write(ds)
        dl.write('\n')
        dl.close()

    print(dc)

    time.sleep(0.1)

The code will fail at various times in the sequence while trying to write a 64 character string to the storage device over sdioio.
Output to serial monitor with traceback:

soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Initializing Data Storage...
SD card present and mounted
Saving data to: /sd/data_log.txt
1
2
3
4
5
6
Traceback (most recent call last):
  File "code.py", line 33, in <module>
OSError: [Errno 5] Input/output error

Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

@tannewt
Copy link
Member

tannewt commented Feb 25, 2022

Thank you for the test program! That'll be helpful when someone has time to debug this issue.

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