diff options
| author | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-05-12 14:47:39 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-05-12 14:47:39 -0700 |
| commit | e1a6f6d5841b0da2bd9289b41816fc620a91b3b7 (patch) | |
| tree | c3b014d2a6669b6b09feee1f6e4866e3c424b25d | |
| parent | 7ea76e0889d3f11960056cfca3bde77a3b70c33e (diff) | |
atmel-samd: Rework SPI flash defines for clarity.
Also add sector protection support for the SAMD Xplained board.
| -rw-r--r-- | atmel-samd/Makefile | 1 | ||||
| -rw-r--r-- | atmel-samd/access_vfs.c | 14 | ||||
| -rw-r--r-- | atmel-samd/boards/circuitplayground_express/mpconfigboard.h | 2 | ||||
| -rw-r--r-- | atmel-samd/boards/feather_m0_express/mpconfigboard.h | 2 | ||||
| -rw-r--r-- | atmel-samd/boards/flash_AT25DF081A.h | 52 | ||||
| -rw-r--r-- | atmel-samd/boards/flash_S25FL216K.h | 48 | ||||
| -rw-r--r-- | atmel-samd/boards/metro_m0_express/mpconfigboard.h | 2 | ||||
| -rw-r--r-- | atmel-samd/internal_flash.c | 18 | ||||
| -rw-r--r-- | atmel-samd/internal_flash.h | 2 | ||||
| -rw-r--r-- | atmel-samd/mpconfigport.h | 2 | ||||
| -rw-r--r-- | atmel-samd/spi_flash.c | 145 |
11 files changed, 205 insertions, 83 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 61f6ea887..806948105 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -73,6 +73,7 @@ INC += $(addprefix -Iasf/sam0/,\ utils/preprocessor \ ) INC += -Iasf/thirdparty/CMSIS/Include +INC += -Iboards INC += -Iboards/$(BOARD)/ INC += -Ifreetouch/ INC += -I$(BUILD) diff --git a/atmel-samd/access_vfs.c b/atmel-samd/access_vfs.c index a8cb33e9c..7af19857a 100644 --- a/atmel-samd/access_vfs.c +++ b/atmel-samd/access_vfs.c @@ -126,7 +126,7 @@ bool vfs_unload(bool unload) //! Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector) { - uint8_t sector_buffer[FLASH_BLOCK_SIZE]; + uint8_t sector_buffer[FILESYSTEM_BLOCK_SIZE]; for (uint16_t sector = 0; sector < nb_sector; sector++) { DRESULT result = disk_read(VFS_INDEX, sector_buffer, addr + sector, 1); if (result == RES_PARERR) { @@ -135,7 +135,7 @@ Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector) if (result == RES_ERROR) { return CTRL_FAIL; } - if (!udi_msc_trans_block(true, sector_buffer, FLASH_BLOCK_SIZE, NULL)) { + if (!udi_msc_trans_block(true, sector_buffer, FILESYSTEM_BLOCK_SIZE, NULL)) { return CTRL_FAIL; // transfer aborted } } @@ -155,9 +155,9 @@ Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector) //! Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector) { - uint8_t sector_buffer[FLASH_BLOCK_SIZE]; + uint8_t sector_buffer[FILESYSTEM_BLOCK_SIZE]; for (uint16_t sector = 0; sector < nb_sector; sector++) { - if (!udi_msc_trans_block(false, sector_buffer, FLASH_BLOCK_SIZE, NULL)) { + if (!udi_msc_trans_block(false, sector_buffer, FILESYSTEM_BLOCK_SIZE, NULL)) { return CTRL_FAIL; // transfer aborted } uint32_t sector_address = addr + sector; @@ -174,13 +174,13 @@ Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector) volatile uint16_t x = addr; (void) x; #if _MAX_SS != _MIN_SS - if (vfs->ssize == FLASH_BLOCK_SIZE) { + if (vfs->ssize == FILESYSTEM_BLOCK_SIZE) { #else // The compiler can optimize this away. - if (_MAX_SS == FLASH_BLOCK_SIZE) { + if (_MAX_SS == FILESYSTEM_BLOCK_SIZE) { #endif if (sector_address == vfs->fatfs.winsect && sector_address > 0) { - memcpy(vfs->fatfs.win, sector_buffer, FLASH_BLOCK_SIZE); + memcpy(vfs->fatfs.win, sector_buffer, FILESYSTEM_BLOCK_SIZE); } } } diff --git a/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index c31e7f8eb..4eb124adf 100644 --- a/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -38,4 +38,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000) +#include "flash_S25FL216K.h" + #define CALIBRATE_CRYSTALLESS 1 diff --git a/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/atmel-samd/boards/feather_m0_express/mpconfigboard.h index 93ec565bd..4f787aef6 100644 --- a/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -26,3 +26,5 @@ #include "spi_flash.h" #define BOARD_FLASH_SIZE (0x00040000 - 0x2000) + +#include "flash_S25FL216K.h" diff --git a/atmel-samd/boards/flash_AT25DF081A.h b/atmel-samd/boards/flash_AT25DF081A.h new file mode 100644 index 000000000..436f7e36c --- /dev/null +++ b/atmel-samd/boards/flash_AT25DF081A.h @@ -0,0 +1,52 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_AT25DF081A_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_AT25DF081A_H__ + +// Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21 +// Xplained board. +// Datasheet: https://www.adestotech.com/wp-content/uploads/doc8715.pdf + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 20) // 2 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. The data sheet calls +// them something else so we just match it byte for byte. +#define SPI_FLASH_JEDEC_MANUFACTURER 0x1F +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x45 +#define SPI_FLASH_JEDEC_CAPACITY 0x01 + +#define SPI_FLASH_SECTOR_PROTECTION + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_AT25DF081A_H__ diff --git a/atmel-samd/boards/flash_S25FL216K.h b/atmel-samd/boards/flash_S25FL216K.h new file mode 100644 index 000000000..ed4fe8433 --- /dev/null +++ b/atmel-samd/boards/flash_S25FL216K.h @@ -0,0 +1,48 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H__ + +// Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash. +// Datasheet: http://www.cypress.com/file/197346/download + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 21) // 2 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 +#define SPI_FLASH_JEDEC_CAPACITY 0x15 + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H__ diff --git a/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/atmel-samd/boards/metro_m0_express/mpconfigboard.h index 728169957..49da728dc 100644 --- a/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -28,3 +28,5 @@ #include "spi_flash.h" #define BOARD_FLASH_SIZE (0x00040000 - 0x2000) + +#include "flash_S25FL216K.h" diff --git a/atmel-samd/internal_flash.c b/atmel-samd/internal_flash.c index 9046edc4c..f0ef921d2 100644 --- a/atmel-samd/internal_flash.c +++ b/atmel-samd/internal_flash.c @@ -43,7 +43,7 @@ #define INTERNAL_FLASH_MEM_SEG1_START_ADDR (0x00040000 - TOTAL_INTERNAL_FLASH_SIZE) #define INTERNAL_FLASH_PART1_START_BLOCK (0x1) -#define INTERNAL_FLASH_PART1_NUM_BLOCKS (TOTAL_INTERNAL_FLASH_SIZE / INTERNAL_FLASH_BLOCK_SIZE) +#define INTERNAL_FLASH_PART1_NUM_BLOCKS (TOTAL_INTERNAL_FLASH_SIZE / FILESYSTEM_BLOCK_SIZE) void internal_flash_init(void) { // Activity LED for flash writes. @@ -58,7 +58,7 @@ void internal_flash_init(void) { } uint32_t internal_flash_get_block_size(void) { - return INTERNAL_FLASH_BLOCK_SIZE; + return FILESYSTEM_BLOCK_SIZE; } uint32_t internal_flash_get_block_count(void) { @@ -112,7 +112,7 @@ static int32_t convert_block_to_flash_addr(uint32_t block) { if (INTERNAL_FLASH_PART1_START_BLOCK <= block && block < INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS) { // a block in partition 1 block -= INTERNAL_FLASH_PART1_START_BLOCK; - return INTERNAL_FLASH_MEM_SEG1_START_ADDR + block * INTERNAL_FLASH_BLOCK_SIZE; + return INTERNAL_FLASH_MEM_SEG1_START_ADDR + block * FILESYSTEM_BLOCK_SIZE; } // bad block return -1; @@ -147,7 +147,7 @@ bool internal_flash_read_block(uint8_t *dest, uint32_t block) { enum status_code error_code; // A block is made up of multiple pages. Read each page // sequentially. - for (int i = 0; i < INTERNAL_FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) { + for (int i = 0; i < FILESYSTEM_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) { do { error_code = nvm_read_buffer(src + i * NVMCTRL_PAGE_SIZE, @@ -195,7 +195,7 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) { // A block is made up of multiple pages. Write each page // sequentially. - for (int i = 0; i < INTERNAL_FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) { + for (int i = 0; i < FILESYSTEM_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) { do { error_code = nvm_write_buffer(dest + i * NVMCTRL_PAGE_SIZE, @@ -216,7 +216,7 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) { mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_read_block(dest + i * INTERNAL_FLASH_BLOCK_SIZE, block_num + i)) { + if (!internal_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error } } @@ -225,7 +225,7 @@ mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_write_block(src + i * INTERNAL_FLASH_BLOCK_SIZE, block_num + i)) { + if (!internal_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error } } @@ -251,7 +251,7 @@ STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_ STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE); + mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); @@ -259,7 +259,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_fla STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE); + mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); diff --git a/atmel-samd/internal_flash.h b/atmel-samd/internal_flash.h index d8bc8c67b..52ae4c9f1 100644 --- a/atmel-samd/internal_flash.h +++ b/atmel-samd/internal_flash.h @@ -32,8 +32,6 @@ #define FLASH_ROOT_POINTERS -#define INTERNAL_FLASH_BLOCK_SIZE (512) - #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms #define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2) diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index f66feb4ce..166f257ef 100644 --- a/atmel-samd/mpconfigport.h +++ b/atmel-samd/mpconfigport.h @@ -76,7 +76,7 @@ // size. // #define MICROPY_FATFS_MAX_SS (4096) -#define FLASH_BLOCK_SIZE (512) +#define FILESYSTEM_BLOCK_SIZE (512) #define MICROPY_VFS_FAT (1) #define MICROPY_PY_MACHINE (1) diff --git a/atmel-samd/spi_flash.c b/atmel-samd/spi_flash.c index 812e4359e..da986ecac 100644 --- a/atmel-samd/spi_flash.c +++ b/atmel-samd/spi_flash.c @@ -52,20 +52,12 @@ #define CMD_PAGE_PROGRAM 0x02 // #define CMD_PAGE_PROGRAM CMD_READ_JEDEC_ID #define CMD_READ_STATUS 0x05 +#define CMD_WRITE_STATUS_BYTE1 0x01 static bool spi_flash_is_initialised = false; struct spi_module spi_flash_instance; -// The total size of the flash. -static uint32_t flash_size; - -// The erase sector size. -static uint32_t sector_size; - -// The page size. Its the maximum number of bytes that can be written at once. -static uint32_t page_size; - // The currently cached sector in the cache, ram or flash based. static uint32_t current_sector; @@ -74,7 +66,7 @@ static uint32_t current_sector; static uint32_t dirty_mask; // Address of the scratch flash sector. -#define SCRATCH_SECTOR (flash_size - sector_size) +#define SCRATCH_SECTOR (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) // Enable the flash over SPI. static void flash_enable(void) { @@ -92,7 +84,7 @@ static bool wait_for_flash_ready(void) { uint8_t response[2] = {0x00, 0x01}; enum status_code status = STATUS_OK; // Both the write enable and write in progress bits should be low. - while (status == STATUS_OK && ((response[1] & 0x1) == 1 || (response[1] & 0x2) == 2)) { + while (status == STATUS_OK && (response[1] & 0x3) != 0) { flash_enable(); status = spi_transceive_buffer_wait(&spi_flash_instance, status_request, response, 2); flash_disable(); @@ -118,7 +110,12 @@ static void address_to_bytes(uint32_t address, uint8_t* bytes) { // Read data_length's worth of bytes starting at address into data. static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { - wait_for_flash_ready(); + if (!spi_flash_is_initialised) { + return false; + } + if (!wait_for_flash_ready()) { + return false; + } enum status_code status; // We can read as much as we want sequentially. uint8_t read_request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; @@ -136,22 +133,30 @@ static bool read_flash(uint32_t address, uint8_t* data, uint32_t data_length) { // that the sector that address resides in has already been erased. So make sure // to run erase_sector. static bool write_flash(uint32_t address, const uint8_t* data, uint32_t data_length) { - if (page_size == 0) { + if (!spi_flash_is_initialised) { return false; } for (uint32_t bytes_written = 0; bytes_written < data_length; - bytes_written += page_size) { + bytes_written += SPI_FLASH_PAGE_SIZE) { if (!wait_for_flash_ready() || !write_enable()) { return false; } + enum status_code status; + + // Print out the protection status. + uint8_t protect_check[5] = {0x3C, 0x00, 0x00, 0x00, 0x00}; + address_to_bytes(address + bytes_written, protect_check + 1); + flash_enable(); + status = spi_write_buffer_wait(&spi_flash_instance, protect_check, 5); + flash_disable(); + flash_enable(); uint8_t command[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; address_to_bytes(address + bytes_written, command + 1); - enum status_code status; status = spi_write_buffer_wait(&spi_flash_instance, command, 4); if (status == STATUS_OK) { - status = shared_dma_write(spi_flash_instance.hw, data + bytes_written, page_size); + status = shared_dma_write(spi_flash_instance.hw, data + bytes_written, SPI_FLASH_PAGE_SIZE); } flash_disable(); if (status != STATUS_OK) { @@ -182,12 +187,12 @@ static bool erase_sector(uint32_t sector_address) { // Sector is really 24 bits. static bool copy_block(uint32_t src_address, uint32_t dest_address) { // Copy page by page to minimize RAM buffer. - uint8_t buffer[page_size]; - for (uint32_t i = 0; i < FLASH_BLOCK_SIZE / page_size; i++) { - if (!read_flash(src_address + i * page_size, buffer, page_size)) { + uint8_t buffer[SPI_FLASH_PAGE_SIZE]; + for (uint32_t i = 0; i < FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; i++) { + if (!read_flash(src_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { return false; } - if (!write_flash(dest_address + i * page_size, buffer, page_size)) { + if (!write_flash(dest_address + i * SPI_FLASH_PAGE_SIZE, buffer, SPI_FLASH_PAGE_SIZE)) { return false; } } @@ -226,15 +231,27 @@ void spi_flash_init(void) { flash_enable(); spi_transceive_buffer_wait(&spi_flash_instance, jedec_id_request, response, 4); flash_disable(); - if (response[1] == 0x01 && response[2] == 0x40 && response[3] == 0x15) { - flash_size = 1 << 21; // 2 MiB - sector_size = 1 << 12; // 4 KiB - page_size = 256; // 256 bytes + if (response[1] == SPI_FLASH_JEDEC_MANUFACTURER && + response[2] == SPI_FLASH_JEDEC_MEMORY_TYPE && + response[3] == SPI_FLASH_JEDEC_CAPACITY) { + spi_flash_is_initialised = true; } else { // Unknown flash chip! - flash_size = 0; + spi_flash_is_initialised = false; + return; } + #ifdef SPI_FLASH_SECTOR_PROTECTION + write_enable(); + + // Turn off sector protection + uint8_t disable_protect_request[2] = {CMD_WRITE_STATUS_BYTE1, 0x00}; + uint8_t disable_protect_response[2] = {0x00, 0x00}; + flash_enable(); + spi_transceive_buffer_wait(&spi_flash_instance, disable_protect_request, disable_protect_response, 2); + flash_disable(); + #endif + // Turn off writes in case this is a microcontroller only reset. uint8_t disable_write_request[1] = {CMD_DISABLE_WRITE}; uint8_t disable_response[1] = {0x00}; @@ -254,14 +271,14 @@ void spi_flash_init(void) { // The size of each individual block. uint32_t spi_flash_get_block_size(void) { - return FLASH_BLOCK_SIZE; + return FILESYSTEM_BLOCK_SIZE; } // The total number of available blocks. uint32_t spi_flash_get_block_count(void) { // We subtract one erase sector size because we may use it as a staging area // for writes. - return SPI_FLASH_PART1_START_BLOCK + (flash_size - sector_size) / FLASH_BLOCK_SIZE; + return SPI_FLASH_PART1_START_BLOCK + (SPI_FLASH_TOTAL_SIZE - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; } // Flush the cache that was written to the scratch portion of flash. Only used @@ -270,11 +287,11 @@ static bool flush_scratch_flash(void) { // First, copy out any blocks that we haven't touched from the sector we've // cached. bool copy_to_scratch_ok = true; - for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { copy_to_scratch_ok = copy_to_scratch_ok && - copy_block(current_sector + i * FLASH_BLOCK_SIZE, - SCRATCH_SECTOR + i * FLASH_BLOCK_SIZE); + copy_block(current_sector + i * FILESYSTEM_BLOCK_SIZE, + SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE); } } if (!copy_to_scratch_ok) { @@ -285,9 +302,9 @@ static bool flush_scratch_flash(void) { // Second, erase the current sector. erase_sector(current_sector); // Finally, copy the new version into it. - for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { - copy_block(SCRATCH_SECTOR + i * FLASH_BLOCK_SIZE, - current_sector + i * FLASH_BLOCK_SIZE); + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { + copy_block(SCRATCH_SECTOR + i * FILESYSTEM_BLOCK_SIZE, + current_sector + i * FILESYSTEM_BLOCK_SIZE); } return true; } @@ -296,8 +313,8 @@ static bool flush_scratch_flash(void) { // ram. Each page is allocated separately so that the GC doesn't need to provide // one huge block. We can free it as we write if we want to also. static bool allocate_ram_cache(void) { - uint8_t blocks_per_sector = sector_size / FLASH_BLOCK_SIZE; - uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; + uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; MP_STATE_VM(flash_ram_cache) = gc_alloc(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); if (MP_STATE_VM(flash_ram_cache) == NULL) { return false; @@ -309,7 +326,7 @@ static bool allocate_ram_cache(void) { bool success = true; for (i = 0; i < blocks_per_sector; i++) { for (j = 0; j < pages_per_block; j++) { - uint8_t *page_cache = gc_alloc(page_size, false); + uint8_t *page_cache = gc_alloc(SPI_FLASH_PAGE_SIZE, false); if (page_cache == NULL) { success = false; break; @@ -344,14 +361,14 @@ static bool flush_ram_cache(bool keep_cache) { // we've cached. If we don't do this we'll erase the data during the sector // erase below. bool copy_to_ram_ok = true; - uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; - for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { for (uint8_t j = 0; j < pages_per_block; j++) { copy_to_ram_ok = read_flash( - current_sector + (i * pages_per_block + j) * page_size, + current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - page_size); + SPI_FLASH_PAGE_SIZE); if (!copy_to_ram_ok) { break; } @@ -368,11 +385,11 @@ static bool flush_ram_cache(bool keep_cache) { // Second, erase the current sector. erase_sector(current_sector); // Lastly, write all the data in ram that we've cached. - for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) { for (uint8_t j = 0; j < pages_per_block; j++) { - write_flash(current_sector + (i * pages_per_block + j) * page_size, + write_flash(current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j], - page_size); + SPI_FLASH_PAGE_SIZE); if (!keep_cache) { gc_free(MP_STATE_VM(flash_ram_cache)[i * pages_per_block + j]); } @@ -460,7 +477,7 @@ static int32_t convert_block_to_flash_addr(uint32_t block) { if (SPI_FLASH_PART1_START_BLOCK <= block && block < spi_flash_get_block_count()) { // a block in partition 1 block -= SPI_FLASH_PART1_START_BLOCK; - return block * FLASH_BLOCK_SIZE; + return block * FILESYSTEM_BLOCK_SIZE; } // bad block return -1; @@ -485,7 +502,7 @@ bool spi_flash_read_block(uint8_t *dest, uint32_t block) { return true; } else if (block < SPI_FLASH_PART1_START_BLOCK) { - memset(dest, 0, FLASH_BLOCK_SIZE); + memset(dest, 0, FILESYSTEM_BLOCK_SIZE); return true; } else { // Non-MBR block, get data from flash memory. @@ -496,25 +513,25 @@ bool spi_flash_read_block(uint8_t *dest, uint32_t block) { } // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(sector_size - 1)); - uint8_t block_index = (address / FLASH_BLOCK_SIZE) % (sector_size / FLASH_BLOCK_SIZE); + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); uint8_t mask = 1 << (block_index); // We're reading from the currently cached sector. if (current_sector == this_sector && (mask & dirty_mask) > 0) { if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; for (int i = 0; i < pages_per_block; i++) { - memcpy(dest + i * page_size, + memcpy(dest + i * SPI_FLASH_PAGE_SIZE, MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - page_size); + SPI_FLASH_PAGE_SIZE); } return true; } else { - uint32_t scratch_address = SCRATCH_SECTOR + block_index * FLASH_BLOCK_SIZE; - return read_flash(scratch_address, dest, FLASH_BLOCK_SIZE); + uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; + return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); } } - return read_flash(address, dest, FLASH_BLOCK_SIZE); + return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); } } @@ -532,8 +549,8 @@ bool spi_flash_write_block(const uint8_t *data, uint32_t block) { // Wait for any previous writes to finish. wait_for_flash_ready(); // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(sector_size - 1)); - uint8_t block_index = (address / FLASH_BLOCK_SIZE) % (sector_size / FLASH_BLOCK_SIZE); + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); uint8_t mask = 1 << (block_index); // Flush the cache if we're moving onto a sector our we're writing the // same block again. @@ -551,23 +568,23 @@ bool spi_flash_write_block(const uint8_t *data, uint32_t block) { dirty_mask |= mask; // Copy the block to the appropriate cache. if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; for (int i = 0; i < pages_per_block; i++) { memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - data + i * page_size, - page_size); + data + i * SPI_FLASH_PAGE_SIZE, + SPI_FLASH_PAGE_SIZE); } return true; } else { - uint32_t scratch_address = SCRATCH_SECTOR + block_index * FLASH_BLOCK_SIZE; - return write_flash(scratch_address, data, FLASH_BLOCK_SIZE); + uint32_t scratch_address = SCRATCH_SECTOR + block_index * FILESYSTEM_BLOCK_SIZE; + return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); } } } mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { - if (!spi_flash_read_block(dest + i * FLASH_BLOCK_SIZE, block_num + i)) { + if (!spi_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error } } @@ -576,7 +593,7 @@ mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_ mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { - if (!spi_flash_write_block(src + i * FLASH_BLOCK_SIZE, block_num + i)) { + if (!spi_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error } } @@ -602,7 +619,7 @@ STATIC mp_obj_t spi_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, STATIC mp_obj_t spi_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = spi_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE); + mp_uint_t ret = spi_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_readblocks_obj, spi_flash_obj_readblocks); @@ -610,7 +627,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_readblocks_obj, spi_flash_obj_rea STATIC mp_obj_t spi_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = spi_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE); + mp_uint_t ret = spi_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_writeblocks_obj, spi_flash_obj_writeblocks); |
