Skip to content

Commit 17458ad

Browse files
authored
Merge pull request #2662 from jepler/issue2332
Fix unaligned disk reads properly
2 parents 2e37000 + eef742b commit 17458ad

File tree

4 files changed

+43
-13
lines changed

4 files changed

+43
-13
lines changed

lib/oofatfs/ff.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,11 +3382,7 @@ FRESULT f_read (
33823382
if (!sect) ABORT(fs, FR_INT_ERR);
33833383
sect += csect;
33843384
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
3385-
if (cc
3386-
#if _FS_DISK_READ_ALIGNED
3387-
&& (((int)rbuff & 3) == 0)
3388-
#endif
3389-
) {/* Read maximum contiguous sectors directly */
3385+
if (cc) {/* Read maximum contiguous sectors directly */
33903386
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
33913387
cc = fs->csize - csect;
33923388
}

lib/oofatfs/ffconf.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,12 +343,6 @@
343343
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
344344
/ included somewhere in the scope of ff.h. */
345345

346-
// Set to nonzero if buffers passed to disk_read have a word alignment
347-
// restriction
348-
#ifndef _FS_DISK_READ_ALIGNED
349-
#define _FS_DISK_READ_ALIGNED 0
350-
#endif
351-
352346
/* #include <windows.h> // O/S definitions */
353347

354348

ports/nrf/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ CFLAGS += -Wno-undef
102102
CFLAGS += -Wno-cast-align
103103

104104
NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET
105-
NRF_DEFINES += -D_FS_DISK_READ_ALIGNED=1
106105
CFLAGS += $(NRF_DEFINES)
107106

108107
CFLAGS += \

ports/nrf/supervisor/qspi_flash.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,52 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address) {
8383
}
8484

8585
bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) {
86+
// TODO: In theory, this also needs to handle unaligned data and
87+
// non-multiple-of-4 length. (in practice, I don't think the fat layer
88+
// generates such writes)
8689
return nrfx_qspi_write(data, length, address) == NRFX_SUCCESS;
8790
}
8891

8992
bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) {
90-
return nrfx_qspi_read(data, length, address) == NRFX_SUCCESS;
93+
int misaligned = ((intptr_t)data) & 3;
94+
// If the data is misaligned, we need to read 4 bytes
95+
// into an aligned buffer, and then copy 1, 2, or 3 bytes from the aligned
96+
// buffer to data.
97+
if(misaligned) {
98+
int sz = 4 - misaligned;
99+
__attribute__((aligned(4))) uint8_t buf[4];
100+
101+
if(nrfx_qspi_read(buf, 4, address) != NRFX_SUCCESS) {
102+
return false;
103+
}
104+
memcpy(data, buf, sz);
105+
data += sz;
106+
address += sz;
107+
length -= sz;
108+
}
109+
110+
// nrfx_qspi_read works in 4 byte increments, though it doesn't
111+
// signal an error if sz is not a multiple of 4. Read (directly into data)
112+
// all but the last 1, 2, or 3 bytes depending on the (remaining) length.
113+
uint32_t sz = length & ~(uint32_t)3;
114+
if(nrfx_qspi_read(data, sz, address) != NRFX_SUCCESS) {
115+
return false;
116+
}
117+
data += sz;
118+
address += sz;
119+
length -= sz;
120+
121+
// Now, if we have any bytes left over, we must do a final read of 4
122+
// bytes and copy 1, 2, or 3 bytes to data.
123+
if(length) {
124+
__attribute__((aligned(4))) uint8_t buf[4];
125+
if(nrfx_qspi_read(buf, 4, address) != NRFX_SUCCESS) {
126+
return false;
127+
}
128+
memcpy(data, buf, length);
129+
}
130+
131+
return true;
91132
}
92133

93134
void spi_flash_init(void) {

0 commit comments

Comments
 (0)