Skip to content

Commit

Permalink
NVM library bringup
Browse files Browse the repository at this point in the history
- BMS Boss NVM bringup
  • Loading branch information
JoshLafleur committed Nov 10, 2024
1 parent f788437 commit 85e51c0
Show file tree
Hide file tree
Showing 23 changed files with 1,050 additions and 31 deletions.
255 changes: 255 additions & 0 deletions components/bms_boss/HW/HW_flash.c
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;
}
}

4 changes: 4 additions & 0 deletions components/bms_boss/HW/include/BuildDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include "FeatureDefines_generated.h"
#include "BuildDefines_generated.h"

#define NVM_LIB_ENABLED FEATURE_ENABLED
#define NVM_FLASH_BACKED FEATURE_ENABLED
#define NVM_BLOCK_SIZE 2048 // Multiple of page size

#if MCU_STM32_PN == FDEFS_STM32_PN_STM32F103XB
#define STM32F1
#define STM32F103xB
Expand Down
26 changes: 26 additions & 0 deletions components/bms_boss/HW/include/HW_flash.h
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);
4 changes: 4 additions & 0 deletions components/bms_boss/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ project_source_files = [
SRC_DIR.File("Utility.c"),
SRC_DIR.File("UDS.c"),
SHARED_LIBS.File("LIB_app.c"),
SHARED_LIBS.File("LIB_nvm.c"),
SHARED_LIBS.File("libcrc.c"),
SRC_DIR.File("NVM.c"),
]

project_hw_files = [
Expand All @@ -162,6 +165,7 @@ project_hw_files = [
HW_DIR.File("HW_msp.c"),
HW_DIR.File("HW_tim.c"),
HW_DIR.File("HW_HIH.c"),
HW_DIR.File("HW_flash.c"),
]

project_source_files += project_hw_files
Expand Down
15 changes: 0 additions & 15 deletions components/bms_boss/include/BuildDefines_config.h

This file was deleted.

24 changes: 24 additions & 0 deletions components/bms_boss/include/LIB_nvm_config.h
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;
7 changes: 7 additions & 0 deletions components/bms_boss/include/libcrc_componentSpecific.h
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
Loading

0 comments on commit 85e51c0

Please sign in to comment.