cancel
Showing results for 
Search instead for 
Did you mean: 

Write, Read code for STM32L412 elusive

CGadg
Associate III

What code works for the STM32L412 device?

I want to load an RTC calibration value into flash memory and retrieve it on subsequent running of the firmware.

 

I've got the reading of specific calibration values working in a different IC, for ADC calibration, 

ICTempCal1 = (*((volatile uint16_t*)(0x1FF8007A))); 

Will this work with the L412 IC?

 

But I cannot get programming of a page to work. 

I tried 'HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x080E0000,1000);'

But that fails within the routine. I'm assuming the Erase routine worked, but I haven't got far enough to check.

 

I tried the 'STM32CubeL4/Projects/NUCLEO-L4P5ZG/Examples/FLASH
/FLASH_FastProgram' code and found it to fail in the last section, the GetBank routine.

Different IC also.

 

Can anyone give me the code for these operations?

 

1 ACCEPTED SOLUTION

Accepted Solutions

I can get the code to build in 'STM32CubeL4/Projects/NUCLEO-L412KB/Examples/FLASH/FLASH_EraseProgram'

I'll update after working through that

View solution in original post

12 REPLIES 12
nouirakh
ST Employee

Hello @CGadg 

By making a few changes to the project:
'Projects\NUCLEO-L4P5ZG\Examples\FLASH\FLASH_WriteProtection'
I modified the address of FLASH_USER_START_ADDR start and  FLASH_USER_END_ADDR ADDR to fit with address you mentioned 0x080E0000, and I modified the bank which is located in the memory zone you have selected:

    /* The desired pages are not write protected */
    /* Fill EraseInit structure************************************************/
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Banks       = FLASH_BANK_2;
    EraseInitStruct.Page        = StartPage;
    EraseInitStruct.NbPages     = EndPage - StartPage + 1;
#define FLASH_USER_START_ADDR       ADDR_FLASH_PAGE_224   /* Start @ of user Flash area */
#define FLASH_USER_END_ADDR         ADDR_FLASH_PAGE_228   /* End @ of user Flash area */

For the example you mentioned
'STM32CubeL4/Projects/NUCLEO-L4P5ZG/Examples/FLASH/FLASH_FastProgram' 
I make the changes that you are asking to make in the code and the example works and the routine is done:

#define FLASH_USER_START_ADDR   ADDR_FLASH_PAGE_224   /* Start @ of user Flash area */
#define FLASH_USER_END_ADDR     ADDR_FLASH_PAGE_228  /* End @ of user Flash area */
#define DATA_32                     ((uint32_t)0x12345678)
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
  while (Address < (FLASH_USER_END_ADDR - (FLASH_ROW_SIZE*sizeof(uint64_t))))
  {
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, 1000) == HAL_OK)
    {
      Address = Address +0x8U ; //+ (FLASH_ROW_SIZE*sizeof(uint64_t));
    }
   else
    {
      /* Error occurred while writing data in Flash memory.
         User can add here some code to deal with this error */
      while (1)
      {
        BSP_LED_On(LED3);
      }
    }
  }

  if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, (uint64_t)src_addr) != HAL_OK)
  {
    /* Error occurred while writing data in Flash memory.
       User can add here some code to deal with this error */
    while (1)
    {
      BSP_LED_On(LED3);
    }
  }

  /* Lock the Flash to disable the flash control register access (recommended
     to protect the FLASH memory against possible unwanted operation) *********/
  HAL_FLASH_Lock();

  /* 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;

  while (Address < FLASH_USER_END_ADDR)
  {
    for (data_index = 0; data_index < FLASH_ROW_SIZE; data_index++)
    {
      data64 = *(__IO uint64_t *)Address;

      if(data64 != Data64_To_Prog[data_index])
      {
        MemoryProgramStatus++;
      }
      Address = Address + sizeof(uint64_t);
    }
  }
    /* Check the correctness of written data */
    Address = FLASH_USER_START_ADDR;

    while (Address < FLASH_USER_END_ADDR)
    {
      if((*(__IO uint32_t*) Address) != DATA_32)
      {
        MemoryProgramStatus = FAILED;
      }
      Address += 4;
    }

 

Thanks nouirakh,

I'll work through this and see if I can get it working

I immediately get errors for 'ADDR_FLASH_PAGE_224', so I think your code works on a different IC.

Other errors because the variables need defining, and stm32 Cube IDE doesn't like 'if(data64 != Data64_To_Prog[data_index])' at all

nouirakh
ST Employee

I worked on these following examples:
'Projects/NUCLEO-L4P5ZG/Examples/FLASH/FLASH_FastProgram'
'Projects\NUCLEO-L4P5ZG\Examples\FLASH\FLASH_WriteProtection'
For the 'ADDR_FLASH_PAGE_224' it is defined in the main.h 

You can find in the attached files the main.c/.h 

I double check this code it works for me using Cube IDE and EWARM , Maybe you can inspire from this example and make the necessary adaptation with your IC.
Could you verify it from your end and utilize the IC you mentioned?

Yes thanks,

I've just got one error left, the line

CGadg_0-1713954353622.png

 

is not understood by Cube IDE.... "subscripted value is neither array nor pointer nor vector"

Total of 3 errors within that misunderstanding

nouirakh
ST Employee

It would be greatly appreciated if you could verify these definitions in your code in order to resolve this error?
In the example "Projects/NUCLEO-L4P5ZG/Examples/FLASH/FLASH_FastProgram", We have:

/* Private define ------------------------------------------------------------*/
#define FLASH_ROW_SIZE          64
/* Private variables ---------------------------------------------------------*/
__IO uint64_t data64 = 0;
/* Table used for fast programming */
static const uint64_t Data64_To_Prog[FLASH_ROW_SIZE] = {
  0x0000000000000000, 0x1111111111111111, 0x2222222222222222, 0x3333333333333333,
  0x4444444444444444, 0x5555555555555555, 0x6666666666666666, 0x7777777777777777,
  0x8888888888888888, 0x9999999999999999, 0xAAAAAAAAAAAAAAAA, 0xBBBBBBBBBBBBBBBB,
  0xCCCCCCCCCCCCCCCC, 0xDDDDDDDDDDDDDDDD, 0xEEEEEEEEEEEEEEEE, 0xFFFFFFFFFFFFFFFF,
  0x0011001100110011, 0x2233223322332233, 0x4455445544554455, 0x6677667766776677,
  0x8899889988998899, 0xAABBAABBAABBAABB, 0xCCDDCCDDCCDDCCDD, 0xEEFFEEFFEEFFEEFF,
  0x2200220022002200, 0x3311331133113311, 0x6644664466446644, 0x7755775577557755,
  0xAA88AA88AA88AA88, 0xBB99BB99BB99BB99, 0xEECCEECCEECCEECC, 0xFFDDFFDDFFDDFFDD};
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  uint32_t src_addr = (uint32_t)Data64_To_Prog;
  uint8_t data_index = 0;

 

CGadg
Associate III

Thanks Kholdoun,

I'll probably need to go through it again on Monday though,

Cheers.

I've imported it into a fresh project and there is a mismatch in definitions for 'SYSCFG_MEMRMP_FB_MODE', the compiler asks if I mean '...MEM MODE'. I guess so but I don't want to guess.

It also needs FLASH_BANK_2 defining, though I can't see where that is.

 

I can get the code to build in 'STM32CubeL4/Projects/NUCLEO-L412KB/Examples/FLASH/FLASH_EraseProgram'

I'll update after working through that