cancel
Showing results for 
Search instead for 
Did you mean: 

flash example code with Low Layer Drivers ?

Ben1
Associate III

Hello,

I can't find any example code of flash write or read using LL_drivers, only HAL drivers. I work with Blue NRG and I do have rf_drivers_ll_flash.c with functions that looks like those in rf_drivers_hal_flash.c. But I can't make flash working with LL functions... The only meaningful difference is HAL_Init(), which I can't find any LL drivers equivalent. The other differences are locking the access of the flash during write. Is there something obvious I am missing? (clock init? )

Is there some example code using LL drivers for flash? Even MCU different from Blue NRG will be fine, I'll adapt it.

Thank you !

1 ACCEPTED SOLUTION

Accepted Solutions
Ben1
Associate III

Found it. It was simple actually. We must not declare Flashx instance. We have to use already defined instance FLASH. (why it is needed as a parameter in LL while it is not in HAL?)

LL_FLASH_Program(FLASH, Address, DATA_32);

View solution in original post

4 REPLIES 4

I've written most of my flash update code in assembler, using the RM and HAL/SPL code as a reference.

Typically no, you don't have to enable any special clocks. You have to unlock the peripheral, and pay attention to status/error flags, and that the operations are performed with alignment meeting the flash array's geometry, and that the flash-words are erased, especially where the words are long, and also have ECC bits attached.

Some STM32 expect you to have the code in RAM (check #pragma and attributes on functions, and .MAP from working examples), most will simply stall the MCU with wait-states if you try to read access flash while it is busy with a write/erase operation.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Ben1
Associate III

Thank you for your answer. More precisely, here is a code with HAL, which runs fine :

/* Includes ------------------------------------------------------------------*/
#include "FLASH_EraseProgram_main.h"
 
 
/* Private define ------------------------------------------------------------*/
#define FLASH_USER_START_ADDR   (FLASH_END_ADDR - FLASH_PAGE_SIZE - 0xF)   /* Start @ of user Flash area */
#define FLASH_USER_END_ADDR     (FLASH_END_ADDR - 0xF)  /* End @ of user Flash area */
#define DATA_32                 ((uint32_t)0xDEADBEEF)
 
 
/* Private variables ---------------------------------------------------------*/
uint32_t FirstPage = 0, NbOfPages = 0;
uint32_t Address = 0, PageError = 0;
__IO uint32_t data32 = 0 , MemoryProgramStatus = 0;
 
/**
* @brief  The application entry point.
* @retval int
*/
int main(void)
{
  /* System initialization function */
  if (SystemInit(SYSCLK_32M, RADIO_SYSCLK_NONE) != SUCCESS)
  {
    /* Error during system clock configuration take appropriate action */
    while(1);
  }
  
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  
  /* IO pull configuration with minimum power consumption */
  BSP_IO_Init();
  
  /* Initialization of COM port */
  BSP_COM_Init(NULL);
  
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  
  /* Initialize LED1, LED2 and LED3 */
  BSP_LED_Init(BSP_LED1);
  BSP_LED_Init(BSP_LED2);
  BSP_LED_Init(BSP_LED3);
 
  /* Program the user Flash area word by word
  (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
  printf("Program the user Flash area word by word.\n\r");
  Address = FLASH_USER_START_ADDR;
  
  while (Address < FLASH_USER_END_ADDR)
  {
    if (HAL_FLASH_Program(Address, DATA_32) == HAL_OK)
    {
//	  LL_FLASH_Program(&Flash_instance, Address, DATA_32);
      Address = Address + 4;
    }
    else
    {
      /* Error occurred while writing data in Flash memory.
      User can add here some code to deal with this error */
      printf("Error occurred while writing data in Flash memory.\n\r");
      while (1)
      {
        BSP_LED_On(BSP_LED3);
      }
    }
  }
  
  /* 
  Check if the programmed data is OK
  MemoryProgramStatus = 0: data programmed correctly
  MemoryProgramStatus != 0: number of words not programmed correctly 
  */
  Address = FLASH_USER_START_ADDR;
  MemoryProgramStatus = 0x0;
  printf("Check the programmed data:\n\r");
  while (Address < FLASH_USER_END_ADDR)
  {
    data32 = *(__IO uint32_t *)Address;
    
    if (data32 != DATA_32)
    {
      MemoryProgramStatus++;
    }
    Address = Address + 4;
  }
  
  /*Check if there is an issue to program data*/
  if (MemoryProgramStatus == 0)
  {
    /* No error detected. Switch on LED2*/
    printf("No error detected.\n\r");
    BSP_LED_On(BSP_LED2);
  }
  else
  {
    /* Error detected. Switch on LED1*/
    printf("Error detected.\n\r");
    BSP_LED_On(BSP_LED1);
  }
  /* Infinite loop */
  while (1)
  {
  }
}

