@@ -434,14 +434,29 @@ static const uint8_t device_id[] = {0x20, 0xba, 0x18};
434434// Request flash device ID.
435435static 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+
437454pbio_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+
462505pbio_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