cancel
Showing results for 
Search instead for 
Did you mean: 

Hardfault writing struct to STM32H7 flash using STM32 HAL Driver

gcoard
Associate

I'm trying to write a struct of size around 680 bytes to Sector 1, Bank 2 of the flash in an STM32H757XIH6. I'm pretty new to this kind of thing so I'm slowly building on the code. I'm using the STM32 HAL driver. The address of this sector is 0x08100000.

Here's the code:

 

typedef struct {
    uint32_t data_header;
    Parameter parameter[NUMBER_PARAMETERS];
    int screen_paras[MAX_SCREENS][MAX_WIDGETS];
} Persistent_data;


void save_data() {
    Persistent_data save_data;

    uint32_t data_header = DATA_HEADER;

    save_data.data_header = data_header;
    memcpy(save_data.parameter, parameter, sizeof(save_data.parameter));
    memcpy(save_data.screen_paras, screen_paras, sizeof(save_data.screen_paras));

    size_t size = sizeof(Persistent_data);
    uint32_t word_count = (size + 3) / 4; //32bit alignment
    Flash_Write(FLASH_START_ADDRESS, (uint32_t*)&save_data, word_count);
    }


HAL_StatusTypeDef Flash_Write(uint32_t address, uint32_t* data, uint32_t length) {
    HAL_StatusTypeDef status = HAL_OK;

    // Ensure address is within the flash range
    if (address < FLASH_USER_START_ADDR || (address + length) > FLASH_USER_END_ADDR) {
        return HAL_ERROR;
        }

    // Unlock the Flash
    HAL_FLASH_Unlock();

    // Erase the flash sector
    FLASH_EraseInitTypeDef eraseInitStruct = {
        .TypeErase = FLASH_TYPEERASE_SECTORS,
        .Banks = FLASH_BANK_2,
        .Sector = FLASH_SECTOR_1,
        .NbSectors = 1,
        .VoltageRange = FLASH_VOLTAGE_RANGE_3,
        };
    uint32_t sectorError = 0;

    status = HAL_FLASHEx_Erase(&eraseInitStruct, &sectorError);
    if (status != HAL_OK) {
        HAL_FLASH_Lock();
        return status;
        }

    // Write the data
     for (int i = 0; i < length / 4; i++) { // Writing 32-bit words
        status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, data[i]);
        if (status != HAL_OK) {
            break;
            }
        address += 4; // Increment address by 4 bytes (32 bits)
        }

    // Lock the Flash
    HAL_FLASH_Lock();
    return status;
    }

 

When I try to save the save_data (with all it's members) a hard fault is generated from the line 

status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, data[i]);

 

Tracing it further it gets to *dest_addr = *src_addr; in stm32h7xx_hal_flash.c. From there I'm not sure how to interpret the crash stack, next is <signal handler called>() at 0xffffffed 

 

ffffffed:   Failed to execute MI command:
          -data-disassemble -s 4294967277 -e 4294967529 -- 3
          Error message from debugger back end:
          Cannot access memory at address 0xffffffec

Please let me know if I can provide any more info

2 REPLIES 2
filipxsikora
Associate III

Hello,

first of all, H757 is a dual core. And the second core (CM4) has it's ROM starting at exactly 0x08100000. If you left it at default and haven't moved it, you just deleted CM4's ROM from under it's hands which could lead to all sorts of issues and crashes.

 

Second 

 

 

