Flash (Flash System Routine)

group group_hal_flash

High level interface to the internal flash memory.

Flash memory provides non-volatile storage for user firmware, user configuration data, and bulk data storage.

This driver allows data to be read from and written to flash. It also provides the ability to obtain information about the address and characteristics of the flash block(s) contained on the device. During flash write time, the device should not be reset (including XRES pin, software reset, and watchdog) or unexpected changes may be made to portions of the flash. Also, the low-voltage detect circuits should be configured to generate an interrupt instead of a reset.

note

A Read while Write violation may occur for some devices when a flash Read operation is initiated in the same or neighboring flash sector where the flash Write, Erase, or Program operation is working. Refer the the device datasheet for more information. This violation may cause a HardFault exception. To avoid the Read while Write violation, the user must carefully split the Read and Write operations on flash sectors which are not neighboring, considering all cores in a multi-processor device. You may edit the linker script to place the code into neighboring sectors. For example, use sectors number 0 and 1 for code and sectors 2 and 3 for data storage.

Features

  • Flash operations are performed on a per-sector basis

  • Supports blocking or partially blocking erase, program and write

Code Snippets

Snippet 1: Discovering flash characteristics

Following code snippet demonstrates how to discover flash characteristics. Refer cyhal_flash_info_t for more information.


    cyhal_flash_t      flash_obj;
    cyhal_flash_info_t flash_info;
    uint32_t           flash_start_address;
    uint32_t           flash_size;
    uint32_t           flash_sector_size;
    uint32_t           flash_page_size;
    uint8_t            flash_erase_value;

    // Initialize flash object
    cyhal_flash_init(&flash_obj);

    // Get flash characteristics
    cyhal_flash_get_info(&flash_obj, &flash_info);

    // Wait for 100ms for the flash write to complete
    uint32_t timeout = 100;

    // Wait for the command to finish execution
    while ((true != cyhal_flash_is_operation_complete(&flash_obj)) && (0 < timeout))
    {
        timeout--;
        cyhal_system_delay_ms(1); // delay one millisecond each iteration
    }

    if (0 != timeout)
    {
        for (int index = 0; index < flash_info.block_count; index++)
        {
            const cyhal_flash_block_info_t* block_info = flash_info.blocks;
            block_info         += index;
            flash_start_address = block_info->start_address;
            flash_size          = block_info->size;
            flash_sector_size   = block_info->sector_size;
            flash_page_size     = block_info->page_size;
            flash_erase_value   = block_info->erase_value;
        }
    }

Snippet 2: Blocking Flash Write Operation

Following code snippet demonstrates blocking flash write. It uses a constant array with a size equaling the size of one flash row. This array is placed at an address in flash such that it occupies one complete flash row. It uses blocking flash write operation which blocks the caller until the write is completed. It then verifies the flash data by comparing the flash data with the written data.


    // Use cyhal_flash_get_info() to obtain values for the particular device
    #define FLASH_START_ADDR        (0x10000000)
    #define FLASH_SIZE              (0x100000)
    #define FLASH_PAGE_SIZE         (512)
    #define LAST_FLASH_ROW          ((FLASH_SIZE/FLASH_PAGE_SIZE) - 1)

    // This array reserves space in the flash for one page of size FLASH_PAGE_SIZE. Explicit
    // initialization is required so that memory is allocated in flash instead of RAM.
    #define CALCULATE_FLASH_ADDRESS(row_num) (FLASH_START_ADDR + ((row_num) * FLASH_PAGE_SIZE))

    // Make the address point to last user flash page
    const uint8_t* flash_data_ptr = (uint8_t*)CALCULATE_FLASH_ADDRESS(LAST_FLASH_ROW);

    cy_rslt_t result;                               // Flash Write Status
    uint8_t   ram_data[FLASH_PAGE_SIZE];            // RAM data to be written to Flash
    uint8_t   flash_read_data[FLASH_PAGE_SIZE];     // RAM data read from Flash for validation
    bool      compare_status = false;               // Compare Status

    // Flash object
    cyhal_flash_t flash_obj;

    // Initialize flash object
    cyhal_flash_init(&flash_obj);

    // Initialize the data in RAM that will be written into flash
    for (int index = 0; index < FLASH_PAGE_SIZE; index++)
    {
        ram_data[index] = (uint8_t)index;
    }

    // Blocking flash erase prior to flash write
    result = cyhal_flash_erase(&flash_obj, (uint32_t)flash_data_ptr);

    if (result != CY_RSLT_SUCCESS)
    {
        // Error erasing flash
    }

    // Blocking flash write
    result = cyhal_flash_write(&flash_obj, (uint32_t)flash_data_ptr, (const uint32_t*)ram_data);

    if (CY_RSLT_SUCCESS == result)
    {
        // Read flash data
        result =
            cyhal_flash_read(&flash_obj, (uint32_t)flash_data_ptr, flash_read_data,
                             sizeof(flash_read_data));

        if (CY_RSLT_SUCCESS == result)
        {
            // Verify the data written into flash by comparing it with the RAM data
            if (0 == memcmp(ram_data, flash_read_data, sizeof(flash_read_data)))
            {
                compare_status = true;
            }
        }
    }

