Fatfs problems Nucleo F401 RE

Hi Zerynth Team.

I have questions about fatfs.

Board Nucleo-F401RE, FreeRTOS, license Premium.
SD card is succesfully mounted after call: fatfs.mount(‘0:’, {“drv”: SPI0, “cs”: D10, “clock”: 1000000} )

  1. When I open existing file with ‘r’, ‘+’ or ‘w+’ option, it works properly.
    But call: f = os.open(‘file0’, ‘a’) allways causes hard fault:

Hard Fault Dump
target st_nucleof401re
version r20.07.07

R0: 0xFF7100F4
R1: 0x16
R2: 0x300
R3: 0x50
R12: 0x20016C04
LR: 0x800AD67
PC: 0x800A7A4
PSR: 0x610F004A

  1. There are two threads.
    First thread writes data into file periodically and it works OK.
    Second thread reads data from the same file, as reported below.

main.py

import sd
try:
mem = sd.sd(s0)
except Exception as e:
print(e)
thr0r = threading.Thread(target=mem.fileRead, name=‘0r’, args=(‘file0’, dir0Lock, 3017))
thr0r.start()

sd.py

import fatfs
import os
class sd:
def init(self, s0):
fatfs.mount(‘0:’, {“drv”: SPI0, “cs”: D10, “clock”: 5000000} )
os.listdir(’.’)
sleep(500)

def fileRead(self, fileName, lock, delay):
    while True:
        try:
            lock.acquire()
            f = os.open(fileName, 'r')
            print("R1::: ", end='')
            fileSize = f.size() 
	**f.seek(0, 2)**	
            f.close()
            print(fileName, str(fileSize) + "B", stream=self.s0)
            lock.release()
        except Exception as e:
            print(e)
        sleep(delay)

Problems.
When file size becomes greather than 32768 bytes, READ thread and program hangs.
Console view:
WRITE: W1::: file0 32575B 8
READ: R1::: file0 32575B
WRITE: W1::: file0 32750B 9
READ: R1::: file0 32750B
WRITE: W1::: file0 32925B 10

After restart, program hangs after first read (WRITE thread is temporary off):
Console view:
READ: R1::: file0 33100B

But if I comment the line f.seek(0, 2) everything again works OK.
Console view:
WRITE: W1::: file0 33275B 0
READ: R1::: file0 33275B
WRITE: W1::: file0 33450B 1
READ: R1::: file0 33450B
WRITE: W1::: file0 33625B 2
READ: R1::: file0 33625B
WRITE: W1::: file0 33800B 3
WRITE: W1::: file0 33975B 4
READ: R1::: file0 33975B
WRITE: W1::: file0 34150B 5
READ: R1::: file0 34150B

Please help and advise on the matter.
Regards

Hello @Maciek,

sorry for the late reply. About 1 we will try to replicate the issue and come back to you asap.
Regarding 2, I need some clarifications:

  • program starts and works until 32768B (with f.seek(0,2) ON)
  • you reset the board and it hangs after first read (with f.seek(0,2) ON)
  • you uplink the same code again with f.seek(0,2) commented and it keeps on going

Is the above right? also, which version of Zerynth are you using, which version of VM and what features are enabled in the premium VM.

Thanks,

Hi Giacomo,

Yes. It is right.

Zerynth version is 2.6.0-p01, VM R20.07.07 with Secure Firmware, Powersaving and FOTA.

Regards

Hi Giacomo
The next problem I have, is with the fseek function.
Program always hangs, when the sum of bytes, which the function has written, exceeds magic numer of 32758 bytes.

