-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
23 changed files
with
1,050 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
/* | ||
* HW_FLASH.c | ||
* This file describes low-level, mostly hardware-specific Flash behaviour | ||
* https://www.st.com/resource/en/programming_manual/pm0075-stm32f10xxx-flash-memory-microcontrollers-stmicroelectronics.pdf | ||
*/ | ||
|
||
/****************************************************************************** | ||
* I N C L U D E S | ||
******************************************************************************/ | ||
|
||
// module include | ||
#include "HW_flash.h" | ||
#include "LIB_utility.h" | ||
|
||
#include "string.h" | ||
#include "stdbool.h" | ||
|
||
#define FLASH_BASE (0x40022000UL) // base address of flash registers | ||
|
||
#define FLASH_ACR (FLASH_BASE + 0x00UL) // flash access control register | ||
#define FLASH_KEYR (FLASH_BASE + 0x04UL) // flash key register for unlocking flash | ||
#define FLASH_OPTKEYR (FLASH_BASE + 0x08UL) // flash key register for unlocking option bytes | ||
#define FLASH_SR (FLASH_BASE + 0x0CUL) // flash status register | ||
#define FLASH_CR (FLASH_BASE + 0x10UL) // flash control register | ||
#define FLASH_AR (FLASH_BASE + 0x14UL) // flash access register | ||
#define FLASH_OBR (FLASH_BASE + 0x1CUL) // flash option byte register | ||
#define FLASH_WRPR (FLASH_BASE + 0x20UL) // flash write protection register | ||
|
||
#define FLASH_KEY1 (0x45670123UL) // first key to be written to unlock flash | ||
#define FLASH_KEY2 (0xCDEF89ABUL) // second key to be written to unlock flash | ||
#define FLASH_RDPRT (0x000000A5UL) // flash read protection key | ||
#define FLASH_SR_BSY (0x00000001UL) // flash busy bit | ||
#define FLASH_CR_PG (0x00000001UL) // flash program enable bit | ||
#define FLASH_CR_PER (0x00000002UL) // flash page erase enable bit | ||
#define FLASH_CR_START (0x00000040UL) // flash page erase start bit | ||
#define FLASH_CR_LOCK (0x00000080UL) // flash page erase start bit | ||
|
||
#define FLASH_PAGE_LAST (0x08007C00UL) // address of the last flash page | ||
#define FLASH_SIZE_REG (0x1FFFF7E0UL) // register whose 4 least significant bits | ||
// contains the size of the flash for this chip | ||
|
||
#define FLASH_BUSY() ((bool)(GET_REG(FLASH_SR) &FLASH_SR_BSY)) // returns true if flash is busy | ||
|
||
/****************************************************************************** | ||
* P R I V A T E V A R S | ||
******************************************************************************/ | ||
typedef struct | ||
{ | ||
const uint16_t pageSize; | ||
} flash_S; | ||
|
||
flash_S flash; | ||
|
||
/****************************************************************************** | ||
* P U B L I C F U N C T I O N S | ||
******************************************************************************/ | ||
|
||
void FLASH_init(void) | ||
{ | ||
const uint16_t pageSize = FLASH_getPageSize(); | ||
flash_S fl = { | ||
.pageSize = pageSize, | ||
}; | ||
|
||
memcpy(&flash, &fl, sizeof(flash_S)); | ||
} | ||
|
||
/* | ||
* FLASH_lock | ||
* @brief Lock the Flash Programming and Erase Controller (FPEC) once | ||
* we're done interacting with the flash | ||
*/ | ||
void FLASH_lock(void) | ||
{ | ||
// should we take down the HSI as well? | ||
SET_REG(FLASH_CR, FLASH_CR_LOCK); | ||
} | ||
|
||
|
||
/* | ||
* FLASH_unlock | ||
* @brief Unlock the Flash Programming and Erase Controller (FPEC) so we can perform | ||
* operations on the flash | ||
*/ | ||
void FLASH_unlock(void) | ||
{ | ||
if (READ_BIT(FLASH_CR, FLASH_CR_LOCK)) return; | ||
SET_REG(FLASH_KEYR, FLASH_KEY1); | ||
SET_REG(FLASH_KEYR, FLASH_KEY2); | ||
while (READ_BIT(FLASH_CR, FLASH_CR_LOCK)); | ||
} | ||
|
||
/* | ||
* FLASH_erasePages | ||
* @brief Erase the given number of pages of flash, starting from the given page address | ||
* @param startPageAddr uint32_t the address of the first page to erase | ||
* @param pages uint16_t the number of pages to erase | ||
*/ | ||
bool FLASH_erasePages(uint32_t startPageAddr, uint16_t pages) | ||
{ | ||
FLASH_unlock(); | ||
bool ret = true; | ||
|
||
// set the page erase bit | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_PER); | ||
|
||
for (uint16_t page = 0U; page < pages; page++) | ||
{ | ||
uint32_t currPageAddr = startPageAddr + (page * flash.pageSize); | ||
uint32_t currPageEnd = currPageAddr + flash.pageSize; | ||
while (FLASH_BUSY()) | ||
{} | ||
|
||
// set the page address to erase | ||
SET_REG(FLASH_AR, currPageAddr); | ||
// start the erase process | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_START); | ||
|
||
while (FLASH_BUSY()) | ||
{} | ||
|
||
// verify page has been erased | ||
// verify 64 bits at a time | ||
for (uint32_t flashWordAddr = currPageAddr; flashWordAddr < currPageEnd; flashWordAddr += 8) | ||
{ | ||
if ((*(volatile uint64_t *)flashWordAddr) != 0xFFFFFFFFFFFFFFFFULL) | ||
{ | ||
ret = false; | ||
} | ||
} | ||
} | ||
|
||
// clear the page erase bit | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) & ~FLASH_CR_PER); | ||
|
||
while (FLASH_BUSY()) | ||
{} | ||
|
||
FLASH_lock(); | ||
return ret; | ||
} | ||
|
||
/* | ||
* FLASH_writeWords | ||
* @brief write the given words of data starting at the given address in flash | ||
* @param addr uint32_t the address of the first word to write | ||
* @param data uint32_t* the words to write | ||
* @param dataLen uint16_t the number of words to write | ||
*/ | ||
bool FLASH_writeWords(uint32_t addr, uint32_t *data, uint16_t dataLen) | ||
{ | ||
volatile uint16_t *addr_16; | ||
volatile uint16_t *data_16; | ||
bool ret = true; | ||
|
||
FLASH_unlock(); | ||
// Set the PG bit in FLASH_CR which enables writing | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_PG); | ||
|
||
// write all the data | ||
for (uint16_t dataOffset = 0U; dataOffset < dataLen; dataOffset++) | ||
{ | ||
// get pointer to the word in flash, access as two half words. | ||
// word is 4 bytes, thus (offset * 4) | ||
addr_16 = (volatile uint16_t*)(addr + (dataOffset * 4U)); | ||
|
||
// uint32_t cast to uint16_t array | ||
// so increment by 2 when we want to get to the next word | ||
data_16 = &(((volatile uint16_t*)data)[dataOffset * 2U]); | ||
|
||
while (FLASH_BUSY()) | ||
{} | ||
addr_16[0] = data_16[0]; | ||
|
||
while (FLASH_BUSY()) | ||
{} | ||
addr_16[1] = data_16[1]; | ||
|
||
while (FLASH_BUSY()) | ||
{} | ||
|
||
// verify the data in flash, | ||
// compare as words | ||
if (*(volatile uint32_t *)(addr + (dataOffset * 4U)) != data[dataOffset]) | ||
{ | ||
ret = false; | ||
break; | ||
} | ||
} | ||
|
||
// Clear the PG bit in FLASH_CR | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) & ~FLASH_CR_PG); | ||
FLASH_lock(); | ||
|
||
return ret; | ||
} | ||
|
||
/* | ||
* FLASH_writeHalfwords | ||
* @brief write the given halfwords of data starting at the given address in flash | ||
* @param addr uint32_t the address of the first halfword to write | ||
* @param data uint16_t* the halfwords to write | ||
* @param dataLen uint16_t the number of halfwords to write | ||
*/ | ||
bool FLASH_writeHalfwords(uint32_t addr, uint16_t *data, uint16_t dataLen) | ||
{ | ||
bool ret = true; | ||
|
||
FLASH_unlock(); | ||
// Set the PG bit in FLASH_CR which enables writing | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_PG); | ||
|
||
// write all the data | ||
for (uint16_t dataIdx = 0U; dataIdx < dataLen; dataIdx++) | ||
{ | ||
while (FLASH_BUSY()) | ||
{} | ||
volatile uint16_t* addr_16 = (volatile uint16_t*)(addr + dataIdx * sizeof(uint16_t)); | ||
*addr_16 = data[dataIdx]; | ||
|
||
while (FLASH_BUSY()) | ||
{} | ||
|
||
// verify the data in flash, | ||
// compare as halfwords | ||
if (*addr_16 != data[dataIdx]) | ||
{ | ||
ret = false; | ||
break; | ||
} | ||
} | ||
|
||
// Clear the PG bit in FLASH_CR | ||
SET_REG(FLASH_CR, GET_REG(FLASH_CR) & ~FLASH_CR_PG); | ||
FLASH_lock(); | ||
|
||
return ret; | ||
} | ||
|
||
uint32_t FLASH_getPageSize(void) | ||
{ | ||
uint16_t *flashSize = (uint16_t *)(FLASH_SIZE_REG); | ||
|
||
// chips with more than 128 pages of flash have pages of size 2k | ||
// otherwise, pages are of size 1k | ||
if ((*flashSize & 0xFFFF) > 128U) | ||
{ | ||
return 2048U; | ||
} | ||
else | ||
{ | ||
return 1024U; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* HW_FLASH.h | ||
* This file describes low-level, mostly hardware-specific Flash peripheral values | ||
*/ | ||
|
||
#pragma once | ||
|
||
/****************************************************************************** | ||
* I N C L U D E S | ||
******************************************************************************/ | ||
|
||
#include "Types.h" | ||
|
||
/****************************************************************************** | ||
* P U B L I C F U N C T I O N P R O T O T Y P E S | ||
******************************************************************************/ | ||
|
||
void FLASH_init(void); | ||
|
||
void FLASH_lock(void); | ||
void FLASH_unlock(void); | ||
|
||
uint32_t FLASH_getPageSize(void); | ||
bool FLASH_erasePages(uint32_t pageAddr, uint16_t pages); | ||
bool FLASH_writeHalfwords(uint32_t addr, uint16_t *data, uint16_t dataLen); | ||
bool FLASH_writeWords(uint32_t addr, uint32_t *data, uint16_t dataLen); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* LIB_nvm_config.h | ||
* LIB_nvm Component Specific file | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "HW.h" | ||
#include "HW_flash.h" | ||
#include "LIB_nvm.h" | ||
|
||
/****************************************************************************** | ||
* T Y P E D E F S | ||
******************************************************************************/ | ||
|
||
#define LIB_NVM_GET_TIME_MS HW_getTick | ||
#define LIB_NVM_GET_FLASH_PAGE_SIZE FLASH_getPageSize | ||
#define LIB_NVM_CLEAR_FLASH_PAGES FLASH_erasePages | ||
#define LIB_NVM_WRITE_TO_FLASH(addr, data, bytes) FLASH_writeHalfwords(addr, data, bytes / sizeof(storage_t)) | ||
|
||
typedef enum | ||
{ | ||
NVM_ENTRYID_COUNT = 0U, | ||
} lib_nvm_entryId_E; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/* | ||
* libcrc_componentSpecific.h | ||
* | ||
* Configuration for the libcrc module | ||
*/ | ||
|
||
#define LIBCRC_CRC8_FAST |
Oops, something went wrong.