Skip to content

Commit 859c996

Browse files
committed
pbio/drv/block_device/block_device_ev3: Implement flash reading and writing
This completes the storage implementation for EV3.
1 parent 952522c commit 859c996

File tree

1 file changed

+87
-9
lines changed

1 file changed

+87
-9
lines changed

lib/pbio/drv/block_device/block_device_ev3.c

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,29 @@ static const uint8_t device_id[] = {0x20, 0xba, 0x18};
434434
// Request flash device ID.
435435
static const uint8_t cmd_rdid[] = {FLASH_CMD_GET_ID, 0x00, 0x00, 0x00};
436436

437+
// Request the write-status byte.
438+
static const uint8_t cmd_status[] = {FLASH_CMD_GET_STATUS, 0x00};
439+
440+
// Enable flash writing. Needed once before each write operation.
441+
static const uint8_t cmd_write_enable[] = {FLASH_CMD_WRITE_ENABLE};
442+
443+
// Request reading from address. Buffer: read command + address + dummy byte.
444+
// Should be followed by another command that reads the data.
445+
static uint8_t read_address[4] = {FLASH_CMD_READ_DATA};
446+
447+
// Request page write at address. Buffer: write command + address.
448+
// Should be followed by the data.
449+
static uint8_t write_address[4] = {FLASH_CMD_WRITE_DATA};
450+
451+
// Request sector erase at address. Buffer: erase command + address.
452+
static uint8_t erase_address[4] = {FLASH_CMD_ERASE_BLOCK};
453+
437454
pbio_error_t pbdrv_block_device_read(pbio_os_state_t *state, uint32_t offset, uint8_t *buffer, uint32_t size) {
438455

439456
static uint32_t size_done;
440457
static uint32_t size_now;
441458
pbio_error_t err;
442459

443-
(void)err;
444-
445460
PBIO_OS_ASYNC_BEGIN(state);
446461

447462
// Exit on invalid size.
@@ -453,21 +468,48 @@ pbio_error_t pbdrv_block_device_read(pbio_os_state_t *state, uint32_t offset, ui
453468
for (size_done = 0; size_done < size; size_done += size_now) {
454469
size_now = pbio_int_math_min(size - size_done, FLASH_SIZE_READ);
455470

456-
// TODO: Actually implement reading
471+
// Set address for this read request and send it.
472+
set_address_be(&read_address[1], PBDRV_CONFIG_BLOCK_DEVICE_EV3_START_ADDRESS + offset + size_done);
473+
err = spi_begin_for_flash(read_address, sizeof(read_address), 0, buffer + size_done, size_now);
474+
if (err != PBIO_SUCCESS) {
475+
return err;
476+
}
477+
PBIO_OS_AWAIT_WHILE(state, bdev.spi_status & SPI_STATUS_WAIT_ANY);
457478
}
458479

459480
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
460481
}
461482

483+
/**
484+
* Poll the status register waiting for writes to complete.
485+
*/
486+
static pbio_error_t flash_wait_write(pbio_os_state_t *state) {
487+
uint8_t status;
488+
pbio_error_t err;
489+
490+
PBIO_OS_ASYNC_BEGIN(state);
491+
492+
do {
493+
err = spi_begin_for_flash(cmd_status, sizeof(cmd_status), 0, 0, 0);
494+
if (err != PBIO_SUCCESS) {
495+
return err;
496+
}
497+
PBIO_OS_AWAIT_WHILE(state, bdev.spi_status & SPI_STATUS_WAIT_ANY);
498+
499+
status = bdev.spi_cmd_buf_rx[1];
500+
} while (status & FLASH_STATUS_BUSY);
501+
502+
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
503+
}
504+
462505
pbio_error_t pbdrv_block_device_store(pbio_os_state_t *state, uint8_t *buffer, uint32_t size) {
463506

507+
static pbio_os_state_t sub;
464508
static uint32_t offset;
465509
static uint32_t size_now;
466510
static uint32_t size_done;
467511
pbio_error_t err;
468512

469-
(void)err;
470-
471513
PBIO_OS_ASYNC_BEGIN(state);
472514

473515
// Exit on invalid size.
@@ -477,14 +519,52 @@ pbio_error_t pbdrv_block_device_store(pbio_os_state_t *state, uint8_t *buffer, u
477519

478520
// Erase sector by sector.
479521
for (offset = 0; offset < size; offset += FLASH_SIZE_ERASE) {
480-
// TODO: Actually implement erasing
522+
// Enable writing
523+
err = spi_begin_for_flash(cmd_write_enable, sizeof(cmd_write_enable), 0, 0, 0);
524+
if (err != PBIO_SUCCESS) {
525+
return err;
526+
}
527+
PBIO_OS_AWAIT_WHILE(state, bdev.spi_status & SPI_STATUS_WAIT_ANY);
528+
529+
// Erase this block
530+
set_address_be(&erase_address[1], PBDRV_CONFIG_BLOCK_DEVICE_EV3_START_ADDRESS + offset);
531+
err = spi_begin_for_flash(erase_address, sizeof(erase_address), 0, 0, 0);
532+
if (err != PBIO_SUCCESS) {
533+
return err;
534+
}
535+
PBIO_OS_AWAIT_WHILE(state, bdev.spi_status & SPI_STATUS_WAIT_ANY);
536+
537+
// Wait for completion
538+
PBIO_OS_AWAIT(state, &sub, err = flash_wait_write(&sub));
539+
if (err != PBIO_SUCCESS) {
540+
return err;
541+
}
481542
}
482543

483544
// Write page by page.
484545
for (size_done = 0; size_done < size; size_done += size_now) {
485546
size_now = pbio_int_math_min(size - size_done, FLASH_SIZE_WRITE);
486547

487-
// TODO: Actually implement writing
548+
// Enable writing
549+
err = spi_begin_for_flash(cmd_write_enable, sizeof(cmd_write_enable), 0, 0, 0);
550+
if (err != PBIO_SUCCESS) {
551+
return err;
552+
}
553+
PBIO_OS_AWAIT_WHILE(state, bdev.spi_status & SPI_STATUS_WAIT_ANY);
554+
555+
// Write this block
556+
set_address_be(&write_address[1], PBDRV_CONFIG_BLOCK_DEVICE_EV3_START_ADDRESS + size_done);
557+
err = spi_begin_for_flash(write_address, sizeof(write_address), buffer + size_done, 0, size_now);
558+
if (err != PBIO_SUCCESS) {
559+
return err;
560+
}
561+
PBIO_OS_AWAIT_WHILE(state, bdev.spi_status & SPI_STATUS_WAIT_ANY);
562+
563+
// Wait for completion
564+
PBIO_OS_AWAIT(state, &sub, err = flash_wait_write(&sub));
565+
if (err != PBIO_SUCCESS) {
566+
return err;
567+
}
488568
}
489569

490570
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
@@ -564,8 +644,6 @@ void pbdrv_block_device_init(void) {
564644
// Enable!
565645
SPIEnable(SOC_SPI_0_REGS);
566646

567-
(void)set_address_be;
568-
569647
bdev.spi_status = SPI_STATUS_COMPLETE;
570648

571649
pbdrv_init_busy_up();

0 commit comments

Comments
 (0)