def fileWrite(self, fileName, lock, led, delay):
counter = 0
while True:
try:
digitalWrite(led, 1)
print("WRITE: ", end=’’)
f = os.open(fileName, ‘+’)
f.seek(0, 2)
print("W1::: ", end=’’)
f.write(‘ABCDefghijklmnoprstuvwxz\n’ * 5, sync=True)
fileSize = f.size()
f.close()
counter += 125
print(fileName, str(fileSize) + “B”, " SUM:: ", str(counter) + “B”, stream=self.s0)
digitalWrite(led, 0)
except Exception as e:
print(“EXW:”, e)
sleep(delay)

Console view:
WRITE: W1::: file0 491075B SUM:: 32250B
WRITE: W1::: file0 491200B SUM:: 32375B
WRITE: W1::: file0 491325B SUM:: 32500B
WRITE: W1::: file0 491450B SUM:: 32625B
WRITE: W1::: file0 491575B SUM:: 32750B

The same function, without fseek(0, 2) works OK.

Regards

Hi @Maciek,

we are trying to replicate the issue. Can you print the result of f.seek and check that it is non negative?

Hi @Maciek
I am testing the feature you mentioned, Could you please attach the whole python file?

Hi Zerynth Team.

Whole code.
main.py:

dir0Lock = threading.Lock()
pinMode(A0, OUTPUT)
pinMode(A1, OUTPUT)

import sd
mem = None
try:
    mem = sd.sd(s0)
except Exception as e:
    print("EXC", e)
    while True: pass

thr0w = threading.Thread(target=mem.fileWrite,  name='0w', args=('file0', dir0Lock, A0, 1095))
thr0r = threading.Thread(target=mem.fileRead,   name='0r', args=('file0', dir0Lock, A1, 3017))

sd.py:
class sd:
def init(self, s0):
fatfs.mount(‘0:’, {“drv”: SPI0, “cs”: D10, “clock”: 5000000} )
os.listdir(’.’)
sleep(500)
self.s0 = s0

# function "write"
def fileWrite(self, fileName, lock, led, delay):
    counter = 0
    while True:
        try:
            lock.acquire()
            print("WRITE: ", end='')
            sleep(10)
            f = os.open(fileName, '+')
            f.seek(0, 2)
            print("W1::: ", end='')
            f.write('ABCDefghijklmnoprstuvwxz\n' * 20, sync=True)
            fileSize = f.size()
            f.close()
            counter += 500
            rnd = random(1, 15)
            print(fileName, str(fileSize) + "B", " SUM:: ", str(counter) + "B", stream=self.s0)
            lock.release()
        except Exception as e:
            print("EXW:", e)
        sleep(delay)    

def fileRead(self, fileName, lock, led, delay):
    counter = 0
    while True:
        try:
            lock.acquire()
            print("READ:  ", end='')
            f = os.open(fileName, 'r')
            print("R1::: ", end='')
            fileSize = f.size() 
            if fileSize > 26:
                f.seek(-26, 2)
                rec = f.read(6)
            f.close()
            print(fileName, str(fileSize) + "B", counter, rec, stream=self.s0)
            counter += 1
            lock.release()
        except Exception as e:
            print("EXR:", e)
        sleep(delay)

I’ve tested some changes in the program and the current situation is this.

Case 1

Function “write”.
Start thread:
thr0w.start()

Console view.
Program hangs after writing 32 kB:
WRITE: W1::: file0 7930750B SUM:: 500B
WRITE: W1::: file0 7931250B SUM:: 1000B

WRITE: W1::: file0 7831250B SUM:: 32000B
WRITE: W1::: file0 7831750B SUM:: 32500B

Case 2
“write” function with commented out f.seek line (0, 2)
Start thread:
thr0w.start()

Console view.
Program works fine.
WRITE: W1::: file0 8085250B SUM:: 500B
WRITE: W1::: file0 8085250B SUM:: 1000B

WRITE: W1::: file0 8085250B SUM:: 32000B
WRITE: W1::: file0 8085250B SUM:: 32500B
WRITE: W1::: file0 8085250B SUM:: 33000B
WRITE: W1::: file0 8085250B SUM:: 33500B

Case 3

