cancel
Showing results for 
Search instead for 
Did you mean: 

Talk to Flash in STM32L412KB without using HAL library

Anonymous
Associate II

Hello everyone!

I am trying to write to flash without using built-in HAL functions. Initially, I want "Hello World!". The Flash is only aligned double word writable as shown in the reference manual (RM0394) standard Programming technique Section 3.3.7.

Link to reference manual:

https://www.st.com/en/microcontrollers-microprocessors/stm32l412kb.html#

Before you go through the code, I also think there's no need to erase the flash since it's FFFF.. all the way so I am assuming, I don't need to clean it at least right now. I have also tried altering the Start_Address to go to different pages but, I haven't had any luck yet. The reason to choose page 48 is because I will need 32 Kb. I am considering 32Kb starting from the top. This is just an assumption.

My code:

uint64_t* Start_Address = (uint64_t*)(0x08018000); /* Page 48 address */

 volatile uint32_t* pClkCtrlreg = (uint32_t*)(0x40021048);    /* RCC_AHB1ENR Clock Enable Register */

 volatile uint32_t* pFlashKeyReg = (uint32_t*)(0x40022008); /* FLASH_KEYR Register */

 volatile uint32_t* pFlashStatusReg = (uint32_t*)(0x40022010);  /* FLASH_SR Status Register enable */

 volatile uint32_t* pFlashCtrlReg = (uint32_t*)(0x40022014);   /* FLASH_CR Control Register enable */

 uint64_t TEST = 2434; /* Just an example*/

*pClkCtrlreg |= (1<<8);                 /* Flash Clock enabled*/

 if(!((*pFlashStatusReg) & (1<<16))){ /* Unlocking the Flash */

 *pFlashKeyReg = 0x45670123; /* Entering Key 1*/

 *pFlashKeyReg = 0xCDEF89AB; /* Entering Key 2*/

 }

  /* Page Erase (Page 48 only) */

 if(!((*pFlashStatusReg) & (1<<16))){ /* BSY Flag Status check */

 if(((*pFlashStatusReg) & (1<<7))) /* Check if PGSERR is set*/

 {

*pFlashStatusReg &= 0x11113C05;           /* Clearing previous programming errors while PGSERR is set */

 }

 else

 {

*pFlashStatusReg &= 0xFFFF3FED;           /* Clearing previous programming errors while PGSERR is not set */

 }

 *pFlashCtrlReg |= (1<<1);               /* Set the PER Bit */

 *pFlashCtrlReg |= (3<<7);               /* Page 48: Set Bits 7th and 8th */

 *pFlashCtrlReg &= (~(1<<3));               /* Page 48: Clear Bit 3 */

 *pFlashCtrlReg &= (~(1<<4));               /* Page 48: Clear Bit 4 */

 *pFlashCtrlReg &= (~(1<<5));               /* Page 48: Clear Bit 5 */

 *pFlashCtrlReg &= (~(1<<6));               /* Page 48: Clear Bit 6 */

 *pFlashStatusReg |= (1<<16);  /* Set STRT Bit */

 while((*pFlashStatusReg) & (1<<16));  /* Wait until BSY Flag is cleared*/

 }

 /* Standard Programming Technique */

 if(!((*pFlashStatusReg) & (1<<16))){ /* BSY Flag Status check */

 if(((*pFlashStatusReg) & (1<<7))) /* Check if PGSERR is set*/

 {

*pFlashStatusReg &= 0x11113C05;           /* Clearing previous programming errors while PGSERR is set */

 }

 else

 {

*pFlashStatusReg &= 0xFFFF3FED;           /* Clearing previous programming errors while PGSERR is not set */

 }

 *pFlashCtrlReg |= (1<<0);               /* Set the PG Bit */

// Flash is unlocked and ready to be written at this stage. How should I write to flash now? I have tried memset/memcpy. Can y'all suggest what to do next?

4 REPLIES 4
TDK
Guru

No need to reinvent the wheel. Use the CMSIS headers so yourself and others can read your code.

Here's what HAL does. Easy enough to read the functions and lift the relevant code.

/**
  * @brief  Program a double word (64-bit) at a specified address.
  * @note   This function must be used when the device voltage range is from
  *         2.7V to 3.6V and Vpp in the range 7V to 9V.
  *
  * @note   If an erase and a program operations are requested simultaneously,    
  *         the erase operation is performed before the program one.
  *  
  * @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)
{
  /* Check the parameters */
  assert_param(IS_FLASH_ADDRESS(Address));
  
  /* If the previous operation is completed, proceed to program the new data */
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
  FLASH->CR |= FLASH_PSIZE_DOUBLE_WORD;
  FLASH->CR |= FLASH_CR_PG;
 
  /* Program first word */
  *(__IO 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 */
  *(__IO uint32_t*)(Address+4) = (uint32_t)(Data >> 32);
}

If you feel a post has answered your question, please click "Accept as Solution".
Anonymous
Associate II

I agree with this but, my manager doesn't want me to use this library for the allotted task

I agree with this but, my manager doesn't want me to use this library for the allotted task

Anonymous
Associate II

So I was able to write to Flash using this but, how do I clear it?