cancel
Showing results for 
Search instead for 
Did you mean: 

What causes HAL_FLASH_OB_Unlock() to call HardFaultHandler()? It calls WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); and jumps directly to HardFaultHandler().

KiptonM
Lead

The HAL_FLASH documentation is especially poor.

There in no overview of what you have to do.

You would think (because of lack of anything saying different) you have to

HAL_FLASH_OB_Unlock()

HAL_FLASH_Program(...)

HAL_FLASH_OB_Lock()

The first command HAL_FLASH_OB_Unlock() crashes.

HAL_FLASH_Program(...) says the format is

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)

Nowhere in the HAL Documentation's (UM1940) 1441 pages does it say what "TypeProgram" is, what it is used for, or what it should be.

It says TypeProgram indicates the way to program at a specific address. The value can be a value of FLASH Type Program. What is FLASH Type Program?

On page 234 it has

FLASH Type Program

FLASH_TYPEPROGRAM_BYTE

FLASH_TYPEPROGRAM_HALFWORD

FLASH_TYPEPROGRAM_WORD

FLASH_TYPEPROGRAM_DOUBLEWORD

I cannot program that with a byte or a halfword, or a word. it can only be a word.

Looking into the code for

HAL_FLASH_Program() in stm32g0xx_hal_flash.c it says

/**

 * @brief Program double word or fast program of a row at a specified address.

 * @param TypeProgram Indicate the way to program at a specified address.

 *           This parameter can be a value of @ref FLASH_Type_Program

 * @param Address Specifies the address to be programmed.

 * @param Data Specifies the data to be programmed

 *        This parameter is the data for the double word program and the address where

 *        are stored the data for the row fast program depending on the TypeProgram:

 *        TypeProgram = FLASH_TYPEPROGRAM_DOUBLEWORD (64-bit)

 *        TypeProgram = FLASH_TYPEPROGRAM_FAST (32-bit).

 *

 * @retval HAL_StatusTypeDef HAL Status

 */

So one of the options is FLASH_TYPEPROGRAM_FAST. But that is not on the list on page 234! Why?

The macro

#define IS_FLASH_TYPEPROGRAM(__VALUE__)        (((__VALUE__) == FLASH_TYPEPROGRAM_DOUBLEWORD) || \

                            ((__VALUE__) == FLASH_TYPEPROGRAM_FAST))

It does not say any of the other values are valid from Page 234.

I still do not know why HAL_FLASH_OB_Unlock() crashes. It is the first step.

Kip

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

You are kind of reading the reference manual, but many things seem to be invisible...

3.4.1 FLASH option byte description:

"The option bytes can be read from the Flash memory locations listed in Table 16 or from the Option byte registers"

And look at option byte detailed description after the table 16 - all of the bits are marked as read-only (r).

3.4.2 FLASH option byte programming, Modifying user options:

"2. Write the desired values in the FLASH option registers."

3.7.8 FLASH option register (FLASH_OPTR):

All of the bits are marked as read/write (rw).

And here is my code on STM32L4, which does what you are trying to implement:

#define BSP_FLASH_OPTR    ( (0xFFEFF8AA & ~(FLASH_OPTR_nSWBOOT0 | FLASH_OPTR_IWDG_STDBY | FLASH_OPTR_IWDG_SW)) )
 
void BSP_SyncOptionBytes(void)
{
	if (FLASH->OPTR == BSP_FLASH_OPTR) {
		return;
	}
 
	if (FLASH->CR & FLASH_CR_LOCK) {
		FLASH->KEYR = DEV_FLASH_KEY1;
		FLASH->KEYR = DEV_FLASH_KEY2;
	}
	if (FLASH->CR & FLASH_CR_OPTLOCK) {
		FLASH->OPTKEYR = DEV_FLASH_OPTKEY1;
		FLASH->OPTKEYR = DEV_FLASH_OPTKEY2;
	}
 
	FLASH->OPTR = BSP_FLASH_OPTR;
	FLASH->CR = FLASH_CR_OPTSTRT;
	while (FLASH->SR & FLASH_SR_BSY);
 
	FLASH->CR = FLASH_CR_OBL_LAUNCH;
}

View solution in original post

38 REPLIES 38
KiptonM
Lead

Found it. Nowhere in the HAL documentation does it say you have to first HAL_FLASH_Unlock() then HAL_FLASH_OB_Unlock();

But that is what you have to do.

At least it is not crashing.

Kip

KiptonM
Lead

I read the address 0x1FFF7800 into a uint32_t, Change the bits I need to the correct value.

Put it into a uint64_t as the lower 4 bytes, then did a bit inversion into the upper 4 bytes. And tried to write. It returned a 1. 0 is O.K.

No clue from the Documentation.

KiptonM
Lead

It gets into FLASH_WaitForLastOperation(uint32_t Timeout)|

And it appears the Flash Status register has the WRPERR bit set. It says it is set by hardware when an address to be erased/programmed belongs to a write protected part (by WRP, PCROP, or RDP Level 1) of the Flash Memory.

I thought the purpose of the HAL_FLASH_OB_Unlock() was to unlock the OB memory.

Again nothing in the HAL documentation about this.

KiptonM
Lead

WRPERR is for user area. Not the OB area. Why am I getting a WRPERR error?

KiptonM
Lead

I think I traced down the latest error.

In the routine below when I write the first uint32_t (in line 13) CFGBSY is set to 1 it never checks to see if it is cleared. So it tries to write the second one (in line 20) while it is busy, which generates an error.

/**
  * @brief  Program double-word (64-bit) at a specified address.
  * @param  Address Specifies the address to be programmed.
  * @param  Data Specifies the data to be programmed.
  * @retval None
  */
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
{
  /* Set PG bit */
  SET_BIT(FLASH->CR, FLASH_CR_PG);
 
  /* Program first word */
  *(uint32_t *)Address = (uint32_t)Data;
 
  /* Barrier to ensure programming is performed in 2 steps, in right order
    (independently of compiler optimization behavior) */
  __ISB();
 
  /* Program second word */
  *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);
}
 
KiptonM
Lead

So I decided to call Program Memory with FLASH_TYPEPROGRAM_FAST since it uses a different routine.

But when it gets to the other code FLASH_Program_Fast(Address, (uint32_t)Data); I cannot enter it. It goes directly to HardFault_Handler(void); I looked at the variables and the (uint32_t)Data said it was "Optimized out".

KiptonM
Lead

It looks like after I write the first uint32_t in Flash_Program_DoubleWord() The FLASH->SR CFGBSY (bit 18) never resets. I would have thought it would reset when it was finished programming. The documentation does not address it. It just says it is "reset when program operation completes or is interrupted by an error."

Otavio Borges
Associate III

Data variable as "Optimized Out" usually is beacuse of compilation optimization. The variable is there but the symbol for the debugger is removed by the compiler. Tweak the compilation flags to use -O0 and -g3 (on project properties).

Is the FLASH peripheral clock enabled? Look for HAL_RCC_FLASH_CLK_ENABLE.

Also, you might need to adjust flash latency depending on your system clock

There is no string "HAL_RCC_FLASH_CLK_ENABLE" and no "HAL_RCC_FLA" and no "FLASH_CLK" I cannot find anything in there with that string or with the part of the string in the UM1940 or in RM0444.

I cannot find anything about a FLASH clock in RCC or in Flash sections.

The Optimized out variable meant I could not easily see it. I am pretty sure it is correct. I can put it into a print statement and see it on the serial port terminal.

My system clock for the STM32G031 is 64MHz. I do not see anywhere to set the latency in the MX program.