From 02b624f33eda92b8d044c6c25fb7d0581b761e3e Mon Sep 17 00:00:00 2001 From: etsells Date: Mon, 9 Mar 2026 20:14:01 -0700 Subject: [PATCH 1/8] checkpoint --- flash/MX25L51245GZ2I-08G.c | 131 +++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 flash/MX25L51245GZ2I-08G.c diff --git a/flash/MX25L51245GZ2I-08G.c b/flash/MX25L51245GZ2I-08G.c new file mode 100644 index 0000000..8af007b --- /dev/null +++ b/flash/MX25L51245GZ2I-08G.c @@ -0,0 +1,131 @@ +/** + ****************************************************************************** + * @file : MX25L51245GZ2I-08G.c + * @brief : Driver for the flash chip on FC rev 3. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 Sun Devil Rocketry. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is covered under the + * BSD-3-Clause. + * + * https://opensource.org/license/bsd-3-clause + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### Flash driver features ##### + ============================================================================== + [..] + (+) Implements the same APIs as the legacy driver + ****************************************************************************** + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "flash.h" + + +/* Global Variables ----------------------------------------------------------*/ + + + +/* Private function prototypes -----------------------------------------------*/ + + + +/* Procedures ----------------------------------------------------------------*/ + +/** + * @brief Initializes the flash driver + * + * @param pflash_handle Pointer to the flash handle for this device. + * @retval The status of the flash peripheral. + */ +FLASH_STATUS flash_init + ( + HFLASH_BUFFER* pflash_handle + ) +{ +/*------------------------------------------------------------------------------ + Local variables +------------------------------------------------------------------------------*/ +FLASH_STATUS flash_status; /* Flash API function return codes */ +uint8_t status_register; /* Desired status register contents */ + + +/*------------------------------------------------------------------------------ + Initializations +------------------------------------------------------------------------------*/ +flash_status = FLASH_OK; +status_register = FLASH_REG_RESET_VAL; + + +/*------------------------------------------------------------------------------ + Pre-processing +------------------------------------------------------------------------------*/ + +/* Check for invalid BPL setting */ +if ( pflash_handle -> bpl_bits > FLASH_BPL_ALL ) + { + return FLASH_INVALID_INPUT; + } + +/* Determine the desired status register contents */ +status_register &= pflash_handle -> bpl_bits; +status_register |= pflash_handle -> bpl_write_protect; + + +/*------------------------------------------------------------------------------ + API Function Implementation +------------------------------------------------------------------------------*/ + +/* Configure write protection */ +if ( pflash_handle -> write_protected ) + { + flash_write_disable(); + return FLASH_OK; + } +else + { + flash_write_enable(); + } + +/* Check the flash chip status register to confirm chip can be reached */ +flash_status = flash_get_status( pflash_handle ); +if ( flash_status != FLASH_OK ) + { + return flash_status; + } +else if ( pflash_handle -> status_register == 0xFF ) + { + return FLASH_INIT_FAIL; + } + +/* Disable writing to the chip in case of prior interrupted write operation */ +if ( write_disable() != FLASH_OK ) + { + return FLASH_CANNOT_WRITE_DISABLE; + } + +/* Set the bpl bits in the flash chip */ +flash_status = flash_set_status( status_register ); + +/* Confirm Status register contents */ +while( flash_is_flash_busy() == FLASH_BUSY ){} +flash_status = flash_get_status( pflash_handle ); +if ( pflash_handle -> status_register != status_register ) + { + return FLASH_INIT_FAIL; + } +else + { + return flash_status; + } + +} /* flash_init */ From cbdb79baa1a8d323c513c5fa95531ea32146fac5 Mon Sep 17 00:00:00 2001 From: ETSsound <147210601+ETSsound@users.noreply.github.com> Date: Thu, 12 Mar 2026 18:06:54 -0700 Subject: [PATCH 2/8] Start of a flash driver --- flash/MX25L51245GZ2I-08G.c | 143 +++++++++++++++++++++------------- flash/flash.h | 154 +++++++++++++++++++++---------------- 2 files changed, 179 insertions(+), 118 deletions(-) diff --git a/flash/MX25L51245GZ2I-08G.c b/flash/MX25L51245GZ2I-08G.c index 8af007b..00855cc 100644 --- a/flash/MX25L51245GZ2I-08G.c +++ b/flash/MX25L51245GZ2I-08G.c @@ -18,7 +18,7 @@ ****************************************************************************** @verbatim ============================================================================== - ##### Flash driver features ##### + ##### Flash driver features ##### ============================================================================== [..] (+) Implements the same APIs as the legacy driver @@ -30,6 +30,8 @@ #include "main.h" #include "flash.h" +#include "stm32h7xx_hal.h" + /* Global Variables ----------------------------------------------------------*/ @@ -37,6 +39,10 @@ /* Private function prototypes -----------------------------------------------*/ +static FLASH_STATUS flash_qspi_enable + ( + void + ); /* Procedures ----------------------------------------------------------------*/ @@ -63,69 +69,102 @@ uint8_t status_register; /* Desired status register contents */ Initializations ------------------------------------------------------------------------------*/ flash_status = FLASH_OK; -status_register = FLASH_REG_RESET_VAL; +status_register = 0U; /*------------------------------------------------------------------------------ Pre-processing ------------------------------------------------------------------------------*/ -/* Check for invalid BPL setting */ -if ( pflash_handle -> bpl_bits > FLASH_BPL_ALL ) - { - return FLASH_INVALID_INPUT; - } +// /* Check for invalid BPL setting */ +// if ( pflash_handle -> bpl_bits > FLASH_BPL_ALL ) +// { +// return FLASH_INVALID_INPUT; +// } -/* Determine the desired status register contents */ -status_register &= pflash_handle -> bpl_bits; -status_register |= pflash_handle -> bpl_write_protect; +// /* Determine the desired status register contents */ +// status_register &= pflash_handle -> bpl_bits; +// status_register |= pflash_handle -> bpl_write_protect; /*------------------------------------------------------------------------------ API Function Implementation ------------------------------------------------------------------------------*/ -/* Configure write protection */ -if ( pflash_handle -> write_protected ) - { - flash_write_disable(); - return FLASH_OK; - } -else - { - flash_write_enable(); - } - -/* Check the flash chip status register to confirm chip can be reached */ -flash_status = flash_get_status( pflash_handle ); -if ( flash_status != FLASH_OK ) - { - return flash_status; - } -else if ( pflash_handle -> status_register == 0xFF ) - { - return FLASH_INIT_FAIL; - } - -/* Disable writing to the chip in case of prior interrupted write operation */ -if ( write_disable() != FLASH_OK ) - { - return FLASH_CANNOT_WRITE_DISABLE; - } - -/* Set the bpl bits in the flash chip */ -flash_status = flash_set_status( status_register ); - -/* Confirm Status register contents */ -while( flash_is_flash_busy() == FLASH_BUSY ){} -flash_status = flash_get_status( pflash_handle ); -if ( pflash_handle -> status_register != status_register ) - { - return FLASH_INIT_FAIL; - } -else - { - return flash_status; - } +/* Activate QSPI */ +if ( flash_qspi_enable() != FLASH_OK ) + { + return FLASH_INIT_FAIL; + } + +/* Write enable */ +// if ( pflash_handle -> write_protected ) +// { +// flash_write_disable(); +// return FLASH_OK; +// } +// else +// { +// flash_write_enable(); +// } + +// /* Check the flash chip status register to confirm chip can be reached */ +// flash_status = flash_get_status( pflash_handle ); +// if ( flash_status != FLASH_OK ) +// { +// return flash_status; +// } +// else if ( pflash_handle -> status_register == 0xFF ) +// { +// return FLASH_INIT_FAIL; +// } + +// /* Disable writing to the chip in case of prior interrupted write operation */ +// if ( write_disable() != FLASH_OK ) +// { +// return FLASH_CANNOT_WRITE_DISABLE; +// } + +// /* Set the bpl bits in the flash chip */ +// flash_status = flash_set_status( status_register ); + +// /* Confirm Status register contents */ +// while( flash_is_flash_busy() == FLASH_BUSY ){} +// flash_status = flash_get_status( pflash_handle ); +// if ( pflash_handle -> status_register != status_register ) +// { +// return FLASH_INIT_FAIL; +// } +// else +// { +// return flash_status; +// } + +return FLASH_OK; } /* flash_init */ + + +static FLASH_STATUS flash_qspi_enable + ( + void + ) +{ +/* Initializations */ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; + +/* Construct QSPI enable command (single SPI mode) */ +spi_command.Instruction = FLASH_ENABLE_QSPI_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; + +/* Transmit (blocking) */ +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); + +return ( hal_status == HAL_OK ); + +} /* flash_qspi_enable */ \ No newline at end of file diff --git a/flash/flash.h b/flash/flash.h index 5ab5877..cd3ab03 100644 --- a/flash/flash.h +++ b/flash/flash.h @@ -38,82 +38,104 @@ Includes #include /* Project includes */ +#ifndef A0010 #include "sensor.h" +#endif /*------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------*/ -/* Flash subcommand bitmasks */ -#define FLASH_SUBCMD_OP_BITMASK 0b11100000 -#define FLASH_NBYTES_BITMASK 0b00011111 - -/* Write protection ON/OFF States */ -#define FLASH_WP_READ_ONLY true -#define FLASH_WP_WRITE_ENABLED false - -/* Flash Chip operation codes from datasheet */ -#define FLASH_OP_HW_READ 0x03 -#define FLASH_OP_HW_READ_HS 0x0B -#define FLASH_OP_HW_4K_ERASE 0x20 -#define FLASH_OP_HW_32K_ERASE 0x52 -#define FLASH_OP_HW_64K_ERASE 0xD8 -#define FLASH_OP_HW_FULL_ERASE 0x60 -#define FLASH_OP_HW_BYTE_PROGRAM 0x02 -#define FLASH_OP_HW_AAI_PROGRAM 0xAD -#define FLASH_OP_HW_RDSR 0x05 -#define FLASH_OP_HW_EWSR 0x50 -#define FLASH_OP_HW_WRSR 0x01 -#define FLASH_OP_HW_WREN 0x06 -#define FLASH_OP_HW_WRDI 0x04 -#define FLASH_OP_HW_RDID 0x90 -#define FLASH_OP_HW_JEDEC_ID 0x9F -#define FLASH_OP_HW_EBSY 0x70 -#define FLASH_OP_HW_DBSY 0x80 - -/* Maximum Flash address */ -#define FLASH_MAX_ADDR 0x07FFFF - -/* Reset state of flash register */ -#define FLASH_REG_RESET_VAL 0b00111000 - -/* Timeouts */ -#ifndef SDR_DEBUG - #define HAL_FLASH_TIMEOUT 100 +#ifndef A0010 + /* Flash subcommand bitmasks */ + #define FLASH_SUBCMD_OP_BITMASK 0b11100000 + #define FLASH_NBYTES_BITMASK 0b00011111 + + /* Write protection ON/OFF States */ + #define FLASH_WP_READ_ONLY true + #define FLASH_WP_WRITE_ENABLED false + + /* Flash Chip operation codes from datasheet */ + #define FLASH_OP_HW_READ 0x03 + #define FLASH_OP_HW_READ_HS 0x0B + #define FLASH_OP_HW_4K_ERASE 0x20 + #define FLASH_OP_HW_32K_ERASE 0x52 + #define FLASH_OP_HW_64K_ERASE 0xD8 + #define FLASH_OP_HW_FULL_ERASE 0x60 + #define FLASH_OP_HW_BYTE_PROGRAM 0x02 + #define FLASH_OP_HW_AAI_PROGRAM 0xAD + #define FLASH_OP_HW_RDSR 0x05 + #define FLASH_OP_HW_EWSR 0x50 + #define FLASH_OP_HW_WRSR 0x01 + #define FLASH_OP_HW_WREN 0x06 + #define FLASH_OP_HW_WRDI 0x04 + #define FLASH_OP_HW_RDID 0x90 + #define FLASH_OP_HW_JEDEC_ID 0x9F + #define FLASH_OP_HW_EBSY 0x70 + #define FLASH_OP_HW_DBSY 0x80 + + /* Maximum Flash address */ + #define FLASH_MAX_ADDR 0x07FFFF + + /* Reset state of flash register */ + #define FLASH_REG_RESET_VAL 0b00111000 + + /* Timeouts */ + #ifndef SDR_DEBUG + #define HAL_FLASH_TIMEOUT 100 + #else + #define HAL_FLASH_TIMEOUT 0xFFFFFFFF + #endif + + /* Flash busy/ready boolean codes */ + #define FLASH_BUSY true + #define FLASH_READY false + + /* Status register bitmasks */ + #define FLASH_BUSY_BITMASK 0b00000001 + + /* Flash Block Addresses - 4Mbit of memory -> 512kB total + 4kB min sector size -> Max 128 sectors + 32kB sector size -> 16 Pages + 64kB sector size -> 8 Pages*/ + /* Use 32kB pages for up to 15 flight's recorded */ + #define FLASH_BLOCK0_ADDR 0x000000 + #define FLASH_BLOCK1_ADDR 0x008000 + #define FLASH_BLOCK2_ADDR 0x010000 + #define FLASH_BLOCK3_ADDR 0x018000 + #define FLASH_BLOCK4_ADDR 0x020000 + #define FLASH_BLOCK5_ADDR 0x028000 + #define FLASH_BLOCK6_ADDR 0x030000 + #define FLASH_BLOCK7_ADDR 0x038000 + #define FLASH_BLOCK8_ADDR 0x040000 + #define FLASH_BLOCK9_ADDR 0x048000 + #define FLASH_BLOCK10_ADDR 0x050000 + #define FLASH_BLOCK11_ADDR 0x058000 + #define FLASH_BLOCK12_ADDR 0x060000 + #define FLASH_BLOCK13_ADDR 0x068000 + #define FLASH_BLOCK14_ADDR 0x070000 + #define FLASH_BLOCK15_ADDR 0x078000 #else - #define HAL_FLASH_TIMEOUT 0xFFFFFFFF + /* Config Commands */ + #define FLASH_WRITE_ENABLE_CMD 0x06 + #define FLASH_WRITE_DISABLE_CMD 0x04 + #define FLASH_READ_STATUS_REG_CMD 0x05 + #define FLASH_READ_CFG_REG_CMD 0x15 + #define FLASH_WRITE_STATUS_CFG_REG_CMD 0x01 + #define FLASH_ENABLE_QSPI_CMD 0x35 /* MUST be performed in SPI mode */ + #define FLASH_DISABLE_QSPI_CMD 0xF5 /* MUST be performed in QSPI mode */ + #define FLASH_ENABLE_4BYTE_ADDR_CMD 0xB7 + #define FLASH_SET_BURST_LENGTH_CMD 0xC0 + /* I/O Commands */ + #define FLASH_READ_CMD 0xEC + #define FLASH_PAGE_WRITE_CMD 0x12 + #define FLASH_CHIP_ERASE_CMD 0xC7 + #define FLASH_SECTOR_ERASE_4KB_CMD 0x21 + #define FLASH_BLOCK_ERASE_32KB_CMD 0x5C + #define FLASH_BLOCK_ERASE_64KB_CMD 0xDC #endif -/* Flash busy/ready boolean codes */ -#define FLASH_BUSY true -#define FLASH_READY false - -/* Status register bitmasks */ -#define FLASH_BUSY_BITMASK 0b00000001 - -/* Flash Block Addresses - 4Mbit of memory -> 512kB total - 4kB min sector size -> Max 128 sectors - 32kB sector size -> 16 Pages - 64kB sector size -> 8 Pages*/ -/* Use 32kB pages for up to 15 flight's recorded */ -#define FLASH_BLOCK0_ADDR 0x000000 -#define FLASH_BLOCK1_ADDR 0x008000 -#define FLASH_BLOCK2_ADDR 0x010000 -#define FLASH_BLOCK3_ADDR 0x018000 -#define FLASH_BLOCK4_ADDR 0x020000 -#define FLASH_BLOCK5_ADDR 0x028000 -#define FLASH_BLOCK6_ADDR 0x030000 -#define FLASH_BLOCK7_ADDR 0x038000 -#define FLASH_BLOCK8_ADDR 0x040000 -#define FLASH_BLOCK9_ADDR 0x048000 -#define FLASH_BLOCK10_ADDR 0x050000 -#define FLASH_BLOCK11_ADDR 0x058000 -#define FLASH_BLOCK12_ADDR 0x060000 -#define FLASH_BLOCK13_ADDR 0x068000 -#define FLASH_BLOCK14_ADDR 0x070000 -#define FLASH_BLOCK15_ADDR 0x078000 - /*------------------------------------------------------------------------------ Typdefs From 473eda07c8d7f065b6f2680ac8bc5b48bd981e2d Mon Sep 17 00:00:00 2001 From: ETSound Date: Tue, 5 May 2026 11:14:24 -0700 Subject: [PATCH 3/8] Add "legacy" disclaimer to flash. --- flash/flash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flash/flash.c b/flash/flash.c index f682834..9c4f0c0 100644 --- a/flash/flash.c +++ b/flash/flash.c @@ -5,7 +5,12 @@ * * DESCRIPTION: * Contains API functions for writing and reading data from the engine -* controller's flash +* controller's flash. +* +* NOTE: +* This is the "legacy" flash driver for the 4MBit +* SST25VF040B-50-4I-S2AE-T flash chip used on old liquids & flight +* boards. * * COPYRIGHT: * Copyright (c) 2025 Sun Devil Rocketry. From 81e5a89f0de1b5e1a8cf034643876173cccab061 Mon Sep 17 00:00:00 2001 From: ETSound Date: Tue, 5 May 2026 12:00:51 -0700 Subject: [PATCH 4/8] Finish initialization routines --- flash/MX25L51245GZ2I-08G.c | 249 +++++++++++++++++++++++++++---------- flash/flash.h | 23 +++- 2 files changed, 208 insertions(+), 64 deletions(-) diff --git a/flash/MX25L51245GZ2I-08G.c b/flash/MX25L51245GZ2I-08G.c index 00855cc..cf076d3 100644 --- a/flash/MX25L51245GZ2I-08G.c +++ b/flash/MX25L51245GZ2I-08G.c @@ -31,7 +31,7 @@ #include "flash.h" #include "stm32h7xx_hal.h" - +#include "sdr_pin_defines_A0010.h" /* Global Variables ----------------------------------------------------------*/ @@ -44,6 +44,16 @@ static FLASH_STATUS flash_qspi_enable void ); +static FLASH_STATUS flash_write_enable + ( + void + ); + +static FLASH_STATUS flash_enable_4byte_addressing + ( + void + ); + /* Procedures ----------------------------------------------------------------*/ @@ -62,30 +72,13 @@ FLASH_STATUS flash_init Local variables ------------------------------------------------------------------------------*/ FLASH_STATUS flash_status; /* Flash API function return codes */ -uint8_t status_register; /* Desired status register contents */ /*------------------------------------------------------------------------------ Initializations ------------------------------------------------------------------------------*/ flash_status = FLASH_OK; -status_register = 0U; - - -/*------------------------------------------------------------------------------ - Pre-processing -------------------------------------------------------------------------------*/ - -// /* Check for invalid BPL setting */ -// if ( pflash_handle -> bpl_bits > FLASH_BPL_ALL ) -// { -// return FLASH_INVALID_INPUT; -// } - -// /* Determine the desired status register contents */ -// status_register &= pflash_handle -> bpl_bits; -// status_register |= pflash_handle -> bpl_write_protect; - +pflash_handle -> status_register = 0; /*------------------------------------------------------------------------------ API Function Implementation @@ -98,47 +91,31 @@ if ( flash_qspi_enable() != FLASH_OK ) } /* Write enable */ -// if ( pflash_handle -> write_protected ) -// { -// flash_write_disable(); -// return FLASH_OK; -// } -// else -// { -// flash_write_enable(); -// } - -// /* Check the flash chip status register to confirm chip can be reached */ -// flash_status = flash_get_status( pflash_handle ); -// if ( flash_status != FLASH_OK ) -// { -// return flash_status; -// } -// else if ( pflash_handle -> status_register == 0xFF ) -// { -// return FLASH_INIT_FAIL; -// } - -// /* Disable writing to the chip in case of prior interrupted write operation */ -// if ( write_disable() != FLASH_OK ) -// { -// return FLASH_CANNOT_WRITE_DISABLE; -// } - -// /* Set the bpl bits in the flash chip */ -// flash_status = flash_set_status( status_register ); - -// /* Confirm Status register contents */ -// while( flash_is_flash_busy() == FLASH_BUSY ){} -// flash_status = flash_get_status( pflash_handle ); -// if ( pflash_handle -> status_register != status_register ) -// { -// return FLASH_INIT_FAIL; -// } -// else -// { -// return flash_status; -// } +if ( flash_write_enable() != FLASH_OK ) + { + return FLASH_INIT_FAIL; + } +else + { + pflash_handle -> write_protected = false; + } + +/* Enable 4-byte addressing */ +if ( flash_enable_4byte_addressing() != FLASH_OK ) + { + return FLASH_INIT_FAIL; + } + +/* Check the flash chip status register to confirm chip can be reached */ +flash_status = flash_get_status( pflash_handle ); +if ( flash_status != FLASH_OK ) + { + return flash_status; + } +else if ( !(pflash_handle -> status_register & FLASH_STATUS_REG_QUAD_ENABLED) ) + { + return FLASH_INIT_FAIL; + } return FLASH_OK; @@ -156,15 +133,161 @@ OSPI_RegularCmdTypeDef spi_command = {0}; /* Construct QSPI enable command (single SPI mode) */ spi_command.Instruction = FLASH_ENABLE_QSPI_CMD; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_NONE; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; /* Transmit (blocking) */ -hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); + +if( hal_status == HAL_OK ) + { + return FLASH_OK; + } +else + { + return FLASH_FAIL; + } + +} /* flash_qspi_enable */ + + +static FLASH_STATUS flash_write_enable + ( + void + ) +{ +/* Initializations */ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; + +/* Construct write enable command (no address/data) */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_WRITE_ENABLE_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_NONE; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +/* Transmit (blocking) */ +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); + +if( hal_status == HAL_OK ) + { + return FLASH_OK; + } +else + { + return FLASH_FAIL; + } + +} /* flash_write_enable */ + + +FLASH_STATUS flash_get_status + ( + HFLASH_BUFFER* pflash_handle + ) +{ +/* Initializations */ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; + +if ( pflash_handle == NULL ) + { + return FLASH_INVALID_INPUT; + } + +/* Construct "Read Status Register" command */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_READ_STATUS_REG_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_1_LINE; +spi_command.NbData = 1; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } -return ( hal_status == HAL_OK ); +hal_status = HAL_OSPI_Receive(&FLASH_OSPI, &(pflash_handle->status_register), HAL_FLASH_TIMEOUT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +return FLASH_OK; + +} /* flash_get_status */ + + +static FLASH_STATUS flash_enable_4byte_addressing + ( + void + ) +{ +/* Initializations */ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; + +/* Construct "Enter 4-byte address mode" command (no address/data) */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_ENABLE_4BYTE_ADDR_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_NONE; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); + +if( hal_status == HAL_OK ) + { + return FLASH_OK; + } +else + { + return FLASH_FAIL; + } -} /* flash_qspi_enable */ \ No newline at end of file +} /* flash_enable_4byte_addressing */ \ No newline at end of file diff --git a/flash/flash.h b/flash/flash.h index cd3ab03..8ce262a 100644 --- a/flash/flash.h +++ b/flash/flash.h @@ -42,12 +42,17 @@ Includes #include "sensor.h" #endif +/* Aliasing -- choose implementation */ +#ifndef A0010 +#define USE_LEGACY_FLASH_DRIVER +#endif + /*------------------------------------------------------------------------------ Macros ------------------------------------------------------------------------------*/ -#ifndef A0010 +#ifdef USE_LEGACY_FLASH_DRIVER /* Flash subcommand bitmasks */ #define FLASH_SUBCMD_OP_BITMASK 0b11100000 #define FLASH_NBYTES_BITMASK 0b00011111 @@ -117,6 +122,8 @@ Includes #define FLASH_BLOCK14_ADDR 0x070000 #define FLASH_BLOCK15_ADDR 0x078000 #else + /* Utility Macros */ + #define HAL_FLASH_TIMEOUT 100 /* Config Commands */ #define FLASH_WRITE_ENABLE_CMD 0x06 #define FLASH_WRITE_DISABLE_CMD 0x04 @@ -134,6 +141,16 @@ Includes #define FLASH_SECTOR_ERASE_4KB_CMD 0x21 #define FLASH_BLOCK_ERASE_32KB_CMD 0x5C #define FLASH_BLOCK_ERASE_64KB_CMD 0xDC + + /* Status Register Bitmasks */ + #define FLASH_STATUS_REG_WRITE_PROTECTED 0b10000000 + #define FLASH_STATUS_REG_QUAD_ENABLED 0b01000000 + #define FLASH_STATUS_REG_BP3 0b00100000 + #define FLASH_STATUS_REG_BP2 0b00010000 + #define FLASH_STATUS_REG_BP1 0b00001000 + #define FLASH_STATUS_REG_BP0 0b00000100 + #define FLASH_STATUS_REG_WEL 0b00000010 + #define FLASH_STATUS_REG_WIP 0b00000001 #endif @@ -176,11 +193,13 @@ typedef struct _FLASH_BUFFER_TAG { /* Write protection state */ bool write_protected; + #ifdef USE_LEGACY_FLASH_DRIVER /* BPL settings for block protection */ FLASH_BPL_BITS bpl_bits; /* Write protection setting of flash BPL bits */ FLASH_BPL_WP bpl_write_protect; + #endif /* Contents of status register */ uint8_t status_register; @@ -290,6 +309,7 @@ bool flash_is_flash_busy void ); +#ifdef USE_LEGACY_FLASH_DRIVER /* Enable writing to the external flash chip */ void flash_write_enable ( @@ -301,6 +321,7 @@ void flash_write_disable ( void ); +#endif /* Write bytes from a flash buffer to the external flash */ FLASH_STATUS flash_write From aa1740e629db933ce5b9bad746fcead22372ef00 Mon Sep 17 00:00:00 2001 From: ETSound Date: Tue, 5 May 2026 12:45:28 -0700 Subject: [PATCH 5/8] Possibly finished flash driver? --- flash/MX25L51245GZ2I-08G.c | 357 ++++++++++++++++++++++++++++++++++++- flash/flash.h | 16 +- 2 files changed, 363 insertions(+), 10 deletions(-) diff --git a/flash/MX25L51245GZ2I-08G.c b/flash/MX25L51245GZ2I-08G.c index cf076d3..8870042 100644 --- a/flash/MX25L51245GZ2I-08G.c +++ b/flash/MX25L51245GZ2I-08G.c @@ -54,11 +54,20 @@ static FLASH_STATUS flash_enable_4byte_addressing void ); +static FLASH_STATUS flash_wait_ready + ( + uint32_t timeout_ms + ); + /* Procedures ----------------------------------------------------------------*/ /** * @brief Initializes the flash driver + * + * @details This function should be called before any other in the flash + * driver, as it initializes the driver to a known state that allows other + * commands to function properly. * * @param pflash_handle Pointer to the flash handle for this device. * @retval The status of the flash peripheral. @@ -122,6 +131,289 @@ return FLASH_OK; } /* flash_init */ +/** + * @brief Erase the entire contents of the flash chip. + * + * @param pflash_handle A pointer to the flash handle object to be used for the operation. + * @retval The status of the flash peripheral. + */ +FLASH_STATUS flash_erase + ( + HFLASH_BUFFER* pflash_handle + ) +{ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; + +if ( pflash_handle == NULL ) + { + return FLASH_INVALID_INPUT; + } +else if ( pflash_handle -> write_protected ) + { + return FLASH_WRITE_PROTECTED; + } + +/* Construct command */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_CHIP_ERASE_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_NONE; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +/* Wait until the device clears BUSY bit */ +return flash_wait_ready(FLASH_TIMEOUT_ERASE); + +} /* flash_erase */ + + +/** + * @brief Erase a block of flash. + * + * @param flash_block_num The number of the block to erase (0-indexed). + * @param size The size of the block to erase. + * + * @retval The status of the flash peripheral. + */ +FLASH_STATUS flash_block_erase + ( + FLASH_BLOCK flash_block_num, + FLASH_BLOCK_SIZE size + ) +{ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; +uint32_t addr = 0; +uint32_t end_addr = 0; +uint32_t opcode = 0; + +/* Convert the block number/size to addresses and operations */ +switch ( size ) + { + case FLASH_BLOCK_4K: + opcode = FLASH_SECTOR_ERASE_4KB_CMD; + addr = ((uint32_t)flash_block_num) * 0x1000u; + end_addr = (addr + 0x1000) - 1; + break; + + case FLASH_BLOCK_32K: + opcode = FLASH_BLOCK_ERASE_32KB_CMD; + addr = ((uint32_t)flash_block_num) * 0x8000u; + end_addr = (addr + 0x8000) - 1; + break; + + case FLASH_BLOCK_64K: + opcode = FLASH_BLOCK_ERASE_64KB_CMD; + addr = ((uint32_t)flash_block_num) * 0x10000u; + end_addr = (addr + 0x10000) - 1; + break; + + default: + return FLASH_INVALID_INPUT; + } + +/* Validate addresses */ +if( end_addr > FLASH_MAX_ADDR ) + { + return FLASH_INVALID_INPUT; + } + +/* Construct command */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = opcode; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.Address = addr; +spi_command.AddressMode = HAL_OSPI_ADDRESS_1_LINE; +spi_command.AddressSize = HAL_OSPI_ADDRESS_32_BITS; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_NONE; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +return flash_wait_ready(FLASH_TIMEOUT_ERASE); + +} /* flash_block_erase */ + + +/** + * @brief Write up to a page (256 bytes) to the flash memory. + * + * @param pflash_handle A pointer to the flash handle object to be used for the operation. + * @retval The status of the flash peripheral. + */ +FLASH_STATUS flash_write + ( + HFLASH_BUFFER* pflash_handle + ) +{ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; +size_t len = 0; + +if ( (pflash_handle == NULL) || (pflash_handle->pbuffer == NULL) ) + { + return FLASH_INVALID_INPUT; + } + +len = pflash_handle->num_bytes; +if ( ( len == 0u ) + || ( len > FLASH_PAGE_SIZE ) ) + { + return FLASH_INVALID_INPUT; + } + +/* Validate addresses */ +if( ( pflash_handle->address + len ) - 1 > FLASH_MAX_ADDR ) + { + return FLASH_INVALID_INPUT; + } + +/* Assumes flash_init() already enabled QSPI + write enable */ + +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_PAGE_PROGRAM_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.Address = pflash_handle->address; +spi_command.AddressMode = HAL_OSPI_ADDRESS_1_LINE; +spi_command.AddressSize = HAL_OSPI_ADDRESS_32_BITS; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_4_LINES; +spi_command.NbData = len; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = 0; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +hal_status = HAL_OSPI_Transmit(&FLASH_OSPI, pflash_handle->pbuffer, FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +return flash_wait_ready(FLASH_TIMEOUT_DEFAULT); + +} /* flash_write */ + + +/** + * @brief Read data from the flash memory. + * + * @param pflash_handle A pointer to the flash handle object to be used for the operation. + * @retval The status of the flash peripheral. + */ +FLASH_STATUS flash_read + ( + HFLASH_BUFFER* pflash_handle, + uint32_t num_bytes + ) +{ +HAL_StatusTypeDef hal_status = HAL_OK; +OSPI_RegularCmdTypeDef spi_command = {0}; +size_t len = 0; + +/* Verify valid pointers */ +if ( ( pflash_handle == NULL ) + || ( pflash_handle->pbuffer == NULL ) ) + { + return FLASH_INVALID_INPUT; + } + +/* If we're reading more bytes than the buffer can handle, we fail so we prevent overflow */ +len = num_bytes; +if ( ( len == 0u ) + || ( len > pflash_handle->num_bytes ) ) + { + return FLASH_INVALID_INPUT; + } + +/* Validate addresses */ +if( ( pflash_handle->address + len ) - 1 > FLASH_MAX_ADDR ) + { + return FLASH_INVALID_INPUT; + } + +/* Construct command */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_READ_CMD; +spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; +spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; +spi_command.Address = pflash_handle->address; +spi_command.AddressMode = HAL_OSPI_ADDRESS_1_LINE; +spi_command.AddressSize = HAL_OSPI_ADDRESS_32_BITS; +spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; +spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; +spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; +spi_command.DataMode = HAL_OSPI_DATA_4_LINES; +spi_command.NbData = len; +spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; +spi_command.DummyCycles = FLASH_READ_DUMMY_CYCLES; +spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; +spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +hal_status = HAL_OSPI_Receive(&FLASH_OSPI, pflash_handle->pbuffer, FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) + { + return FLASH_FAIL; + } + +return FLASH_OK; + +} /* flash_read */ + + +/** + * @brief Enable QSPI mode on the flash peripheral. + * + * @retval The status of the flash peripheral. + */ static FLASH_STATUS flash_qspi_enable ( void @@ -149,7 +441,7 @@ spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; /* Transmit (blocking) */ -hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); if( hal_status == HAL_OK ) { @@ -163,6 +455,11 @@ else } /* flash_qspi_enable */ +/** + * @brief Enable writes to the flash peripheral. + * + * @retval The status of the flash peripheral. + */ static FLASH_STATUS flash_write_enable ( void @@ -190,7 +487,7 @@ spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; /* Transmit (blocking) */ -hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); if( hal_status == HAL_OK ) { @@ -204,6 +501,12 @@ else } /* flash_write_enable */ +/** + * @brief Retrieve the status register on the flash peripheral. + * + * @param pflash_handle A pointer to the flash handle object to be used for the operation. + * @retval The status of the flash peripheral. + */ FLASH_STATUS flash_get_status ( HFLASH_BUFFER* pflash_handle @@ -236,13 +539,13 @@ spi_command.DummyCycles = 0; spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; -hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); if ( hal_status != HAL_OK ) { return FLASH_FAIL; } -hal_status = HAL_OSPI_Receive(&FLASH_OSPI, &(pflash_handle->status_register), HAL_FLASH_TIMEOUT); +hal_status = HAL_OSPI_Receive(&FLASH_OSPI, &(pflash_handle->status_register), FLASH_TIMEOUT_DEFAULT); if ( hal_status != HAL_OK ) { return FLASH_FAIL; @@ -253,6 +556,11 @@ return FLASH_OK; } /* flash_get_status */ +/** + * @brief Enable four-byte addresses on the flash peripheral. + * + * @retval The status of the flash peripheral. + */ static FLASH_STATUS flash_enable_4byte_addressing ( void @@ -279,7 +587,7 @@ spi_command.DummyCycles = 0; spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; -hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, HAL_FLASH_TIMEOUT); +hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); if( hal_status == HAL_OK ) { @@ -290,4 +598,41 @@ else return FLASH_FAIL; } -} /* flash_enable_4byte_addressing */ \ No newline at end of file +} /* flash_enable_4byte_addressing */ + + +/** + * @brief Busy-wait until the flash signals ready status. + * + * @param timeout_ms The amount of time to wait (in ms) for the operation to complete. + * @retval The status of the flash peripheral. + */ +static FLASH_STATUS flash_wait_ready + ( + uint32_t timeout_ms + ) +{ +uint32_t start = HAL_GetTick(); +HFLASH_BUFFER handle = {0}; + +while ( true ) + { + if ( flash_get_status( &handle ) != FLASH_OK ) + { + return FLASH_SPI_ERROR; + } + + if ( ( handle.status_register & FLASH_STATUS_REG_WIP ) == 0u ) + { + return FLASH_OK; + } + + if ( timeout_ms != 0xFFFFFFFFu ) + { + if ( ( HAL_GetTick() - start ) > timeout_ms ) + { + return FLASH_TIMEOUT; + } + } + } +} \ No newline at end of file diff --git a/flash/flash.h b/flash/flash.h index 8ce262a..c23bf03 100644 --- a/flash/flash.h +++ b/flash/flash.h @@ -123,7 +123,11 @@ Includes #define FLASH_BLOCK15_ADDR 0x078000 #else /* Utility Macros */ - #define HAL_FLASH_TIMEOUT 100 + #define FLASH_TIMEOUT_DEFAULT 100 + #define FLASH_TIMEOUT_ERASE 1000 + #define FLASH_READ_DUMMY_CYCLES 8 + #define FLASH_PAGE_SIZE 256 + #define FLASH_MAX_ADDR 0x03FFFFFF /* Config Commands */ #define FLASH_WRITE_ENABLE_CMD 0x06 #define FLASH_WRITE_DISABLE_CMD 0x04 @@ -135,8 +139,8 @@ Includes #define FLASH_ENABLE_4BYTE_ADDR_CMD 0xB7 #define FLASH_SET_BURST_LENGTH_CMD 0xC0 /* I/O Commands */ - #define FLASH_READ_CMD 0xEC - #define FLASH_PAGE_WRITE_CMD 0x12 + #define FLASH_READ_CMD 0x6B + #define FLASH_PAGE_PROGRAM_CMD 0x12 #define FLASH_CHIP_ERASE_CMD 0xC7 #define FLASH_SECTOR_ERASE_4KB_CMD 0x21 #define FLASH_BLOCK_ERASE_32KB_CMD 0x5C @@ -246,6 +250,7 @@ typedef enum FLASH_STATUS } FLASH_STATUS; /* Flash Block Numbers */ +#ifdef USE_LEGACY_FLASH_DRIVER typedef enum _FLASH_BLOCK { FLASH_BLOCK_0 = 0, @@ -262,8 +267,11 @@ typedef enum _FLASH_BLOCK FLASH_BLOCK_12 , FLASH_BLOCK_13 , FLASH_BLOCK_14 , - FLASH_BLOCK_15 + FLASH_BLOCK_15 , } FLASH_BLOCK; +#else +typedef uint32_t FLASH_BLOCK; +#endif /* Flash Block Sizes */ typedef enum _FLASH_BLOCK_SIZE From 5fa3056657ebad17f813df8174ab0938107601fa Mon Sep 17 00:00:00 2001 From: ETSound Date: Tue, 5 May 2026 12:56:25 -0700 Subject: [PATCH 6/8] Final tweaks --- flash/MX25L51245GZ2I-08G.c | 106 ++++++++++++++++++++++--------------- flash/flash.h | 9 +++- 2 files changed, 71 insertions(+), 44 deletions(-) diff --git a/flash/MX25L51245GZ2I-08G.c b/flash/MX25L51245GZ2I-08G.c index 8870042..407af08 100644 --- a/flash/MX25L51245GZ2I-08G.c +++ b/flash/MX25L51245GZ2I-08G.c @@ -409,58 +409,87 @@ return FLASH_OK; } /* flash_read */ +FLASH_STATUS flash_is_flash_busy + ( + HFLASH_BUFFER* pflash_handle + ) +{ +if ( flash_get_status( pflash_handle ) != FLASH_OK ) + { + return FLASH_FAIL; + } +else if ( ( pflash_handle->status_register & FLASH_STATUS_REG_WIP ) == 0u ) + { + return FLASH_OK; + } +else + { + return FLASH_IN_PROGRESS; + } +} + + /** - * @brief Enable QSPI mode on the flash peripheral. + * @brief Retrieve the status register on the flash peripheral. * + * @param pflash_handle A pointer to the flash handle object to be used for the operation. * @retval The status of the flash peripheral. */ -static FLASH_STATUS flash_qspi_enable +FLASH_STATUS flash_get_status ( - void + HFLASH_BUFFER* pflash_handle ) { /* Initializations */ HAL_StatusTypeDef hal_status = HAL_OK; OSPI_RegularCmdTypeDef spi_command = {0}; -/* Construct QSPI enable command (single SPI mode) */ -spi_command.Instruction = FLASH_ENABLE_QSPI_CMD; +if ( pflash_handle == NULL ) + { + return FLASH_INVALID_INPUT; + } + +/* Construct "Read Status Register" command */ +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; spi_command.FlashId = HAL_OSPI_FLASH_ID_1; +spi_command.Instruction = FLASH_READ_STATUS_REG_CMD; spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; -spi_command.DataMode = HAL_OSPI_DATA_NONE; +spi_command.DataMode = HAL_OSPI_DATA_1_LINE; +spi_command.NbData = 1; spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; spi_command.DummyCycles = 0; spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; -spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; -spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; -/* Transmit (blocking) */ hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); - -if( hal_status == HAL_OK ) +if ( hal_status != HAL_OK ) { - return FLASH_OK; + return FLASH_FAIL; } -else + +hal_status = HAL_OSPI_Receive(&FLASH_OSPI, &(pflash_handle->status_register), FLASH_TIMEOUT_DEFAULT); +if ( hal_status != HAL_OK ) { return FLASH_FAIL; } -} /* flash_qspi_enable */ +return FLASH_OK; + +} /* flash_get_status */ /** - * @brief Enable writes to the flash peripheral. + * @brief Enable QSPI mode on the flash peripheral. * * @retval The status of the flash peripheral. */ -static FLASH_STATUS flash_write_enable +static FLASH_STATUS flash_qspi_enable ( void ) @@ -469,12 +498,10 @@ static FLASH_STATUS flash_write_enable HAL_StatusTypeDef hal_status = HAL_OK; OSPI_RegularCmdTypeDef spi_command = {0}; -/* Construct write enable command (no address/data) */ -spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +/* Construct QSPI enable command (single SPI mode) */ +spi_command.Instruction = FLASH_ENABLE_QSPI_CMD; spi_command.FlashId = HAL_OSPI_FLASH_ID_1; -spi_command.Instruction = FLASH_WRITE_ENABLE_CMD; spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; -spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; @@ -485,6 +512,8 @@ spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; spi_command.DummyCycles = 0; spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; +spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; /* Transmit (blocking) */ hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); @@ -498,33 +527,27 @@ else return FLASH_FAIL; } -} /* flash_write_enable */ +} /* flash_qspi_enable */ /** - * @brief Retrieve the status register on the flash peripheral. + * @brief Enable writes to the flash peripheral. * - * @param pflash_handle A pointer to the flash handle object to be used for the operation. * @retval The status of the flash peripheral. */ -FLASH_STATUS flash_get_status +static FLASH_STATUS flash_write_enable ( - HFLASH_BUFFER* pflash_handle + void ) { /* Initializations */ HAL_StatusTypeDef hal_status = HAL_OK; OSPI_RegularCmdTypeDef spi_command = {0}; -if ( pflash_handle == NULL ) - { - return FLASH_INVALID_INPUT; - } - -/* Construct "Read Status Register" command */ +/* Construct write enable command (no address/data) */ spi_command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG; spi_command.FlashId = HAL_OSPI_FLASH_ID_1; -spi_command.Instruction = FLASH_READ_STATUS_REG_CMD; +spi_command.Instruction = FLASH_WRITE_ENABLE_CMD; spi_command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; spi_command.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS; spi_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE; @@ -532,28 +555,25 @@ spi_command.AddressMode = HAL_OSPI_ADDRESS_NONE; spi_command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE; spi_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; spi_command.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE; -spi_command.DataMode = HAL_OSPI_DATA_1_LINE; -spi_command.NbData = 1; +spi_command.DataMode = HAL_OSPI_DATA_NONE; spi_command.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE; spi_command.DummyCycles = 0; spi_command.DQSMode = HAL_OSPI_DQS_DISABLE; spi_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; +/* Transmit (blocking) */ hal_status = HAL_OSPI_Command(&FLASH_OSPI, &spi_command, FLASH_TIMEOUT_DEFAULT); -if ( hal_status != HAL_OK ) + +if( hal_status == HAL_OK ) { - return FLASH_FAIL; + return FLASH_OK; } - -hal_status = HAL_OSPI_Receive(&FLASH_OSPI, &(pflash_handle->status_register), FLASH_TIMEOUT_DEFAULT); -if ( hal_status != HAL_OK ) +else { return FLASH_FAIL; } -return FLASH_OK; - -} /* flash_get_status */ +} /* flash_write_enable */ /** @@ -619,7 +639,7 @@ while ( true ) { if ( flash_get_status( &handle ) != FLASH_OK ) { - return FLASH_SPI_ERROR; + return FLASH_FAIL; } if ( ( handle.status_register & FLASH_STATUS_REG_WIP ) == 0u ) diff --git a/flash/flash.h b/flash/flash.h index c23bf03..ed016d0 100644 --- a/flash/flash.h +++ b/flash/flash.h @@ -229,6 +229,7 @@ typedef enum FLASH_STATUS { FLASH_OK = 0 , FLASH_FAIL , + FLASH_IN_PROGRESS , FLASH_UNSUPPORTED_OP , FLASH_UNRECOGNIZED_OP , FLASH_TIMEOUT , @@ -311,13 +312,13 @@ FLASH_STATUS flash_set_status uint8_t flash_status ); +#ifdef USE_LEGACY_FLASH_DRIVER /* Check if the flash chip is ready for write operations */ bool flash_is_flash_busy ( void ); -#ifdef USE_LEGACY_FLASH_DRIVER /* Enable writing to the external flash chip */ void flash_write_enable ( @@ -329,6 +330,12 @@ void flash_write_disable ( void ); +#else +/* Returns FLASH_IN_PROGRESS if the chip is currently programming. */ +FLASH_STATUS flash_is_flash_busy + ( + HFLASH_BUFFER* pflash_handle + ); #endif /* Write bytes from a flash buffer to the external flash */ From b9cef2409477f68907a44b9dd3d11a4e5681b076 Mon Sep 17 00:00:00 2001 From: ETSound Date: Sun, 31 May 2026 17:09:41 -0700 Subject: [PATCH 7/8] Better null-checks for safety --- flash/MX25L51245GZ2I-08G.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/flash/MX25L51245GZ2I-08G.c b/flash/MX25L51245GZ2I-08G.c index 407af08..c04764c 100644 --- a/flash/MX25L51245GZ2I-08G.c +++ b/flash/MX25L51245GZ2I-08G.c @@ -3,7 +3,7 @@ * @file : MX25L51245GZ2I-08G.c * @brief : Driver for the flash chip on FC rev 3. ****************************************************************************** - * @attention + * @copyright * * Copyright (c) 2026 Sun Devil Rocketry. * All rights reserved. @@ -92,6 +92,11 @@ pflash_handle -> status_register = 0; /*------------------------------------------------------------------------------ API Function Implementation ------------------------------------------------------------------------------*/ +/* Protective Precondition */ +if ( pflash_handle == NULL ) + { + return FLASH_INVALID_INPUT; + } /* Activate QSPI */ if ( flash_qspi_enable() != FLASH_OK ) @@ -409,12 +414,22 @@ return FLASH_OK; } /* flash_read */ +/** + * @brief Identify whether flash is currently performing an operation on the chip. + * + * @param pflash_handle A pointer to the flash handle object to be used for the operation. + * @retval The status of the flash peripheral. + */ FLASH_STATUS flash_is_flash_busy ( HFLASH_BUFFER* pflash_handle ) { -if ( flash_get_status( pflash_handle ) != FLASH_OK ) +if ( pflash_handle == NULL ) + { + return FLASH_INVALID_INPUT; + } +else if ( flash_get_status( pflash_handle ) != FLASH_OK ) { return FLASH_FAIL; } @@ -647,12 +662,10 @@ while ( true ) return FLASH_OK; } - if ( timeout_ms != 0xFFFFFFFFu ) + if ( ( timeout_ms != 0xFFFFFFFFu ) + && ( ( HAL_GetTick() - start ) > timeout_ms ) ) { - if ( ( HAL_GetTick() - start ) > timeout_ms ) - { - return FLASH_TIMEOUT; - } + return FLASH_TIMEOUT; } } } \ No newline at end of file From 60bef1ef99c20027ae34f709c9b47c28e3ba5885 Mon Sep 17 00:00:00 2001 From: ETSound Date: Sun, 31 May 2026 17:10:11 -0700 Subject: [PATCH 8/8] oopsie --- flash/flash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flash/flash.h b/flash/flash.h index ed016d0..f059f6a 100644 --- a/flash/flash.h +++ b/flash/flash.h @@ -268,7 +268,7 @@ typedef enum _FLASH_BLOCK FLASH_BLOCK_12 , FLASH_BLOCK_13 , FLASH_BLOCK_14 , - FLASH_BLOCK_15 , + FLASH_BLOCK_15 } FLASH_BLOCK; #else typedef uint32_t FLASH_BLOCK;