note

It is recommended to declare the flash array as global variable.

Snippet 3: Non-blocking Flash Write Operation using polling

Following code snippet implements the non-blocking flash write using polling to complete the flash write operation. It uses a constant array with a size equaling the size of one flash row. This array is placed at an address in flash such that it occupies one complete flash row. It uses a polling method to complete the flash write operation. It then verifies the flash data by comparing the flash data with the written data.


    // Use cyhal_flash_get_info() to obtain values for the particular device
    #define FLASH_START_ADDR        (0x10000000)
    #define FLASH_SIZE              (0x100000)
    #define FLASH_PAGE_SIZE         (512)
    #define LAST_FLASH_ROW          ((FLASH_SIZE/FLASH_PAGE_SIZE) - 1)

    // This array reserves space in the flash for one page of size FLASH_PAGE_SIZE. Explicit
    // initialization is required so that memory is allocated in flash instead of RAM.
    #define CALCULATE_FLASH_ADDRESS(row_num) (FLASH_START_ADDR + ((row_num) * FLASH_PAGE_SIZE))

    // Make the address point to last user flash page
    const uint8_t* flash_data_ptr = (uint8_t*)CALCULATE_FLASH_ADDRESS(LAST_FLASH_ROW);

    cy_rslt_t result;                               // Flash Write Status
    uint8_t   ram_data[FLASH_PAGE_SIZE];            // RAM data to be written to Flash
    uint8_t   flash_read_data[FLASH_PAGE_SIZE];     // RAM data read from Flash for validation
    bool      compare_status = false;               // Compare Status

    // Flash object
    cyhal_flash_t flash_obj;

    // Initialize flash object
    cyhal_flash_init(&flash_obj);

    // Initialize the data in RAM that will be written into flash
    for (int index = 0; index < FLASH_PAGE_SIZE; index++)
    {
        ram_data[index] = (uint8_t)index;
    }

    // Wait for 100ms for the flash write to complete
    uint32_t timeout = 100;

    // Partially blocking flash erase
    result = cyhal_flash_start_erase(&flash_obj, (uint32_t)flash_data_ptr);

    while (true != cyhal_flash_is_operation_complete(&flash_obj))
    {
        // Wait for the flash erase to be successful
    }

    // Partially-blocking flash write
    result =
        cyhal_flash_start_write(&flash_obj, (uint32_t)flash_data_ptr, (const uint32_t*)ram_data);

    if (CY_RSLT_SUCCESS == result)
    {
        // Wait for 100ms for the flash write to complete
        timeout = 100;

        // Wait for the successful flash write
        while ((true != cyhal_flash_is_operation_complete(&flash_obj)) && (0 < timeout))
        {
            timeout--;
            cyhal_system_delay_ms(1); // delay one millisecond each iteration
        }

        // Flag error if the expected flash write status not returned within timeout period
        if (0 != timeout)
        {
            // Read flash data
            result =
                cyhal_flash_read(&flash_obj, (uint32_t)flash_data_ptr, flash_read_data,
                                 sizeof(flash_read_data));

            if (CY_RSLT_SUCCESS == result)
            {
                // Verify the data written into flash by comparing it with the RAM data
                if (0 == memcmp(ram_data, flash_read_data, sizeof(flash_read_data)))
                {
                    compare_status = true;
                }
            }
        }
    }

note

It is recommended to declare the flash array as global variable.

Functions

cy_rslt_t cyhal_flash_init(cyhal_flash_t *obj)

Initialize the cyhal_flash_t object for accessing flash through the HAL.

Return

The status of the init request. Returns CY_RSLT_SUCCESS on successful operation.

Parameters
  • [out] obj: Pointer to a flash object. The caller must allocate the memory for this object but the init function will initialize its contents.

void cyhal_flash_free(cyhal_flash_t *obj)

Free resources associated with flash object through the HAL.

Parameters
  • [out] obj: The flash object.

void cyhal_flash_get_info(const cyhal_flash_t *obj, cyhal_flash_info_t *info)

Gets flash characteristics like the start address, size, erase values etc.

Refer cyhal_flash_info_t for more information.

Refer

Snippet 1: Discovering flash characteristics for more information.
Parameters
  • [in] obj: The flash object.

  • [out] info: The flash characteristic info.

cy_rslt_t cyhal_flash_read(cyhal_flash_t *obj, uint32_t address, uint8_t *data, size_t size)

Read data starting at a defined address.

Refer

