Add documentation

Flashcart specific
This commit is contained in:
Robin Jones 2025-02-22 01:08:59 +00:00
parent 2fe2a22eee
commit 7e3b802e09
5 changed files with 357 additions and 31 deletions

View File

@ -1,21 +1,24 @@
#include <stddef.h>
/**
* @file flashcart.c
* @brief Flashcart functions implementation
* @ingroup flashcart
*/
#include <stddef.h>
#include <libcart/cart.h>
#include <libdragon.h>
#include <usb.h>
#include "utils/fs.h"
#include "utils/utils.h"
#include "flashcart.h"
#include "flashcart_utils.h"
#include "ed64/ed64_vseries.h"
#include "ed64/ed64_xseries.h"
#include "64drive/64drive.h"
#include "sc64/sc64.h"
/** @brief Save sizes for different flashcart save types. */
static const size_t SAVE_SIZE[__FLASHCART_SAVE_TYPE_END] = {
0,
512,
@ -27,11 +30,21 @@ static const size_t SAVE_SIZE[__FLASHCART_SAVE_TYPE_END] = {
KiB(128),
};
/**
* @brief Dummy initialization function for flashcart.
*
* @return flashcart_err_t Error code.
*/
static flashcart_err_t dummy_init (void) {
return FLASHCART_OK;
}
/**
* @brief Dummy function to check if a feature is supported by the flashcart.
*
* @param feature The feature to check.
* @return true if the feature is supported, false otherwise.
*/
static bool dummy_has_feature (flashcart_features_t feature) {
switch (feature) {
default:
@ -39,22 +52,50 @@ static bool dummy_has_feature (flashcart_features_t feature) {
}
}
/**
* @brief Dummy function to load a ROM into the flashcart.
*
* @param rom_path Path to the ROM file.
* @param progress Progress callback function.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t dummy_load_rom (char *rom_path, flashcart_progress_callback_t *progress) {
return FLASHCART_OK;
}
/**
* @brief Dummy function to load a file into the flashcart.
*
* @param file_path Path to the file.
* @param rom_offset ROM offset.
* @param file_offset File offset.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t dummy_load_file (char *file_path, uint32_t rom_offset, uint32_t file_offset) {
return FLASHCART_OK;
}
/**
* @brief Dummy function to load a save file into the flashcart.
*
* @param save_path Path to the save file.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t dummy_load_save (char *save_path) {
return FLASHCART_OK;
}
/**
* @brief Dummy function to set the save type for the flashcart.
*
* @param save_type The save type.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t dummy_set_save_type (flashcart_save_type_t save_type) {
return FLASHCART_OK;
}
/** @brief Flashcart structure with dummy functions. */
static flashcart_t *flashcart = &((flashcart_t) {
.init = dummy_init,
.deinit = NULL,
@ -75,7 +116,12 @@ static flashcart_t *flashcart = &((flashcart_t) {
bool debug_init_sdfs (const char *prefix, int npart);
#endif
/**
* @brief Convert a flashcart error code to a human-readable message.
*
* @param err The flashcart error code.
* @return char* The error message.
*/
char *flashcart_convert_error_message (flashcart_err_t err) {
switch (err) {
case FLASHCART_OK: return "No error";
@ -90,6 +136,12 @@ char *flashcart_convert_error_message (flashcart_err_t err) {
}
}
/**
* @brief Initialize the flashcart.
*
* @param storage_prefix Pointer to the storage prefix.
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_init (const char **storage_prefix) {
flashcart_err_t err;
@ -144,6 +196,11 @@ flashcart_err_t flashcart_init (const char **storage_prefix) {
return FLASHCART_OK;
}
/**
* @brief Deinitialize the flashcart.
*
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_deinit (void) {
if (flashcart->deinit) {
return flashcart->deinit();
@ -152,14 +209,33 @@ flashcart_err_t flashcart_deinit (void) {
return FLASHCART_OK;
}
/**
* @brief Check if the flashcart has a specific feature.
*
* @param feature The feature to check.
* @return true if the feature is supported, false otherwise.
*/
bool flashcart_has_feature (flashcart_features_t feature) {
return flashcart->has_feature(feature);
}
/**
* @brief Get the firmware version of the flashcart.
*
* @return flashcart_firmware_version_t The firmware version.
*/
flashcart_firmware_version_t flashcart_get_firmware_version (void) {
return flashcart->get_firmware_version();
}
/**
* @brief Load a ROM into the flashcart.
*
* @param rom_path Path to the ROM file.
* @param byte_swap Flag indicating whether to byte swap the ROM.
* @param progress Progress callback function.
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_load_rom (char *rom_path, bool byte_swap, flashcart_progress_callback_t *progress) {
flashcart_err_t err;
@ -174,6 +250,14 @@ flashcart_err_t flashcart_load_rom (char *rom_path, bool byte_swap, flashcart_pr
return err;
}
/**
* @brief Load a file into the flashcart.
*
* @param file_path Path to the file.
* @param rom_offset ROM offset.
* @param file_offset File offset.
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_load_file (char *file_path, uint32_t rom_offset, uint32_t file_offset) {
if ((file_path == NULL) || ((file_offset % FS_SECTOR_SIZE) != 0)) {
return FLASHCART_ERR_ARGS;
@ -182,6 +266,13 @@ flashcart_err_t flashcart_load_file (char *file_path, uint32_t rom_offset, uint3
return flashcart->load_file(file_path, rom_offset, file_offset);
}
/**
* @brief Load a save file into the flashcart.
*
* @param save_path Path to the save file.
* @param save_type The save type.
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_load_save (char *save_path, flashcart_save_type_t save_type) {
flashcart_err_t err;
@ -221,6 +312,13 @@ flashcart_err_t flashcart_load_save (char *save_path, flashcart_save_type_t save
return flashcart->set_save_writeback(save_path);
}
/**
* @brief Load the 64DD IPL into the flashcart.
*
* @param ipl_path Path to the IPL file.
* @param progress Progress callback function.
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_load_64dd_ipl (char *ipl_path, flashcart_progress_callback_t *progress) {
if (!flashcart->load_64dd_ipl) {
return FLASHCART_ERR_FUNCTION_NOT_SUPPORTED;
@ -233,6 +331,13 @@ flashcart_err_t flashcart_load_64dd_ipl (char *ipl_path, flashcart_progress_call
return flashcart->load_64dd_ipl(ipl_path, progress);
}
/**
* @brief Load a 64DD disk into the flashcart.
*
* @param disk_path Path to the disk file.
* @param disk_parameters Pointer to the disk parameters.
* @return flashcart_err_t Error code.
*/
flashcart_err_t flashcart_load_64dd_disk (char *disk_path, flashcart_disk_parameters_t *disk_parameters) {
if (!flashcart->load_64dd_disk) {
return FLASHCART_ERR_FUNCTION_NOT_SUPPORTED;

View File

@ -1,16 +1,35 @@
/**
* @file flashcart_utils.c
* @brief Flashcart utility functions implementation
* @ingroup flashcart
*/
#include <libdragon.h>
#include "flashcart_utils.h"
#include "utils/fs.h"
#include "utils/utils.h"
/**
* @brief Perform a DMA read operation from the PI (Peripheral Interface).
*
* @param src Source address.
* @param dst Destination address.
* @param length Length of data to read.
*/
void pi_dma_read_data (void *src, void *dst, size_t length) {
data_cache_hit_writeback_invalidate(dst, length);
dma_read_async(dst, (uint32_t) (src), length);
dma_wait();
}
/**
* @brief Perform a DMA write operation to the PI (Peripheral Interface).
*
* @param src Source address.
* @param dst Destination address.
* @param length Length of data to write.
*/
void pi_dma_write_data (void *src, void *dst, size_t length) {
assert((((uint32_t) (src)) & 0x07) == 0);
assert((((uint32_t) (dst)) & 0x01) == 0);
@ -21,6 +40,11 @@ void pi_dma_write_data (void *src, void *dst, size_t length) {
dma_wait();
}
/**
* @brief Align the file size to the SD sector size to prevent partial sector load.
*
* @param fil Pointer to the file object.
*/
void fatfs_fix_file_size (FIL *fil) {
// HACK: Align file size to the SD sector size to prevent FatFs from doing partial sector load.
// We are relying on direct transfer from SD to SDRAM without CPU intervention.
@ -28,6 +52,15 @@ void fatfs_fix_file_size (FIL *fil) {
fil->obj.objsize = ALIGN(f_size(fil), FS_SECTOR_SIZE);
}
/**
* @brief Get the file sectors in the FAT filesystem.
*
* @param path Path to the file.
* @param address Pointer to store the address of the file sectors.
* @param type The type of address (memory or PI).
* @param max_sectors Maximum number of sectors.
* @return true if an error occurred, false otherwise.
*/
bool fatfs_get_file_sectors (char *path, uint32_t *address, address_type_t type, uint32_t max_sectors) {
FATFS *fs;
FIL fil;

View File

@ -7,27 +7,56 @@
#ifndef FLASHCART_UTILS_H__
#define FLASHCART_UTILS_H__
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <fatfs/ff.h>
#define SAVE_WRITEBACK_MAX_SECTORS (256)
/**
* @brief Address types for DMA operations.
*/
typedef enum {
ADDRESS_TYPE_MEM,
ADDRESS_TYPE_PI,
ADDRESS_TYPE_MEM, /**< Memory address type. */
ADDRESS_TYPE_PI, /**< Peripheral Interface address type. */
} address_type_t;
/**
* @brief Perform a DMA read operation from the PI (Peripheral Interface).
*
* @param src Source address.
* @param dst Destination address.
* @param length Length of data to read.
*/
void pi_dma_read_data (void *src, void *dst, size_t length);
/**
* @brief Perform a DMA write operation to the PI (Peripheral Interface).
*
* @param src Source address.
* @param dst Destination address.
* @param length Length of data to write.
*/
void pi_dma_write_data (void *src, void *dst, size_t length);
/**
* @brief Fix the file size in the FAT filesystem.
*
* @param fil Pointer to the file object.
*/
void fatfs_fix_file_size (FIL *fil);
/**
* @brief Get the file sectors in the FAT filesystem.
*
* @param path Path to the file.
* @param address Pointer to store the address of the file sectors.
* @param address_type The type of address (memory or PI).
* @param max_sectors Maximum number of sectors.
* @return true if successful, false otherwise.
*/
bool fatfs_get_file_sectors (char *path, uint32_t *address, address_type_t address_type, uint32_t max_sectors);
#endif
#endif /* FLASHCART_UTILS_H__ */

View File

@ -1,3 +1,9 @@
/**
* @file sc64.c
* @brief SummerCart64 functions implementation
* @ingroup flashcart
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -12,7 +18,6 @@
#include "sc64_ll.h"
#include "sc64.h"
#define SRAM_FLASHRAM_ADDRESS (0x08000000)
#define ROM_ADDRESS (0x10000000)
#define IPL_ADDRESS (0x13BC0000)
@ -39,7 +44,6 @@
#define THB_UNMAPPED (0xFFFFFFFF)
#define THB_WRITABLE_FLAG (1 << 31)
static const struct {
uint8_t head;
uint8_t sector_length;
@ -63,6 +67,7 @@ static const struct {
{ 1, 128, 149, 912 },
{ 1, 112, 114, 1061 },
};
static const uint8_t vzone_to_pzone[DISK_TYPES][DISK_ZONES] = {
{0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10},
{0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11},
@ -72,9 +77,19 @@ static const uint8_t vzone_to_pzone[DISK_TYPES][DISK_ZONES] = {
{0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15},
{0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8},
};
static const uint8_t rom_zones[DISK_TYPES] = { 5, 7, 9, 11, 13, 15, 16 };
/**
* @brief Load data to flash memory.
*
* @param fil Pointer to the file object.
* @param address Address to load data to.
* @param size Size of the data to load.
* @param br Pointer to store the number of bytes read.
* @param progress Progress callback function.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t load_to_flash (FIL *fil, void *address, size_t size, UINT *br, flashcart_progress_callback_t *progress) {
size_t erase_block_size;
UINT bp;
@ -107,7 +122,14 @@ static flashcart_err_t load_to_flash (FIL *fil, void *address, size_t size, UINT
return FLASHCART_OK;
}
/**
* @brief Check if a disk zone track is bad.
*
* @param zone Zone number.
* @param track Track number.
* @param disk_parameters Pointer to the disk parameters.
* @return true if the track is bad, false otherwise.
*/
static bool disk_zone_track_is_bad (uint8_t zone, uint8_t track, flashcart_disk_parameters_t *disk_parameters) {
for (int i = 0; i < DISK_BAD_TRACKS_PER_ZONE; i++) {
if (disk_parameters->defect_tracks[zone][i] == track) {
@ -118,6 +140,13 @@ static bool disk_zone_track_is_bad (uint8_t zone, uint8_t track, flashcart_disk_
return false;
}
/**
* @brief Check if a system LBA is bad.
*
* @param lba Logical block address.
* @param disk_parameters Pointer to the disk parameters.
* @return true if the LBA is bad, false otherwise.
*/
static bool disk_system_lba_is_bad (uint16_t lba, flashcart_disk_parameters_t *disk_parameters) {
if (lba < DISK_SYSTEM_LBA_COUNT) {
return disk_parameters->bad_system_area_lbas[lba];
@ -126,6 +155,17 @@ static bool disk_system_lba_is_bad (uint16_t lba, flashcart_disk_parameters_t *d
return false;
}
/**
* @brief Set the THB mapping for a disk.
*
* @param offset Offset for the THB mapping.
* @param track Track number.
* @param head Head number.
* @param block Block number.
* @param valid Valid flag.
* @param writable Writable flag.
* @param file_offset File offset.
*/
static void disk_set_thb_mapping (uint32_t offset, uint16_t track, uint8_t head, uint8_t block, bool valid, bool writable, int file_offset) {
uint32_t index = (track << 2) | (head << 1) | (block);
uint32_t mapping = valid ? ((writable ? THB_WRITABLE_FLAG : 0) | (file_offset & ~(THB_WRITABLE_FLAG))) : THB_UNMAPPED;
@ -133,6 +173,13 @@ static void disk_set_thb_mapping (uint32_t offset, uint16_t track, uint8_t head,
io_write(ROM_ADDRESS + offset + (index * sizeof(uint32_t)), mapping);
}
/**
* @brief Load the THB table for a disk.
*
* @param disk_parameters Pointer to the disk parameters.
* @param thb_table_offset Pointer to store the THB table offset.
* @param current_offset Pointer to the current offset.
*/
static void disk_load_thb_table (flashcart_disk_parameters_t *disk_parameters, uint32_t *thb_table_offset, uint32_t *current_offset) {
int file_offset = 0;
@ -176,6 +223,14 @@ static void disk_load_thb_table (flashcart_disk_parameters_t *disk_parameters, u
*current_offset += (DISK_TRACKS * DISK_HEADS * DISK_BLOCKS * sizeof(uint32_t));
}
/**
* @brief Load the sector table for a disk.
*
* @param path Path to the disk file.
* @param sector_table_offset Pointer to store the sector table offset.
* @param current_offset Pointer to the current offset.
* @return true if an error occurred, false otherwise.
*/
static bool disk_load_sector_table (char *path, uint32_t *sector_table_offset, uint32_t *current_offset) {
if (fatfs_get_file_sectors(path, (uint32_t *) (ROM_ADDRESS + *current_offset), ADDRESS_TYPE_PI, DISK_MAX_SECTORS)) {
return true;
@ -187,6 +242,11 @@ static bool disk_load_sector_table (char *path, uint32_t *sector_table_offset, u
return false;
}
/**
* @brief Get the firmware version of the SummerCart64.
*
* @return flashcart_firmware_version_t The firmware version.
*/
static flashcart_firmware_version_t sc64_get_firmware_version (void) {
flashcart_firmware_version_t version_info;
@ -195,7 +255,11 @@ static flashcart_firmware_version_t sc64_get_firmware_version (void) {
return version_info;
}
/**
* @brief Initialize the SummerCart64.
*
* @return flashcart_err_t Error code.
*/
static flashcart_err_t sc64_init (void) {
uint16_t major;
uint16_t minor;
@ -249,6 +313,11 @@ static flashcart_err_t sc64_init (void) {
return FLASHCART_OK;
}
/**
* @brief Deinitialize the SummerCart64.
*
* @return flashcart_err_t Error code.
*/
static flashcart_err_t sc64_deinit (void) {
sc64_ll_set_config(CFG_ID_ROM_WRITE_ENABLE, false);
@ -257,6 +326,12 @@ static flashcart_err_t sc64_deinit (void) {
return FLASHCART_OK;
}
/**
* @brief Check if the SummerCart64 has a specific feature.
*
* @param feature The feature to check.
* @return true if the feature is supported, false otherwise.
*/
static bool sc64_has_feature (flashcart_features_t feature) {
switch (feature) {
case FLASHCART_FEATURE_64DD: return true;
@ -271,6 +346,13 @@ static bool sc64_has_feature (flashcart_features_t feature) {
}
}
/**
* @brief Load a ROM into the SummerCart64.
*
* @param rom_path Path to the ROM file.
* @param progress Progress callback function.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t sc64_load_rom (char *rom_path, flashcart_progress_callback_t *progress) {
FIL fil;
UINT br;
@ -352,6 +434,14 @@ static flashcart_err_t sc64_load_rom (char *rom_path, flashcart_progress_callbac
return FLASHCART_OK;
}
/**
* @brief Load a file into the SummerCart64.
*
* @param file_path Path to the file.
* @param rom_offset ROM offset.
* @param file_offset File offset.
* @return flashcart_err_t Error code.
*/
static flashcart_err_t sc64_load_file (char *file_path, uint32_t rom_offset, uint32_t file_offset) {
FIL fil;
UINT br;

View File

@ -1,15 +1,20 @@
/**
* @file sc64_ll.c
* @brief Low-level functions for SummerCart64
* @ingroup flashcart
*/
#include <libdragon.h>
#include "../flashcart_utils.h"
#include "sc64_ll.h"
/** @brief SummerCart64 Registers Structure. */
typedef struct {
uint32_t SR_CMD;
uint32_t DATA[2];
uint32_t IDENTIFIER;
uint32_t KEY;
uint32_t SR_CMD; /**< Command Status Register. */
uint32_t DATA[2]; /**< Data Registers. */
uint32_t IDENTIFIER; /**< Identifier Register. */
uint32_t KEY; /**< Key Register. */
} sc64_regs_t;
#define SC64_REGS_BASE (0x1FFF0000UL)
@ -20,7 +25,7 @@ typedef struct {
#define SC64_KEY_LOCK (0xFFFFFFFFUL)
/** @brief SummerCart64 Command IDs. */
typedef enum {
CMD_ID_VERSION_GET = 'V',
CMD_ID_CONFIG_GET = 'c',
@ -34,12 +39,17 @@ typedef enum {
/** @brief SummerCart64 Commands Structure. */
typedef struct {
sc64_cmd_id_t id;
uint32_t arg[2];
uint32_t rsp[2];
sc64_cmd_id_t id; /**< Command ID. */
uint32_t arg[2]; /**< Command arguments. */
uint32_t rsp[2]; /**< Command response. */
} sc64_cmd_t;
/**
* @brief Execute a command on the SummerCart64.
*
* @param cmd Pointer to the command structure.
* @return sc64_error_t Error code.
*/
static sc64_error_t sc64_ll_execute_cmd (sc64_cmd_t *cmd) {
io_write((uint32_t) (&SC64_REGS->DATA[0]), cmd->arg[0]);
io_write((uint32_t) (&SC64_REGS->DATA[1]), cmd->arg[1]);
@ -61,11 +71,21 @@ static sc64_error_t sc64_ll_execute_cmd (sc64_cmd_t *cmd) {
return SC64_OK;
}
/**
* @brief Lock the SummerCart64.
*/
void sc64_ll_lock (void) {
io_write((uint32_t) (&SC64_REGS->KEY), SC64_KEY_LOCK);
}
/**
* @brief Get the firmware version of the SummerCart64.
*
* @param major Pointer to store the major version.
* @param minor Pointer to store the minor version.
* @param revision Pointer to store the revision number.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_get_version (uint16_t *major, uint16_t *minor, uint32_t *revision) {
sc64_cmd_t cmd = {
.id = CMD_ID_VERSION_GET
@ -77,6 +97,13 @@ sc64_error_t sc64_ll_get_version (uint16_t *major, uint16_t *minor, uint32_t *re
return error;
}
/**
* @brief Get a configuration value from the SummerCart64.
*
* @param id Configuration ID.
* @param value Pointer to store the configuration value.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_get_config (sc64_cfg_id_t id, uint32_t *value) {
sc64_cmd_t cmd = {
.id = CMD_ID_CONFIG_GET,
@ -87,6 +114,13 @@ sc64_error_t sc64_ll_get_config (sc64_cfg_id_t id, uint32_t *value) {
return error;
}
/**
* @brief Set a configuration value on the SummerCart64.
*
* @param id Configuration ID.
* @param value Configuration value.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_set_config (sc64_cfg_id_t id, uint32_t value) {
sc64_cmd_t cmd = {
.id = CMD_ID_CONFIG_SET,
@ -95,6 +129,12 @@ sc64_error_t sc64_ll_set_config (sc64_cfg_id_t id, uint32_t value) {
return sc64_ll_execute_cmd(&cmd);
}
/**
* @brief Set the disk mapping on the SummerCart64.
*
* @param disk_mapping Pointer to the disk mapping structure.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_set_disk_mapping (sc64_disk_mapping_t *disk_mapping) {
int disk_count = disk_mapping->count;
@ -121,6 +161,12 @@ sc64_error_t sc64_ll_set_disk_mapping (sc64_disk_mapping_t *disk_mapping) {
return sc64_ll_execute_cmd(&cmd);
}
/**
* @brief Check if there are pending writebacks on the SummerCart64.
*
* @param pending Pointer to store the pending status.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_writeback_pending (bool *pending) {
sc64_cmd_t cmd = {
.id = CMD_ID_WRITEBACK_PENDING
@ -130,6 +176,12 @@ sc64_error_t sc64_ll_writeback_pending (bool *pending) {
return error;
}
/**
* @brief Enable writeback on the SummerCart64.
*
* @param address Address to enable writeback.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_writeback_enable (void *address) {
sc64_cmd_t cmd = {
.id = CMD_ID_WRITEBACK_SD_INFO,
@ -138,6 +190,11 @@ sc64_error_t sc64_ll_writeback_enable (void *address) {
return sc64_ll_execute_cmd(&cmd);
}
/**
* @brief Wait for the flash to become idle on the SummerCart64.
*
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_flash_wait_busy (void) {
sc64_cmd_t cmd = {
.id = CMD_ID_FLASH_WAIT_BUSY,
@ -146,6 +203,12 @@ sc64_error_t sc64_ll_flash_wait_busy (void) {
return sc64_ll_execute_cmd(&cmd);
}
/**
* @brief Get the flash erase block size on the SummerCart64.
*
* @param erase_block_size Pointer to store the erase block size.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_flash_get_erase_block_size (size_t *erase_block_size) {
sc64_cmd_t cmd = {
.id = CMD_ID_FLASH_WAIT_BUSY,
@ -156,6 +219,12 @@ sc64_error_t sc64_ll_flash_get_erase_block_size (size_t *erase_block_size) {
return error;
}
/**
* @brief Erase a flash block on the SummerCart64.
*
* @param address Address of the block to erase.
* @return sc64_error_t Error code.
*/
sc64_error_t sc64_ll_flash_erase_block (void *address) {
sc64_cmd_t cmd = {
.id = CMD_ID_FLASH_ERASE_BLOCK,