Skip to content

Commit f4b4ac7

Browse files
committed
Data that is written to/read from external flash using QSPI needs to be in RAM and WORD aligned.
1 parent f56808f commit f4b4ac7

File tree

1 file changed

+47
-16
lines changed

1 file changed

+47
-16
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/qspi_api.c

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -263,17 +263,19 @@ qspi_status_t qspi_frequency(qspi_t *obj, int hz)
263263

264264
qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void *data, size_t *length)
265265
{
266-
// length needs to be rounded up to the next WORD (4 bytes)
267-
if ((*length & WORD_MASK) > 0) {
266+
// flash address and buffer length must be divisible by 4
267+
if ((*length & WORD_MASK) > 0 ||
268+
(command->address.value & WORD_MASK) > 0) {
268269
return QSPI_STATUS_INVALID_PARAMETER;
269270
}
270-
271+
271272
qspi_status_t status = qspi_prepare_command(obj, command, true);
272273
if (status != QSPI_STATUS_OK) {
273274
return status;
274275
}
275276

276-
if (is_word_aligned(data)) {
277+
if (is_word_aligned(data) &&
278+
nrf_drv_is_in_RAM(data)) {
277279
// write here does not return how much it transfered, we return transfered all
278280
ret_code_t ret = nrf_drv_qspi_write(data, *length, command->address.value);
279281
if (ret == NRF_SUCCESS ) {
@@ -283,7 +285,7 @@ qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void
283285
}
284286
}
285287
else {
286-
// if the data buffer is not WORD/4-byte aligned, use an aligned buffer on the stack
288+
// if the data buffer is not WORD/4-byte aligned or in RAM, use an aligned buffer on the stack
287289
uint32_t aligned_buffer[WORD_COUNT];
288290
uint32_t pos = 0;
289291
size_t bytes_to_write = *length;
@@ -298,6 +300,7 @@ qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void
298300
if (ret != NRF_SUCCESS ) {
299301
return QSPI_STATUS_ERROR;
300302
}
303+
301304
pos += diff;
302305
bytes_to_write -= diff;
303306
}
@@ -307,28 +310,56 @@ qspi_status_t qspi_write(qspi_t *obj, const qspi_command_t *command, const void
307310

308311
qspi_status_t qspi_read(qspi_t *obj, const qspi_command_t *command, void *data, size_t *length)
309312
{
310-
// length needs to be rounded up to the next WORD (4 bytes)
311-
if ((*length & WORD_MASK) > 0) {
313+
// flash address and buffer length must be divisible by 4
314+
if ((*length & WORD_MASK) > 0 ||
315+
(command->address.value & WORD_MASK) > 0) {
312316
return QSPI_STATUS_INVALID_PARAMETER;
313317
}
314318

315319
// check to see if this is an SFDP read
316320
if (command->instruction.value == READSFDP_opcode) {
317321
qspi_status_t status = sfdp_read(obj, command, data, length );
318322
return status;
319-
} else {
320-
qspi_status_t status = qspi_prepare_command(obj, command, false);
321-
if (status != QSPI_STATUS_OK) {
322-
return status;
323+
}
324+
325+
qspi_status_t status = qspi_prepare_command(obj, command, false);
326+
if (status != QSPI_STATUS_OK) {
327+
return status;
328+
}
329+
330+
if (is_word_aligned(data) &&
331+
nrf_drv_is_in_RAM(data)) {
332+
ret_code_t ret = nrf_drv_qspi_read(data, *length, command->address.value);
333+
if (ret == NRF_SUCCESS ) {
334+
return QSPI_STATUS_OK;
335+
} else {
336+
return QSPI_STATUS_ERROR;
323337
}
324338
}
339+
else {
340+
// if the data buffer is not WORD/4-byte aligned or in RAM, use an aligned buffer on the stack
341+
uint32_t aligned_buffer[WORD_COUNT];
342+
uint32_t pos = 0;
343+
size_t bytes_to_read = *length;
325344

326-
ret_code_t ret = nrf_drv_qspi_read(data, *length, command->address.value);
327-
if (ret == NRF_SUCCESS ) {
328-
return QSPI_STATUS_OK;
329-
} else {
330-
return QSPI_STATUS_ERROR;
345+
while(pos < *length) {
346+
347+
size_t diff = bytes_to_read <= sizeof(aligned_buffer) ? bytes_to_read : sizeof(aligned_buffer);
348+
349+
// read one buffer over QSPI
350+
ret_code_t ret = nrf_drv_qspi_read(aligned_buffer, diff, command->address.value+pos);
351+
if (ret != NRF_SUCCESS ) {
352+
return QSPI_STATUS_ERROR;
353+
}
354+
355+
// copy into original read buffer
356+
memcpy(&((uint8_t *)data)[pos], aligned_buffer, diff);
357+
358+
pos += diff;
359+
bytes_to_read -= diff;
360+
}
331361
}
362+
return QSPI_STATUS_OK;
332363
}
333364

334365
qspi_status_t qspi_command_transfer(qspi_t *obj, const qspi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)

0 commit comments

Comments
 (0)