Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ set(UART_DRIVER
set(I2C_DRIVER
${CMAKE_SOURCE_DIR}/drivers/i2c/stm_i2c.c
)
set(FLASH_DRIVER
${CMAKE_SOURCE_DIR}/drivers/flash/stm_flash.c
)

project(blinky C)
set(CPU_FLAGS "-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard")
Expand All @@ -75,7 +78,9 @@ set(SOURCES
${CMAKE_SOURCE_DIR}/cli/app/cli_app.c
${CMAKE_SOURCE_DIR}/cli/app/cli_helper.c
${CMAKE_SOURCE_DIR}/samples/i2c_sample.c
${CMAKE_SOURCE_DIR}/samples/flash_sample.c
${UART_DRIVER}
${FLASH_DRIVER}
${I2C_DRIVER}
${FREERTOS_SRC}
${FREERTOS_TESTS}
Expand All @@ -87,6 +92,7 @@ target_include_directories(RTOS.elf PRIVATE
${CMAKE_SOURCE_DIR}/includes
${CMAKE_SOURCE_DIR}/drivers/uart
${CMAKE_SOURCE_DIR}/drivers/i2c
${CMAKE_SOURCE_DIR}/drivers/flash
${CMAKE_SOURCE_DIR}/tests/freertos
${CMAKE_SOURCE_DIR}/cli/base/
${CMAKE_SOURCE_DIR}/cli/app/
Expand Down
139 changes: 139 additions & 0 deletions drivers/flash/stm_flash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "stm_reg_access.h"

#define FLASH_BASE 0x40022000

#define FLASH_SR_OFFSET 0x10
#define FLASH_CR_OFFSET 0x14
#define FLASH_KEYR_OFFSET 0x8

#define FLASH_SR FLASH_BASE + FLASH_SR_OFFSET
#define FLASH_CR FLASH_BASE + FLASH_CR_OFFSET
#define FLASH_KEYR FLASH_BASE + FLASH_KEYR_OFFSET

#define FLASH_KEY1 0x45670123U
#define FLASH_KEY2 0xCDEF89ABU

#define FLASH_SR_EOP (1U << 0)
#define FLASH_SR_PGSERR (1U << 7)
#define FLASH_SR_SIZERR (1U << 6)
#define FLASH_SR_PGAERR (1U << 5)
#define FLASH_SR_BSY (1U << 16)

#define FLASH_CR_PG (1U << 0)
#define FLASH_CR_PER (1U << 1)
#define FLASH_CR_PNB_Pos 3U
#define FLASH_CR_PNB_Msk (0xFFU << FLASH_CR_PNB_Pos)
#define FLASH_CR_STRT (1U << 16)
#define FLASH_CR_LOCK (1U << 31)


static void flash_wait_not_busy(void)
{
while(1)
{
uint32_t reg_val = REG_RD(FLASH_BASE + FLASH_SR_OFFSET);
if((reg_val & FLASH_SR_BSY) == 0)
break;
}
}

static void flash_clear_flags(void)
{
uint32_t reg_val = 0;
reg_val = REG_RD(FLASH_BASE + FLASH_SR_OFFSET);
reg_val |= FLASH_SR_EOP | FLASH_SR_PGSERR | FLASH_SR_SIZERR | FLASH_SR_PGAERR;
REG_WR(FLASH_BASE + FLASH_SR_OFFSET, reg_val);
}

static void flash_unlock(void)
{
uint32_t reg_val;
reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
if (reg_val & FLASH_CR_LOCK)
{
REG_WR(FLASH_BASE + FLASH_KEYR_OFFSET, FLASH_KEY1);
REG_WR(FLASH_BASE + FLASH_KEYR_OFFSET, FLASH_KEY2);
}
}

static void flash_lock(void)
{
uint32_t reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val |= FLASH_CR_LOCK;
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, FLASH_CR_LOCK);
}

void flash_erase_page(uint32_t page_number)
{
uint32_t reg_val = 0;
flash_wait_not_busy();
flash_clear_flags();
flash_unlock();

reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val &= ~FLASH_CR_PNB_Msk;
reg_val |= FLASH_CR_PER | ((page_number << FLASH_CR_PNB_Pos) & FLASH_CR_PNB_Msk);
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, reg_val);

reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val |= FLASH_CR_STRT;
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, reg_val);

flash_wait_not_busy();
flash_clear_flags();

reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val &= ~FLASH_CR_PER;
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, reg_val);
}

int flash_write_doubleword(uint32_t addr, uint64_t data)
{
uint32_t reg_val = 0;
if (addr % 8 != 0)
return -1;

flash_wait_not_busy();
flash_clear_flags();
flash_unlock();

reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val |= FLASH_CR_PG;
reg_val &= ~(1 << 1);
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, reg_val);

*(volatile uint32_t*)addr = (uint32_t)(data & 0xFFFFFFFFU);
*(volatile uint32_t*)(addr + 4) = (uint32_t)(data >> 32);

flash_wait_not_busy();

reg_val = REG_RD(FLASH_BASE + FLASH_SR_OFFSET);

if (reg_val & (FLASH_SR_PGSERR | FLASH_SR_SIZERR | FLASH_SR_PGAERR))
{
flash_clear_flags();
reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val &= ~FLASH_CR_PG;
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, reg_val);
flash_lock();
return -2;
}

flash_clear_flags();
reg_val = REG_RD(FLASH_BASE + FLASH_CR_OFFSET);
reg_val &= ~FLASH_CR_PG;
REG_WR(FLASH_BASE + FLASH_CR_OFFSET, reg_val);

flash_lock();

uint64_t read_back = *((volatile uint64_t*)addr);
if (read_back != data)
return -3;

return 0;
}


10 changes: 10 additions & 0 deletions drivers/flash/stm_flash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef FLASH_DRIVER_H
#define FLASH_DRIVER_H

#include <stdint.h>

void flash_erase_page(uint32_t page_number);
int flash_write_doubleword(uint32_t addr, uint64_t data);

#endif /* FLASH_DRIVER_H */

52 changes: 52 additions & 0 deletions samples/flash_sample.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "FreeRTOS.h"
#include "task.h"
#include "stm_flash.h"

void flash_task(void *pvParameters);

void flash_sample(void)
{
xTaskCreate(flash_task,
"I2C_RTC",
256,
NULL,
2,
NULL);

vTaskStartScheduler();

while(1)
;
}

#define DEBUG 0

void flash_task(void *pvParameters)
{
(void)pvParameters;
uint32_t page_number = 127;
uint32_t flash_addr = 0x0803F800;
uint64_t value = 0x123456;

#if DEBUG
uint64_t temp = *(volatile uint32_t*)flash_addr;
#endif
flash_erase_page(page_number);

int ret = flash_write_doubleword(flash_addr, value);
if (ret == 0)
{
while (1)
;
}
else
{
while (1)
;
}

}
10 changes: 7 additions & 3 deletions samples/stm_samples.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#define I2C_SAMPLE 1
#define BLINKY_SAMPLE 1
#define I2C_SAMPLE 0
#define BLINKY_SAMPLE 0
#define FLASH_SAMPLE 1

void i2c_sample();
void stm_stm_sample();
void stm_blinky_app();
void flash_sample();

void stm_samples()
{
#if I2C_SAMPLE
i2c_sample();
#elif BLINKY_SAMPLE
stm_blinky_app();
#elif FLASH_SAMPLE
flash_sample();
#endif
}