and here is my code not running : (it compiles but doesn't write in flash) :

/* Private macro -------------------------------------------------------------*/
 
#define LL_FLASH_USER_START_ADDR  (LL_FLASH_END_ADDR - LL_FLASH_PAGE_SIZE - 0xF)    /* Start @ of user Flash area */
 
#define LL_FLASH_USER_END_ADDR   (LL_FLASH_END_ADDR - 0xF)             /* End @ of user Flash area */
 
#define DATA_32         ((uint32_t)0x12345678)
 
#ifdef DEBUG
 
#include <stdio.h>
 
#define PRINTF(...) printf(__VA_ARGS__)
 
#else
 
#define PRINTF(...)
 
#endif
 
/* Private variables ---------------------------------------------------------*/
 
 
 
uint32_t Address = 0;
 
__IO uint32_t data32 = 0;
 
FLASH_TypeDef Flash_instance;
 
 
 
/* Private function prototypes -----------------------------------------------*/
 
/* Private functions ---------------------------------------------------------*/
 
 
 
void ModulesTick(void)
 
{
 
 /* Timer tick */
 
 HAL_VTIMER_Tick();
 
  
 
 /* Bluetooth stack tick */
 
 BLE_STACK_Tick();
 
  
 
 /* NVM manager tick */
 
 NVMDB_Tick();
 
}
 
int main(void) 
{
  WakeupSourceConfig_TypeDef wakeupIO;
  PowerSaveLevels stopLevel;
 
  /* System initialization function */
  if (SystemInit(SYSCLK_64M, BLE_SYSCLK_16M) != SUCCESS)
  {
    /* Error during system clock configuration take appropriate action */
    while(1);
  }
//  /* Configure IOs for power save modes */
//  BSP_IO_Init();
 
  LL_Init1msTick(SystemCoreClock);
 
   
  /* No Wakeup Source needed */
  wakeupIO.IO_Mask_High_polarity = 0;
  wakeupIO.IO_Mask_Low_polarity = 0;
  wakeupIO.RTC_enable = 0;          
  wakeupIO.LPU_enable = 0;
 
  Address = LL_FLASH_USER_START_ADDR;
 
   while (Address < LL_FLASH_USER_END_ADDR)
  {
	  LL_FLASH_Program(&Flash_instance, Address, DATA_32);
      Address = Address + 4;
  }
 
  Address = LL_FLASH_USER_START_ADDR;
 
  printf("Check the programmed data:\n\r");
  while (Address < LL_FLASH_USER_END_ADDR)
  {
    data32 = *(__IO uint32_t *)Address;
    printf("%x  %x \r\n",Address, data32);
    if (data32 != DATA_32)
    {
    	printf("eRRoR !\n\r");
    }
    Address = Address + 4;
  }
  /* Infinite loop */
  while (1)
  {
  }
}

here is the codes of HAL_FLASH_Program() and LL_FLASH_Program() :

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t Address, uint32_t Data)
{
  HAL_StatusTypeDef status;
 
  /* Check the parameters */
  assert_param(IS_ADDR_ALIGNED_32BITS(Address));
  assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
 
  /* Process Locked */
  __HAL_LOCK(&pFlash);
 
  /* Reset error code */
  pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
 
  /* Program a word (32-bit) at a specified address */
  FLASH_Program_Word(Address, Data);
  
  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
 
  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);
 
  /* return status */
  return status;
}
 
// Flash_Program_Word() :
static void FLASH_Program_Word(uint32_t Address, uint32_t Data)
{
  /* Clear All Flags */
  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE|FLASH_FLAG_CMDSTART|FLASH_FLAG_CMDERR|FLASH_FLAG_ILLCMD);
 
  /* Load the word address */
  FLASH->ADDRESS = ((Address>>2) & 0xFFFF);
  
  /* Load the data to program */
  FLASH->DATA0 = Data;
  
  /* Load the WRITE command */
  FLASH->COMMAND = FLASH_CMD_WRITE;
}
 
void LL_FLASH_Program(FLASH_TypeDef *FLASHx, uint32_t Address, uint32_t Data)
{
  /* Check the parameters */
  assert_param(IS_LL_ADDR_ALIGNED_32BITS(Address));
  assert_param(IS_LL_FLASH_PROGRAM_ADDRESS(Address));
 
  /* Clear All Flags */
  LL_FLASH_ClearFlag(FLASHx, LL_FLASH_FLAG_CMDDONE|LL_FLASH_FLAG_CMDSTART|LL_FLASH_FLAG_CMDERR|LL_FLASH_FLAG_ILLCMD);
 
  /* Load the word address */
  FLASHx->ADDRESS = ((Address>>2) & 0xFFFF);
  
  /* Load the data to program */
  FLASHx->DATA0 = Data;
  
  /* Load the WRITE command */
  FLASHx->COMMAND = LL_FLASH_CMD_WRITE;
  
  /* Wait for last operation to be completed */
  while(LL_FLASH_GetFlag(FLASHx, LL_FLASH_FLAG_CMDDONE) != SET);
}

Regarding the functions, nothing changes except some securities like  __HAL_LOCK(&pFlash) and timeouts. In the main program, the differences are clock initialization and HAL_Init() which I can't find LL_Init() or equivalent.

the comment above HAL_Init() says : "Initializes the Flash interface". Can someone tell me where? When I develop the function, I can't see anything related to flash. But it does perform HAL_InitTick(). Can clock initialization can make the difference between flash writable and not writable?

Thank you for your answer

Ben1
Associate III

Found it. It was simple actually. We must not declare Flashx instance. We have to use already defined instance FLASH. (why it is needed as a parameter in LL while it is not in HAL?)

LL_FLASH_Program(FLASH, Address, DATA_32);

One could argue that the first parameter in LL API is (an unnecessary) placeholder for a future multiple FLASH peripheral instances, but in reality it's just an usual lack of logic thinking...