Merge remote-tracking branch 'adafruit/9.0.x' into 9.0.4-update

This commit is contained in:
Dan Halbert 2024-04-17 15:39:10 -04:00
commit c35ec758dd
9 changed files with 297 additions and 76 deletions

View file

@ -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

View file

@ -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;
}

View 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();
}

View file

@ -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}}

View file

@ -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

View file

@ -0,0 +1 @@
// Put board-specific pico-sdk definitions here. This file must exist.

View 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);

View file

@ -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);
}

View file

@ -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"")'