Skip to content

Commit

Permalink
Merge pull request #49 from oyama/fix/multicore-safe-execute
Browse files Browse the repository at this point in the history
Flash exclusive control changed to pico_flash
  • Loading branch information
oyama authored Jun 18, 2024
2 parents 4c475c2 + 4b48311 commit 0208bf3
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 270 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ target_sources(blockdevice_flash INTERFACE
target_compile_options(blockdevice_flash INTERFACE -Werror -Wall -Wextra -Wnull-dereference)
target_link_libraries(blockdevice_flash INTERFACE
blockdevice
hardware_exception
hardware_flash
hardware_sync
pico_sync
pico_flash
)

# Heap memory blockdevice library
Expand Down
4 changes: 2 additions & 2 deletions examples/benchmark/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static uint32_t xor_rand_32bit(uint32_t *seed) {

static void benchmark_write(void) {
const char *label = "Write";
uint64_t start_at = get_absolute_time();
absolute_time_t start_at = get_absolute_time();

int fd = open("/benchmark", O_WRONLY|O_CREAT);
if (fd == -1) {
Expand Down Expand Up @@ -116,7 +116,7 @@ static void benchmark_write(void) {

static void benchmark_read(void) {
const char *label = "Read";
uint64_t start_at = get_absolute_time();
absolute_time_t start_at = get_absolute_time();

int fd = open("/benchmark", O_RDONLY);
if (fd == -1) {
Expand Down
71 changes: 53 additions & 18 deletions src/blockdevice/flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,48 @@
#include <hardware/flash.h>
#include <hardware/regs/addressmap.h>
#include <hardware/sync.h>
#include <pico/flash.h>
#include <pico/mutex.h>
#include <stdio.h>
#include <string.h>
#include "blockdevice/flash.h"

#define FLASH_SAFE_EXECUTE_TIMEOUT 10 * 1000

#define FLASH_BLOCK_DEVICE_ERROR_TIMEOUT -4001 /*!< operation timeout */
#define FLASH_BLOCK_DEVICE_ERROR_NOT_PERMITTED -4002 /*!< safe execution is not possible */
#define FLASH_BLOCK_DEVICE_ERROR_INSUFFICIENT_RESOURCES -4003 /*!< method fails due to dynamic resource exhaustion */

typedef struct {
uint32_t start;
size_t length;
mutex_t _mutex;
} blockdevice_flash_config_t;

typedef struct {
bool is_erase;
size_t addr;
size_t size;
void *buffer;
} _safe_flash_update_param_t;

static const char DEVICE_NAME[] = "flash";

static int _error_remap(int err) {
switch (err) {
case PICO_OK:
return BD_ERROR_OK;
case PICO_ERROR_TIMEOUT:
return FLASH_BLOCK_DEVICE_ERROR_TIMEOUT;
case PICO_ERROR_NOT_PERMITTED:
return FLASH_BLOCK_DEVICE_ERROR_NOT_PERMITTED;
case PICO_ERROR_INSUFFICIENT_RESOURCES:
return FLASH_BLOCK_DEVICE_ERROR_INSUFFICIENT_RESOURCES;
default:
return err;
}
}

static size_t flash_target_offset(blockdevice_t *device) {
blockdevice_flash_config_t *config = device->config;
return config->start;
Expand Down Expand Up @@ -52,28 +81,34 @@ static int read(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_si
return BD_ERROR_OK;
}

static int erase(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
blockdevice_flash_config_t *config = device->config;

mutex_enter_blocking(&config->_mutex);
uint32_t ints = save_and_disable_interrupts();
flash_range_erase(flash_target_offset(device) + addr, (size_t)size);
restore_interrupts(ints);
mutex_exit(&config->_mutex);
static void _safe_flash_update(void *param) {
const _safe_flash_update_param_t *args = param;
if (args->is_erase) {
flash_range_erase(args->addr, args->size);
} else {
flash_range_program(args->addr, (const uint8_t *)args->buffer, args->size);
}
}

return BD_ERROR_OK;
static int erase(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
_safe_flash_update_param_t param = {
.is_erase = true,
.addr = flash_target_offset(device) + addr,
.size = (size_t)size,
};
int err = flash_safe_execute(_safe_flash_update, &param, FLASH_SAFE_EXECUTE_TIMEOUT);
return _error_remap(err);
}

static int program(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t size) {
blockdevice_flash_config_t *config = device->config;

mutex_enter_blocking(&config->_mutex);
uint32_t ints = save_and_disable_interrupts();
flash_range_program(flash_target_offset(device) + addr, buffer, (size_t)size);
restore_interrupts(ints);
mutex_exit(&config->_mutex);

return BD_ERROR_OK;
_safe_flash_update_param_t param = {
.is_erase = false,
.addr = flash_target_offset(device) + addr,
.buffer = (void *)buffer,
.size = (size_t)size,
};
int err = flash_safe_execute(_safe_flash_update, &param, FLASH_SAFE_EXECUTE_TIMEOUT);
return _error_remap(err);
}

static int trim(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
Expand Down
17 changes: 17 additions & 0 deletions src/filesystem/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,23 @@ char *fs_strerror(int errnum) {
break;
}
return (char *)str;
} else if (errnum > 4000) {
// On-board flash blockdevice error
const char *str = "";
switch (errnum) {
case 4001:
str = "operation timeout";
break;
case 4002:
str = "safe execution is not possible";
break;
case 4003:
str = "method fails due to dynamic resource exhaustion";
break;
default:
break;
}
return (char *)str;
} else {
return strerror(errnum);
}
Expand Down
9 changes: 6 additions & 3 deletions tests/multicore/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
add_executable(multicore main.c)
target_compile_options(multicore PRIVATE -Werror -Wall -Wextra -Wnull-dereference)
target_compile_options(multicore PRIVATE
-DPICO_FLASH_ASSUME_CORE1_SAFE=1
-Werror -Wall -Wextra -Wnull-dereference
)
target_link_libraries(multicore PRIVATE
pico_flash
pico_stdlib
pico_multicore
blockdevice_flash
Expand All @@ -12,11 +16,10 @@ target_link_libraries(multicore PRIVATE
)
target_link_options(multicore PRIVATE -Wl,--print-memory-usage)
pico_add_extra_outputs(multicore)
pico_enable_stdio_uart(multicore 1)
pico_enable_stdio_usb(multicore 0)
pico_enable_filesystem(multicore FS_INIT fs_init.c)
pico_set_binary_type(multicore copy_to_ram)


find_program(OPENOCD openocd)
if(OPENOCD)
add_custom_target(run_multicore
Expand Down
39 changes: 39 additions & 0 deletions tests/multicore/fs_init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <hardware/clocks.h>
#include <hardware/flash.h>
#include "blockdevice/flash.h"
#include "blockdevice/flash.h"
#include "blockdevice/sd.h"
#include "filesystem/fat.h"
#include "filesystem/littlefs.h"
#include "filesystem/vfs.h"

#define FLASH_LENGTH_ALL 0

bool fs_init(void) {
blockdevice_t *flash = blockdevice_flash_create(PICO_FLASH_SIZE_BYTES - PICO_FS_DEFAULT_SIZE,
FLASH_LENGTH_ALL);
blockdevice_t *sd = blockdevice_sd_create(spi0,
PICO_DEFAULT_SPI_TX_PIN,
PICO_DEFAULT_SPI_RX_PIN,
PICO_DEFAULT_SPI_SCK_PIN,
PICO_DEFAULT_SPI_CSN_PIN,
24 * MHZ,
true);
filesystem_t *fat = filesystem_fat_create();
filesystem_t *littlefs = filesystem_littlefs_create(500, 16);

int err = fs_format(littlefs, flash);
if (err == -1)
return false;
err = fs_mount("/flash", littlefs, flash);
if (err == -1)
return false;

fs_format(fat, sd);
if (err == -1)
return false;
err = fs_mount("/sd", fat, sd);
if (err == -1)
return false;
return true;
}
Loading

0 comments on commit 0208bf3

Please sign in to comment.