Snippet 2: Blocking Flash Write Operation for more information.
Return

The status of the read request. Returns CY_RSLT_SUCCESS on successful operation.

Parameters
  • [in] obj: The flash object.

  • [in] address: Address to begin reading from.

  • [out] data: The buffer to read data into.

  • [in] size: The number of bytes to read.

cy_rslt_t cyhal_flash_erase(cyhal_flash_t *obj, uint32_t address)

Erase one page starting at a defined address.

The address must be at page boundary. This will block until the erase operation is complete.

Refer

Snippet 2: Blocking Flash Write Operation for more information.
See

cyhal_flash_get_info() to get the flash characteristics for legal address values and the page erase size.

Return

The status of the erase request. Returns CY_RSLT_SUCCESS on successful operation.

Parameters
  • [in] obj: The flash object

  • [in] address: The page starting address

cy_rslt_t cyhal_flash_write(cyhal_flash_t *obj, uint32_t address, const uint32_t *data)

This function erases the page and writes the new data into the page starting at a defined address.

The address must be at page boundary. This will block until the write operation is complete.

Refer

Snippet 2: Blocking Flash Write Operation for more information.
See

cyhal_flash_get_info() to get the flash characteristics for legal address values and the page write size. The provided data buffer must be at least as large as the flash page_size.

Return

The status of the write request. Returns CY_RSLT_SUCCESS on successful operation.

Parameters
  • [in] obj: The flash object

  • [in] address: The page starting address

  • [in] data: The data to write to the flash

cy_rslt_t cyhal_flash_program(cyhal_flash_t *obj, uint32_t address, const uint32_t *data)

Program one page with given data starting at defined address.

The address must be at page boundary. This will block until the write operation is complete.

note

This function does not erase the page prior to writing. The page must be erased first via a separate call to erase.

See

cyhal_flash_get_info() to get the flash characteristics for legal address values and the total page size. The provided data buffer must be at least as large as the flash page_size.

Return

The status of the program request. Returns CY_RSLT_SUCCESS on successful operation.

Parameters
  • [in] obj: The flash object

  • [in] address: The sector starting address

  • [in] data: The data buffer to be programmed

cy_rslt_t cyhal_flash_start_erase(cyhal_flash_t *obj, uint32_t address)

Starts an asynchronous erase of a single page of flash.

Returns immediately and reports a successful start or reason for failure. The address must be aligned on a page boundary.

Refer

Snippet 3: Non-blocking Flash Write Operation using polling for more information.
See

cyhal_flash_get_info() to get the flash characteristics for legal address values and the page erase size.

Return

The status of the start_erase request.

Parameters
  • [in] obj: The Flash object being operated on

  • [in] address: The address to start erasing from

cy_rslt_t cyhal_flash_start_write(cyhal_flash_t *obj, uint32_t address, const uint32_t *data)

Starts an asynchronous write to a single page of flash.

Returns immediately and reports a successful start or reason for failure. The address must be aligned on a page boundary.

Refer

Snippet 3: Non-blocking Flash Write Operation using polling for more information.
See

cyhal_flash_get_info() to get the flash characteristics for legal address values and the page write size. The provided data buffer must be at least as large as the flash page_size.

Return

The status of the start_write request.

Parameters
  • [in] obj: The Flash object being operated on

  • [in] address: The address to start writing to

  • [in] data: The data to write to flash

cy_rslt_t cyhal_flash_start_program(cyhal_flash_t *obj, uint32_t address, const uint32_t *data)

Starts asynchronous programming of a single page of flash.

Returns immediately and reports a successful start or reason for failure.

note

Perform erase operation prior to calling this.

See

cyhal_flash_get_info() to get the flash characteristics for legal address values and the total page size. The provided data buffer must be at least as large as the flash page_size.

Return

The status of the start_program request. Returns CY_RSLT_SUCCESS on successful operation.

Parameters
  • [in] obj: The Flash object being operated on

  • [in] address: The address to start programming

  • [in] data: The data to write to flash

bool cyhal_flash_is_operation_complete(cyhal_flash_t *obj)

Reports status of the flash operation.

Return

true if flash operation is complete. false otherwise.

Parameters
  • [in] obj: The Flash object being operated on

struct cyhal_flash_block_info_t
#include <cyhal_flash.h>

Information about a single block of flash memory.

Public Members

uint32_t start_address

Start address of the memory.

uint32_t size

Size of the flash memory.

uint32_t sector_size

Sector size of the memory.

uint32_t page_size

Page size of the memory.

uint8_t erase_value

The flash erase value.

struct cyhal_flash_info_t
#include <cyhal_flash.h>

Information about all of the blocks of flash memory.

Public Members

uint8_t block_count

The number of distinct flash blocks.

const cyhal_flash_block_info_t *blocks

Array of the distinct flash blocks.