/**
  * @brief  Program a flash word at a specified address
  *   TypeProgram Indicate the way to program at a specified address.
  *         This parameter can be a value of @ref FLASH_Type_Program
  *   FlashAddress specifies the address to be programmed.
  *         This parameter shall be aligned to the Flash word:
  *          - 256 bits for STM32H74x/5X devices (8x 32bits words)
  *          - 128 bits for STM32H7Ax/BX devices (4x 32bits words)
  *          - 256 bits for STM32H72x/3X devices (8x 32bits words)
  *   DataAddress specifies the address of data to be programmed.
  *         This parameter shall be 32-bit aligned
  *
  * @retval HAL_StatusTypeDef HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)

 

 

Is not writing one 32-bit word at once, but eight 32-bit words at once (256-bits). So increment your data pointer accordingly.


@filipxsikora wrote:

Hello,

first of all, H757 is a dual core. And the second core (CM4) has it's ROM starting at exactly 0x08100000. If you left it at default and haven't moved it, you just deleted CM4's ROM from under it's hands which could lead to all sorts of issues and crashes.

 


Interesting, I was just going off this part of the datasheet:

gcoard_0-1736676395610.png

Either way, I've changed the address to 0x08E0000, bank 1 sector 7. 
Yes I had the word size a bit wrong, have made some corrections and it appears to be saving the data.

However, I dont think it's loading (or saving) correctly, probably an issue with my code.
New save function:

void save_data() {
    Persistent_data save_data;

    uint32_t data_header = DATA_HEADER;

    save_data.data_header = data_header;
    memcpy(save_data.parameter, parameter, sizeof(save_data.parameter));
    memcpy(save_data.screen_paras, screen_paras, sizeof(save_data.screen_paras));

    size_t size = sizeof(Persistent_data);
    uint32_t word_count = (size + 31) / 32; //32bit alignment
    Flash_Write(FLASH_START_ADDRESS, (uint32_t*)&save_data, word_count);
    }

HAL_StatusTypeDef Flash_Write(uint32_t address, uint32_t* data, uint32_t length) {
    HAL_StatusTypeDef status = HAL_OK;

    // Ensure address is within the flash range
    if (address < FLASH_USER_START_ADDR || (address + length) > FLASH_USER_END_ADDR) {
        return HAL_ERROR;
        }

    // Unlock the Flash
    HAL_FLASH_Unlock();

    // Erase the flash sector
    FLASH_EraseInitTypeDef eraseInitStruct = {
        .TypeErase = FLASH_TYPEERASE_SECTORS,
        .Banks = FLASH_BANK_1,
        .Sector = FLASH_SECTOR_7,
        .NbSectors = 1,
        .VoltageRange = FLASH_VOLTAGE_RANGE_3,
        };
    uint32_t sectorError = 0;

    status = HAL_FLASHEx_Erase(&eraseInitStruct, &sectorError);
    if (status != HAL_OK) {
        HAL_FLASH_Lock();
        return status;
        }


    //Write the data
     for (int i = 0; i < length / 32; i++) { // Writing 32-byte (256 bit) words
        status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, (uint32_t)&data[i * 8]);
        if (status != HAL_OK) {
            break;
            }
        address += 32; // Increment address by 32 bytes (256 bits)
        }


    // Lock the Flash
    HAL_FLASH_Lock();
    return status;
    }

 

And load function:

void load_data() {

    Persistent_data load_data;
    size_t size = sizeof(Persistent_data);
    uint32_t word_count = (size + 31) / 32; //align
    Flash_Read(FLASH_START_ADDRESS, (uint32_t*)&load_data, word_count);

    if (load_data.data_header == DATA_HEADER) {
        memcpy(parameter, load_data.parameter, sizeof(parameter));
        memcpy(screen_paras, load_data.screen_paras, sizeof(screen_paras));
        }
}

void Flash_Read(uint32_t address, uint32_t* data, uint32_t length) {
    if (address < FLASH_USER_START_ADDR || (address + length) > FLASH_USER_END_ADDR) {
        return; // Out of bounds
    }

    for (uint32_t i = 0; i < length / 32; i++) { // Reading 32-byte (256-bit) words
        // Read 32 bytes (256 bits) from flash starting at the given address
        for (uint32_t j = 0; j < 8; j++) {
            data[i * 8 + j] = *(__IO uint32_t*)(address + j * 4); // 4 bytes per uint32_t word
        }
        address += 32; // Increment address by 32 bytes (256 bits)
    }
}


Not a programmer or anything so I'm sure there's some kind of error I can't figure out.

Thanks for your help