Merge remote-tracking branch 'adafruit/9.0.x' into 9.0.4-update
This commit is contained in:
commit
c35ec758dd
9 changed files with 297 additions and 76 deletions
6
conf.py
6
conf.py
|
|
@ -110,6 +110,12 @@ autoapi_template_dir = 'docs/autoapi/templates'
|
|||
autoapi_python_class_content = "both"
|
||||
autoapi_python_use_implicit_namespaces = True
|
||||
autoapi_root = "shared-bindings"
|
||||
|
||||
# Suppress cache warnings to prevent "unpickable" [sic] warning
|
||||
# about autoapi_prepare_jinja_env() from sphinx >= 7.3.0.
|
||||
# See https://github.com/sphinx-doc/sphinx/issues/12300
|
||||
suppress_warnings = ["config.cache"]
|
||||
|
||||
def autoapi_prepare_jinja_env(jinja_env):
|
||||
jinja_env.globals['support_matrix_reverse'] = modules_support_matrix_reverse
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
|
|||
// Something else might have used the ADC in a different way,
|
||||
// so we completely re-initialize it.
|
||||
|
||||
nrf_saadc_value_t value = -1;
|
||||
nrf_saadc_value_t value = 0;
|
||||
|
||||
const nrf_saadc_channel_config_t config = {
|
||||
.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
|
||||
|
|
@ -120,6 +120,17 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
|
|||
|
||||
nrf_saadc_disable(NRF_SAADC);
|
||||
|
||||
// Adding the "asm volatile" memory fence here or anywhere after the declaration of `value`
|
||||
// fixes an issue with gcc13 which causes `value` to always be zero.
|
||||
// Compiling with gcc10 or gcc12 is fine.
|
||||
// It can also be fixed by declaring `value` to be static.
|
||||
// I think I'd like to declare `value` as volatile, but that causes type errors.
|
||||
asm volatile ("" : : : "memory");
|
||||
|
||||
// Disconnect ADC from pin.
|
||||
nrf_saadc_channel_input_set(NRF_SAADC, CHANNEL_NO, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
|
||||
|
||||
// value is signed and might be (slightly) < 0, even on single-ended conversions, so force to 0.
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
}
|
||||
|
|
|
|||
81
ports/raspberrypi/boards/waveshare_rp2040_geek/board.c
Normal file
81
ports/raspberrypi/boards/waveshare_rp2040_geek/board.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include "supervisor/board.h"
|
||||
|
||||
|
||||
#include "mpconfigboard.h"
|
||||
#include "shared-module/displayio/__init__.h"
|
||||
#include "shared-module/displayio/mipi_constants.h"
|
||||
#include "shared-bindings/board/__init__.h"
|
||||
|
||||
#define DELAY 0x80
|
||||
|
||||
fourwire_fourwire_obj_t board_display_obj;
|
||||
|
||||
// display init sequence according to https://github.com/adafruit/Adafruit_CircuitPython_ST7789
|
||||
uint8_t display_init_sequence[] = {
|
||||
0x01, 0 | DELAY, 0x96, // _SWRESET and Delay 150ms
|
||||
0x11, 0 | DELAY, 0xFF, // _SLPOUT and Delay 500ms
|
||||
0x3A, 0x81, 0x55, 0x0A, // _COLMOD and Delay 10ms
|
||||
0x36, 0x01, 0x08, // _MADCTL
|
||||
0x21, 0 | DELAY, 0x0A, // _INVON Hack and Delay 10ms
|
||||
0x13, 0 | DELAY, 0x0A, // _NORON and Delay 10ms
|
||||
0x36, 0x01, 0xC0, // _MADCTL
|
||||
0x29, 0 | DELAY, 0xFF, // _DISPON and Delay 500ms
|
||||
};
|
||||
|
||||
static void display_init(void) {
|
||||
|
||||
busio_spi_obj_t *spi = common_hal_board_create_spi(0);
|
||||
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
|
||||
|
||||
bus->base.type = &fourwire_fourwire_type;
|
||||
|
||||
common_hal_fourwire_fourwire_construct(
|
||||
bus,
|
||||
spi,
|
||||
&pin_GPIO8, // TFT_DC
|
||||
&pin_GPIO9, // TFT_CS
|
||||
&pin_GPIO12, // TFT_RST
|
||||
50000000, // Baudrate
|
||||
0, // Polarity
|
||||
0 // Phase
|
||||
|
||||
);
|
||||
|
||||
busdisplay_busdisplay_obj_t *display = &allocate_display()->display;
|
||||
display->base.type = &busdisplay_busdisplay_type;
|
||||
|
||||
common_hal_busdisplay_busdisplay_construct(
|
||||
display,
|
||||
bus,
|
||||
240, // Width
|
||||
135, // Height
|
||||
53, // column start
|
||||
40, // row start
|
||||
270, // rotation
|
||||
16, // Color depth
|
||||
false, // Grayscale
|
||||
false, // Pixels in a byte share a row
|
||||
1, // bytes per cell
|
||||
false, // reverse_pixels_in_byte
|
||||
true, // reverse_pixels_in_word
|
||||
MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command
|
||||
MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command
|
||||
MIPI_COMMAND_WRITE_MEMORY_START, // write memory command
|
||||
display_init_sequence,
|
||||
sizeof(display_init_sequence),
|
||||
&pin_GPIO25, // backlight pin
|
||||
NO_BRIGHTNESS_COMMAND,
|
||||
1.0f, // brightness
|
||||
false, // single_byte_bounds
|
||||
false, // data_as_commands
|
||||
true, // auto_refresh
|
||||
60, // native_frames_per_second
|
||||
true, // backlight_on_high
|
||||
false, // SH1107_addressing
|
||||
1000 // backlight pwm frequency
|
||||
);
|
||||
}
|
||||
|
||||
void board_init(void) {
|
||||
display_init();
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 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.
|
||||
*/
|
||||
|
||||
// Micropython setup
|
||||
#define MICROPY_HW_BOARD_NAME "Waveshare RP2040-GEEK"
|
||||
#define MICROPY_HW_MCU_NAME "rp2040"
|
||||
|
||||
#define CIRCUITPY_BOARD_I2C (1)
|
||||
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO29, .sda = &pin_GPIO28}}
|
||||
|
||||
#define CIRCUITPY_BOARD_SPI (2)
|
||||
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO10, .mosi = &pin_GPIO11}, \
|
||||
{.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO20}}
|
||||
|
||||
#define CIRCUITPY_BOARD_UART (1)
|
||||
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO4, .rx = &pin_GPIO5}}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
USB_VID = 0x2E8A
|
||||
USB_PID = 0x1056
|
||||
USB_PRODUCT = "RP2040-GEEK"
|
||||
USB_MANUFACTURER = "Waveshare Electronics"
|
||||
|
||||
CHIP_VARIANT = RP2040
|
||||
CHIP_FAMILY = rp2
|
||||
|
||||
EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ"
|
||||
|
||||
CIRCUITPY__EVE = 1
|
||||
|
|
@ -0,0 +1 @@
|
|||
// Put board-specific pico-sdk definitions here. This file must exist.
|
||||
72
ports/raspberrypi/boards/waveshare_rp2040_geek/pins.c
Normal file
72
ports/raspberrypi/boards/waveshare_rp2040_geek/pins.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#include "shared-bindings/board/__init__.h"
|
||||
#include "shared-module/displayio/__init__.h"
|
||||
|
||||
CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1)
|
||||
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
|
||||
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
|
||||
|
||||
// 2-3 DEBUG
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) },
|
||||
// 4-5 UART
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) },
|
||||
// 8-12 LCD
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
|
||||
// 16-17 I2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) },
|
||||
// 18-23 SD Card
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) },
|
||||
// 25 LCD Backlight
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) },
|
||||
// 28-29 I2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO28), MP_ROM_PTR(&pin_GPIO28) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IO29), MP_ROM_PTR(&pin_GPIO29) },
|
||||
|
||||
// UART
|
||||
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO4) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO5) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
|
||||
|
||||
// I2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO29) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO28) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
|
||||
|
||||
// SPI SD Card
|
||||
{ MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO19)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO20)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO23)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) },
|
||||
|
||||
// SDIO SD Card
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO18)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_GPIO19)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_GPIO20)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_GPIO21)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_GPIO22)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_GPIO23)},
|
||||
|
||||
// LCD
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO8) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO11) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO12) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(&pin_GPIO25) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },
|
||||
|
||||
};
|
||||
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
|
||||
|
|
@ -54,7 +54,11 @@ static const external_flash_device *flash_device = NULL;
|
|||
// cache.
|
||||
static uint32_t dirty_mask;
|
||||
|
||||
// Table of pointers to each cached block
|
||||
// Table of pointers to each cached block. Should be zero'd after allocation.
|
||||
#define BLOCKS_PER_SECTOR (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE)
|
||||
#define PAGES_PER_BLOCK (FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE)
|
||||
#define FLASH_CACHE_TABLE_NUM_ENTRIES (BLOCKS_PER_SECTOR * PAGES_PER_BLOCK)
|
||||
#define FLASH_CACHE_TABLE_SIZE (FLASH_CACHE_TABLE_NUM_ENTRIES * sizeof (uint8_t *))
|
||||
static uint8_t **flash_cache_table = NULL;
|
||||
|
||||
// Wait until both the write enable and write in progress bits have cleared.
|
||||
|
|
@ -207,7 +211,7 @@ void supervisor_flash_init(void) {
|
|||
// Delay to give the SPI Flash time to get going.
|
||||
// TODO(tannewt): Only do this when we know power was applied vs a reset.
|
||||
uint16_t max_start_up_delay_us = 0;
|
||||
for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||
for (size_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||
if (possible_devices[i].start_up_time_us > max_start_up_delay_us) {
|
||||
max_start_up_delay_us = possible_devices[i].start_up_time_us;
|
||||
}
|
||||
|
|
@ -219,7 +223,7 @@ void supervisor_flash_init(void) {
|
|||
#ifdef EXTERNAL_FLASH_NO_JEDEC
|
||||
// For NVM that don't have JEDEC response
|
||||
spi_flash_command(CMD_WAKE);
|
||||
for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||
for (size_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||
const external_flash_device *possible_device = &possible_devices[i];
|
||||
flash_device = possible_device;
|
||||
break;
|
||||
|
|
@ -234,7 +238,7 @@ void supervisor_flash_init(void) {
|
|||
while ((count-- > 0) && (jedec_id_response[0] == 0xff || jedec_id_response[2] == 0x00)) {
|
||||
spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3);
|
||||
}
|
||||
for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||
for (size_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||
const external_flash_device *possible_device = &possible_devices[i];
|
||||
if (jedec_id_response[0] == possible_device->manufacturer_id &&
|
||||
jedec_id_response[1] == possible_device->memory_type &&
|
||||
|
|
@ -323,7 +327,7 @@ static bool flush_scratch_flash(void) {
|
|||
// cached.
|
||||
bool copy_to_scratch_ok = true;
|
||||
uint32_t scratch_sector = flash_device->total_size - SPI_FLASH_ERASE_SIZE;
|
||||
for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) {
|
||||
for (size_t i = 0; i < BLOCKS_PER_SECTOR; i++) {
|
||||
if ((dirty_mask & (1 << i)) == 0) {
|
||||
copy_to_scratch_ok = copy_to_scratch_ok &&
|
||||
copy_block(current_sector + i * FILESYSTEM_BLOCK_SIZE,
|
||||
|
|
@ -338,72 +342,70 @@ 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 < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) {
|
||||
for (size_t i = 0; i < BLOCKS_PER_SECTOR; i++) {
|
||||
copy_block(scratch_sector + i * FILESYSTEM_BLOCK_SIZE,
|
||||
current_sector + i * FILESYSTEM_BLOCK_SIZE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Attempts to allocate a new set of page buffers for caching a full sector in
|
||||
// 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 = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE;
|
||||
uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE;
|
||||
|
||||
uint32_t table_size = blocks_per_sector * pages_per_block * sizeof(size_t);
|
||||
// Attempt to allocate outside the heap first.
|
||||
flash_cache_table = port_malloc(table_size, false);
|
||||
|
||||
// Declare i and j outside the loops in case we fail to allocate everything
|
||||
// we need. In that case we'll give it back.
|
||||
uint8_t i = 0;
|
||||
uint8_t j = 0;
|
||||
bool success = flash_cache_table != NULL;
|
||||
for (i = 0; i < blocks_per_sector && success; i++) {
|
||||
for (j = 0; j < pages_per_block && success; j++) {
|
||||
uint8_t *page_cache = port_malloc(SPI_FLASH_PAGE_SIZE, false);
|
||||
if (page_cache == NULL) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
flash_cache_table[i * pages_per_block + j] = page_cache;
|
||||
}
|
||||
}
|
||||
// We couldn't allocate enough so give back what we got.
|
||||
if (!success) {
|
||||
// We add 1 so that we delete 0 when i is 1. Going to zero (i >= 0)
|
||||
// would never stop because i is unsigned.
|
||||
i++;
|
||||
for (; i > 0; i--) {
|
||||
for (; j > 0; j--) {
|
||||
port_free(flash_cache_table[(i - 1) * pages_per_block + (j - 1)]);
|
||||
}
|
||||
j = pages_per_block;
|
||||
}
|
||||
port_free(flash_cache_table);
|
||||
flash_cache_table = NULL;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// Free all entries in the partially or completely filled flash_cache_table, and then free the table itself.
|
||||
static void release_ram_cache(void) {
|
||||
uint8_t blocks_per_sector = SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE;
|
||||
uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE;
|
||||
for (uint8_t i = 0; i < blocks_per_sector; i++) {
|
||||
for (uint8_t j = 0; j < pages_per_block; j++) {
|
||||
uint32_t offset = i * pages_per_block + j;
|
||||
port_free(flash_cache_table[offset]);
|
||||
if (flash_cache_table == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < FLASH_CACHE_TABLE_NUM_ENTRIES; i++) {
|
||||
// Table may not be completely full. Stop at first NULL entry.
|
||||
if (flash_cache_table[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
port_free(flash_cache_table[i]);
|
||||
}
|
||||
port_free(flash_cache_table);
|
||||
flash_cache_table = NULL;
|
||||
}
|
||||
|
||||
// Attempts to allocate a new set of page buffers for caching a full sector in
|
||||
// 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) {
|
||||
flash_cache_table = port_malloc(FLASH_CACHE_TABLE_SIZE, false);
|
||||
if (flash_cache_table == NULL) {
|
||||
// Not enough space even for the cache table.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear all the entries so it's easy to find the last entry.
|
||||
memset(flash_cache_table, 0, FLASH_CACHE_TABLE_SIZE);
|
||||
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < BLOCKS_PER_SECTOR && success; i++) {
|
||||
for (size_t j = 0; j < PAGES_PER_BLOCK && success; j++) {
|
||||
uint8_t *page_cache = port_malloc(SPI_FLASH_PAGE_SIZE, false);
|
||||
if (page_cache == NULL) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
flash_cache_table[i * PAGES_PER_BLOCK + j] = page_cache;
|
||||
}
|
||||
}
|
||||
|
||||
// We couldn't allocate enough so give back what we got.
|
||||
if (!success) {
|
||||
release_ram_cache();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
// Flush the cached sector from ram onto the flash. We'll free the cache unless
|
||||
// keep_cache is true.
|
||||
static bool flush_ram_cache(bool keep_cache) {
|
||||
if (flash_cache_table == NULL) {
|
||||
// Nothing to flush because there is no cache.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (current_sector == NO_SECTOR_LOADED) {
|
||||
if (!keep_cache) {
|
||||
release_ram_cache();
|
||||
|
|
@ -414,13 +416,12 @@ 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 = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE;
|
||||
for (uint8_t i = 0; i < SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE; i++) {
|
||||
for (size_t i = 0; i < BLOCKS_PER_SECTOR; i++) {
|
||||
if ((dirty_mask & (1 << i)) == 0) {
|
||||
for (uint8_t j = 0; j < pages_per_block; j++) {
|
||||
for (size_t j = 0; j < PAGES_PER_BLOCK; j++) {
|
||||
copy_to_ram_ok = read_flash(
|
||||
current_sector + (i * pages_per_block + j) * SPI_FLASH_PAGE_SIZE,
|
||||
flash_cache_table[i * pages_per_block + j],
|
||||
current_sector + (i * PAGES_PER_BLOCK + j) * SPI_FLASH_PAGE_SIZE,
|
||||
flash_cache_table[i * PAGES_PER_BLOCK + j],
|
||||
SPI_FLASH_PAGE_SIZE);
|
||||
if (!copy_to_ram_ok) {
|
||||
break;
|
||||
|
|
@ -438,10 +439,10 @@ 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 < 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) * SPI_FLASH_PAGE_SIZE,
|
||||
flash_cache_table[i * pages_per_block + j],
|
||||
for (size_t i = 0; i < BLOCKS_PER_SECTOR; i++) {
|
||||
for (size_t j = 0; j < PAGES_PER_BLOCK; j++) {
|
||||
write_flash(current_sector + (i * PAGES_PER_BLOCK + j) * SPI_FLASH_PAGE_SIZE,
|
||||
flash_cache_table[i * PAGES_PER_BLOCK + j],
|
||||
SPI_FLASH_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
|
@ -496,15 +497,14 @@ static bool external_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 & (~(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);
|
||||
size_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % BLOCKS_PER_SECTOR;
|
||||
uint32_t mask = 1 << (block_index);
|
||||
// We're reading from the currently cached sector.
|
||||
if (current_sector == this_sector && (mask & dirty_mask) > 0) {
|
||||
if (flash_cache_table != NULL) {
|
||||
uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE;
|
||||
for (int i = 0; i < pages_per_block; i++) {
|
||||
for (int i = 0; i < PAGES_PER_BLOCK; i++) {
|
||||
memcpy(dest + i * SPI_FLASH_PAGE_SIZE,
|
||||
flash_cache_table[block_index * pages_per_block + i],
|
||||
flash_cache_table[block_index * PAGES_PER_BLOCK + i],
|
||||
SPI_FLASH_PAGE_SIZE);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -527,8 +527,8 @@ static bool external_flash_write_block(const uint8_t *data, uint32_t block) {
|
|||
wait_for_flash_ready();
|
||||
// Mask out the lower bits that designate the address within the sector.
|
||||
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);
|
||||
size_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % BLOCKS_PER_SECTOR;
|
||||
uint32_t mask = 1 << (block_index);
|
||||
// Flush the cache if we're moving onto a sector or we're writing the
|
||||
// same block again.
|
||||
if (current_sector != this_sector || (mask & dirty_mask) > 0) {
|
||||
|
|
@ -550,9 +550,8 @@ static bool external_flash_write_block(const uint8_t *data, uint32_t block) {
|
|||
dirty_mask |= mask;
|
||||
// Copy the block to the appropriate cache.
|
||||
if (flash_cache_table != NULL) {
|
||||
uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE;
|
||||
for (int i = 0; i < pages_per_block; i++) {
|
||||
memcpy(flash_cache_table[block_index * pages_per_block + i],
|
||||
for (int i = 0; i < PAGES_PER_BLOCK; i++) {
|
||||
memcpy(flash_cache_table[block_index * PAGES_PER_BLOCK + i],
|
||||
data + i * SPI_FLASH_PAGE_SIZE,
|
||||
SPI_FLASH_PAGE_SIZE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ python3 -m venv test-stubs
|
|||
pip install mypy isort black adafruit-circuitpython-typing wheel build
|
||||
rm -rf circuitpython-stubs .mypy_cache
|
||||
make stubs
|
||||
pip install --force-reinstall circuitpython-stubs/dist/circuitpython-stubs-*.tar.gz
|
||||
# Allow either dash or underscore as separator. setuptools v69.3.0 changed from "-" to "_".
|
||||
pip install --force-reinstall circuitpython-stubs/dist/circuitpython[-_]stubs-*.tar.gz
|
||||
export MYPYPATH=circuitpython-stubs/
|
||||
echo "The following test should pass:"
|
||||
mypy -c 'import busio; b: busio.I2C; b.writeto(0x30, b"")'
|
||||
|
|
|
|||
Loading…
Reference in a new issue