Original “write” function with f.seek line enabled (0, 2).
Function fileRead also without changes.
Start threads:
thr0w.start(PRIO_NORMAL, 2048)
thr0r.start(PRIO_NORMAL, 2048)

Console view.
Program works fine.
WRITE: W1::: file0 9785250B SUM:: 500B
READ: R1::: file0 9785250B 0
ABCDe
WRITE: W1::: file0 9785750B SUM:: 1000B
WRITE: W1::: file0 9786250B SUM:: 1500B
WRITE: W1::: file0 9786750B SUM:: 2000B
READ: R1::: file0 9786750B 1
ABCDe

WRITE: W1::: file0 9816250B SUM:: 31500B
WRITE: W1::: file0 9816750B SUM:: 32000B
WRITE: W1::: file0 9817250B SUM:: 32500B
READ: R1::: file0 9817250B 24
ABCDe
WRITE: W1::: file0 9817750B SUM:: 33000B
WRITE: W1::: file0 9818250B SUM:: 33500B
WRITE: W1::: file0 9818750B SUM:: 34000B
READ: R1::: file0 9818750B 25
ABCDe

It seems that ‘fseek’ related problem occurs when the treads
are started with the default ‘size’ parameters.

Regards,
Maciek

Hello @Maciek,

thanks for your report. The problem seems indeed in the thread stack size for F401RE and not in the fatfs library itself. We will update the default stack size in the next Zerynth release.

Hi Giacomo
Unfortunately, I still have a problem with fatfs.

import fatfs 
import os
fatfs.mount('0:', {"drv": SPI0, "cs": D10, "clock": 5000000} )
os.listdir('.')
sleep(500)

This program works fine:

if not os.exists('0:/dir0'):
    os.mkdir('0:/dir0')

os.chdir('0:/dir0')
print("0::", os.listdir('.'))
if os.exists('file0'):
    os.remove('file0')
print("1::", os.listdir('.'))
sleep(100)
if not os.exists('file0'):
    f = os.open('file0', 'w+')
    f.close()
print("2::", os.listdir('.'))

Console view:
0:: [file0]
1:: []
2:: [file0]

But this doesn’t:
if not os.exists(‘0:/dir0’):
os.mkdir(‘0:/dir0’)

# os.chdir('0:/dir0')
print("0::", os.listdir('0:/dir0'))
if os.exists('0:/dir0/file0'):
    os.remove('0:/dir0/file0')
........

Console view:
empty - program hangs near line ‘print(“0::”, os.listdir(‘0:/dir0’))’

Also this doesn’t work:
if not os.exists(‘0:/dir0’):
os.mkdir(‘0:/dir0’)

# os.chdir('0:/dir0')
# print("0::", os.listdir('0:/dir0'))
if os.exists('0:/dir0/file0'):
    os.remove('0:/dir0/file0')
.........

Console view:
Hard Fault Dump
target st_nucleof401re
version r20.07.07
===============
R0: 0xFF7100F4
R1: 0x16
R2: 0x300
R3: 0x50
R12: 0x20016C0C
LR: 0x800AD67
PC: 0x800A7A4
PSR: 0x610F004A
===============

Is there a problem with absolute paths and/or listdir function?
BTW, without line ‘os.listdir(’.’)’, the code below also causes hard fault(?).

import fatfs 
import os
fatfs.mount('0:', {"drv": SPI0, "cs": D10, "clock": 5000000} )
# os.listdir('.')
sleep(500)

if not os.exists('0:/dir0'):
    os.mkdir('0:/dir0')
........

Console view:
Hard Fault Dump
target st_nucleof401re
version r20.07.07
===============
R0: 0x2147
R1: 0x20017F54
R2: 0x801DF290
R3: 0x20000B24
R12: 0x40026408
LR: 0x8009A77
PC: 0x800AEEE
PSR: 0xA100000F

Regards,
Maciek