Tiny storage(file) system on MCU internal flash memory for Nucleo F4xx. The purpose of SOFBlock class is to provide a way to write data on flash memory in the same way of file handling class in the file system.

Files at this revision

API Documentation at this revision

Comitter:
masaaki_makabe
Date:
Wed Nov 16 04:49:19 2022 +0000
Parent:
4:a59b917583c9
Commit message:
add STM32L4xx

Changed in this revision

SOF_dev_stm32_f4xx.cpp Show diff for this revision Revisions of this file
SOF_dev_stm32_l4xx.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/SOF_dev_stm32_f4xx.cpp	Fri Nov 05 04:30:56 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/**
-* @file SOF_dev_stm32.c
-*
-* @brief Flash device access interface for STM32 F4xx series
-*
-*
-* History:
-*/
-
-#include <stdio.h>
-#include "SOF_dev.h"
-#include <string.h>
-
-#include "mbed.h"
-#include "stm32f4xx_hal_flash.h"
-
-#define DCRLF	"\r\n"
-
-#if 0
-#define DPRINTF	printf
-#define DASSERT(cond)  \
-	if (!(cond)) { \
-		printf("%s:%d assertion failed! '%s\r\n"\
-			, __FILE__, __LINE__, #cond); \
-	}
-#else
-#define DPRINTF(...)
-#define DASSERT(...)
-#endif
-
-#if defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F407xx)
-static const SOF_SectorSpec_t _sec_spec[] = {
-    {FLASH_SECTOR_0, 0x08000000, 16*1024},
-    {FLASH_SECTOR_1, 0x08004000, 16*1024},
-    {FLASH_SECTOR_2, 0x08008000, 16*1024},
-    {FLASH_SECTOR_3, 0x0800C000, 16*1024},
-    {FLASH_SECTOR_4, 0x08010000, 64*1024},
-    {FLASH_SECTOR_5, 0x08020000, 128*1024},
-    {FLASH_SECTOR_6, 0x08040000, 128*1024},
-    {FLASH_SECTOR_7, 0x08060000, 128*1024},
-};
-//#else
-//#error "Not supported device"
-#endif
-
-/* debug mak  STM32F412xx 1MBytes --------------------------------------------*/
-#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) ||\
-    defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx)  
-static const SOF_SectorSpec_t _sec_spec[] = {
-    {FLASH_SECTOR_0,  0x08000000, 16*1024},
-    {FLASH_SECTOR_1,  0x08004000, 16*1024},
-    {FLASH_SECTOR_2,  0x08008000, 16*1024},
-    {FLASH_SECTOR_3,  0x0800C000, 16*1024},
-    {FLASH_SECTOR_4,  0x08010000, 64*1024},
-    {FLASH_SECTOR_5,  0x08020000, 128*1024},
-    {FLASH_SECTOR_6,  0x08040000, 128*1024},
-    {FLASH_SECTOR_7,  0x08060000, 128*1024},
-    {FLASH_SECTOR_8,  0x08080000, 128*1024},
-    {FLASH_SECTOR_9,  0x080A0000, 128*1024},
-    {FLASH_SECTOR_10, 0x080C0000, 128*1024},
-    {FLASH_SECTOR_11, 0x080E0000, 128*1024},
-};
-#endif
-
-#define N_SECTOR_SPEC			(sizeof(_sec_spec)/sizeof(_sec_spec[0]))
-
-#define SECTOR_NO(sector)		_sec_spec[sector].sec_no
-#define SECTOR_ADDR(sector)	_sec_spec[sector].sec_addr
-#define SECTOR_SIZE(sector)		_sec_spec[sector].sec_size
-
-
-static inline size_t handle_to_sector_index(SOF_DevHandle_t hdev)
-{
-    DASSERT(hdev < N_SECTOR_SPEC);
-    return hdev;
-}
-
-const SOF_SectorSpec_t *SOF_dev_info(uint8_t sector_index)
-{
-    DASSERT(sector_index < N_SECTOR_SPEC);
-    return &_sec_spec[sector_index];
-}
-
-int SOF_dev_is_valid_sector(uint8_t sector_index)
-{
-    return sector_index < N_SECTOR_SPEC;
-}
-
-const SOF_SectorSpec_t *SOF_dev_info_by_index(uint8_t sector_index)
-{
-    DASSERT(SOF_dev_is_valid_sector(sector_index));
-    return &_sec_spec[sector_index];
-}
-
-const SOF_SectorSpec_t *SOF_dev_info(SOF_DevHandle_t hdev)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-
-    return SOF_dev_info_by_index(sector_index);
-}
-
-SOF_DevHandle_t SOF_dev_open(uint8_t sector_index)
-{
-    DASSERT(sector_index < N_SECTOR_SPEC);
-    return (SOF_DevHandle_t)sector_index;
-}
-
-void SOF_dev_close(SOF_DevHandle_t hdev)
-{
-}
-
-uint8_t *SOF_dev_get_hw_addr(SOF_DevHandle_t hdev)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-
-    return (uint8_t *)SECTOR_ADDR(sector_index);
-}
-
-
-void SOF_dev_erase(SOF_DevHandle_t hdev)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-    FLASH_EraseInitTypeDef ei;
-    uint32_t error = 0;
-
-    DPRINTF("FLASH_Erase_Sector %d"DCRLF, SECTOR_NO(sector_index));
-    HAL_FLASH_Unlock();
-
-    ei.TypeErase = TYPEERASE_SECTORS;
-    ei.Sector = SECTOR_NO(sector_index);
-    ei.NbSectors = 1;
-    ei.Banks = 0;
-    ei.VoltageRange = VOLTAGE_RANGE_3;
-    HAL_FLASHEx_Erase(&ei, &error);
-    HAL_FLASH_Lock();
-    DPRINTF("FLASH_Erase_Sector ok"DCRLF);
-}
-
-
-int SOF_dev_write_word(SOF_DevHandle_t hdev, uint32_t offset_addr, uint32_t data)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-    uint32_t dst = SECTOR_ADDR(sector_index) + offset_addr;
-
-    DASSERT((offset_addr%sizeof(uint32_t)) == 0);
-    HAL_FLASH_Unlock();
-    if (HAL_FLASH_Program(TYPEPROGRAM_WORD, dst, data) != HAL_OK) {
-        DPRINTF("FLASH_ProgramWord failed: %#x"DCRLF, dst);
-        HAL_FLASH_Lock();
-        return -1;
-    }
-
-    HAL_FLASH_Lock();
-
-    if (data != SOF_dev_read_word(hdev, offset_addr)) {
-        DPRINTF("addr=%x %#04x %#04x"DCRLF, dst, data, SOF_dev_read_word(hdev, offset_addr));
-        return -1;
-    }
-
-    return 0;
-}
-
-uint32_t SOF_dev_read_word(SOF_DevHandle_t hdev, uint32_t offset_addr)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-    uint32_t src = SECTOR_ADDR(sector_index) + offset_addr;
-
-    DASSERT((offset_addr%sizeof(uint32_t)) == 0);
-
-    return *(volatile uint32_t*)src;
-}
-
-int SOF_dev_write_byte(SOF_DevHandle_t hdev, uint32_t offset_addr, uint8_t data)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-    uint32_t dst = SECTOR_ADDR(sector_index) + offset_addr;
-
-    HAL_FLASH_Unlock();
-    if (HAL_FLASH_Program(TYPEPROGRAM_BYTE, dst, data) != HAL_OK) {
-        DPRINTF("FLASH_ProgramWord failed: %#x"DCRLF, dst);
-        HAL_FLASH_Lock();
-        return -1;
-    }
-
-    HAL_FLASH_Lock();
-
-    if (data != SOF_dev_read_byte(hdev, offset_addr)) {
-        DPRINTF("addr=%x %#02x %#02x"DCRLF, dst, data, SOF_dev_read_byte(hdev, offset_addr));
-        return -1;
-    }
-
-    return 0;
-}
-
-uint8_t SOF_dev_read_byte(SOF_DevHandle_t hdev, uint32_t offset_addr)
-{
-    uint8_t sector_index = handle_to_sector_index(hdev);
-    uint32_t src = SECTOR_ADDR(sector_index) + offset_addr;
-
-    return *(volatile uint8_t*)src;
-}
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SOF_dev_stm32_l4xx.cpp	Wed Nov 16 04:49:19 2022 +0000
@@ -0,0 +1,311 @@
+/**
+* @file SOF_dev_stm32_l4xx.c
+*
+* @brief Flash device access interface for STM32 L4xx series
+*
+*
+* History:
+*/
+
+#include <stdio.h>
+#include "SOF_dev.h"
+#include <string.h>
+
+#include "mbed.h"
+
+#include "stm32l4xx_hal_flash.h"
+
+#define DCRLF	"\r\n"
+
+#if 0
+extern Serial pc;
+#define DPRINTF	pc.printf
+#define DASSERT(cond)  \
+	if (!(cond)) { \
+		pc.printf("%s:%d assertion failed! '%s\r\n"\
+			, __FILE__, __LINE__, #cond); \
+	}
+#else
+#define DPRINTF(...)
+#define DASSERT(...)
+#endif
+
+// 1024*4*sizeof(byte) = 4Kbyte flash must (application)
+//
+// STM32L4xx flash area
+//  bank  address      size  page   (virtual_sector)
+//  1     0x08000000   2k    0
+//  1     0x08000800   2k    1
+//  1     0x08001000   2k    2
+//
+//  1     0x0803C000   2k    120     11
+//  1     0x0803C800   2k    121     11
+//  1     0x0803D000   2k    122     11
+//  1     0x0803D800   2k    123     11
+//  1     0x0803E000   2k    124     11 <-- ここを11セクタの先頭とする
+//  1     0x0803E800   2k    125     11
+//  1     0x0803F000   2k    126     11
+//  1     0x0803F800   2k    127     11 <-- STM32L432KC ここまで (256KB)
+//
+//  1     0x0807C000   2k    248     11 
+//  1     0x0807C800   2k    249     11
+//  1     0x0807D000   2k    250     11
+//  1     0x0807D800   2k    251     11
+//  1     0x0807E000   2k    252     11
+//  1     0x0807E800   2k    253     11
+//  1     0x0807F000   2k    254     11
+//  1     0x0807F800   2k    255     11 <-- 512KB
+#define REQ_SECTOR  11
+#define PAGE_SIZE   2048
+#define START_ADDRESS  0x0803E000 //11セクタの先頭アドレス
+
+/*--- sector11 table ---*/
+#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx)
+static const SOF_SectorSpec_t _sec11_spec[] = {
+//   page    address              size
+    {124,    START_ADDRESS+0x0000, PAGE_SIZE},
+    {125,    START_ADDRESS+0x0800, PAGE_SIZE},
+    {126,    START_ADDRESS+0x1000, PAGE_SIZE},
+    {127,    START_ADDRESS+0x1800, PAGE_SIZE},//last page
+};
+#elif defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx)
+static const SOF_SectorSpec_t _sec11_spec_example[] = {
+    {255,    START_ADDRESS+0x0000, PAGE_SIZE},//last page
+};
+#else
+  #error "Not supported device"
+#endif
+
+#define N_PAGE_SPEC    (sizeof(_sec11_spec)/sizeof(_sec11_spec[0]))
+#define PAGE_NO(page)   _sec11_spec[0].sec_no //top page
+#define PAGE_ADDR(page)  _sec11_spec[0].sec_addr //top address
+
+static const SOF_SectorSpec_t _sec11_dummy = {
+    //                         ここ重要。ページの最後をセットすること
+    REQ_SECTOR, START_ADDRESS, PAGE_SIZE*N_PAGE_SPEC
+};
+
+static uint64_t _data64w = 0;
+static uint64_t _data64b = 0;
+static int32_t _offset_addr_w = -1;
+static int32_t _offset_addr_b = -1;
+
+static inline size_t handle_to_sector_index(SOF_DevHandle_t hdev)
+{
+	DASSERT(hdev == REQ_SECTOR);
+    return hdev;
+}
+
+int SOF_dev_is_valid_sector(uint8_t sector_index)
+{
+	return sector_index == REQ_SECTOR;
+}
+
+const SOF_SectorSpec_t *SOF_dev_info_by_index(uint8_t sector_index)
+{
+    DASSERT(SOF_dev_is_valid_sector(sector_index));
+    return &_sec11_dummy;
+}
+
+const SOF_SectorSpec_t *SOF_dev_info(SOF_DevHandle_t hdev)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    return SOF_dev_info_by_index(sector_index);
+}
+
+SOF_DevHandle_t SOF_dev_open(uint8_t sector_index)
+{
+    DPRINTF("SOF_dev_open %d\r\n", sector_index);
+	_data64w = _data64b = 0;
+	_offset_addr_w = -1;
+	_offset_addr_b = -1;
+
+    DASSERT(sector_index == REQ_SECTOR);
+    return (SOF_DevHandle_t)sector_index;
+}
+
+void SOF_dev_close(SOF_DevHandle_t hdev)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    DPRINTF("SOF_dev_close %d\r\n", sector_index);
+
+	//if write pending, must write
+    //
+	if(_offset_addr_w >= 0){
+		SOF_dev_write_word(sector_index, _offset_addr_w + 4, 0);//+4:write finish
+	}
+	if(_offset_addr_b >= 0){
+		SOF_dev_write_byte(sector_index, _offset_addr_b + 7, 0);//+7:write finish
+	}
+}
+
+uint8_t *SOF_dev_get_hw_addr(SOF_DevHandle_t hdev)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    return (uint8_t *)PAGE_ADDR(sector_index);
+}
+
+/*--- hdev is sector (11 only by application)  ---*/
+void SOF_dev_erase(SOF_DevHandle_t hdev)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    FLASH_EraseInitTypeDef ei;
+    uint32_t error = 0;
+
+    DPRINTF("FLASH_Erase_Page %d"DCRLF, PAGE_NO(sector_index));
+    HAL_FLASH_Unlock();
+
+    ei.TypeErase = FLASH_TYPEERASE_PAGES;
+#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) ||\
+    defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx)
+    ei.Banks = FLASH_BANK_1;//bank1 only
+#else
+    ei.Banks = FLASH_BANK_2;
+#endif
+    ei.Page = PAGE_NO(secotr_index); //top page
+    ei.NbPages = N_PAGE_SPEC; //number of page
+    HAL_StatusTypeDef ret = HAL_FLASHEx_Erase(&ei, &error);
+
+    HAL_FLASH_Lock();
+    DPRINTF("FLASH_Erase_Page ret=%d, page=%d, n=%d\r\n", ret, ei.Page, ei.NbPages);
+}
+
+uint64_t SOF_dev_read_dword(SOF_DevHandle_t hdev, uint32_t offset_addr)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    uint32_t src = PAGE_ADDR(sector_index) + offset_addr;
+    uint64_t ret = *(volatile uint64_t*)src;
+    return ret;
+}
+
+int SOF_dev_write_word(SOF_DevHandle_t hdev, uint32_t offset_addr, uint32_t data)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    uint32_t dst = PAGE_ADDR(sector_index) + offset_addr;
+    DPRINTF("SOF_dev_write_word dst=%08X ofs=%d, ", dst, offset_addr);
+    // +0     +4     +8
+    //  +------+------+
+    //  |DWORDH|DWORDL|
+    //  +------+------+
+    if(offset_addr % 8 == 0){//address 8 multiple
+    	_data64w |= data;
+    	_offset_addr_w = offset_addr;
+        DPRINTF("data=%08X\r\n", data);
+    	return 0;//next waiting
+    } else if(offset_addr % 4 == 0){//address 4 multiple
+    	_data64w |= ((uint64_t)data << 32);
+        dst = PAGE_ADDR(sector_index) + _offset_addr_w;
+        DPRINTF("data=%08X\r\n", data);
+    }
+
+    DASSERT((offset_addr % sizeof(uint32_t)) == 0);//required address 4 multiple
+    HAL_FLASH_Unlock();
+
+    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, dst, _data64w) != HAL_OK) {
+        DPRINTF("FLASH_ProgramWord failed: %#x"DCRLF, dst);
+        HAL_FLASH_Lock();
+        return -1;
+    }
+
+    HAL_FLASH_Lock();
+
+/*--- read back ---*/
+    if (_data64w != SOF_dev_read_dword(hdev, _offset_addr_w)) {
+        DPRINTF("addr=%X %#04X %#04X"DCRLF, dst, data, SOF_dev_read_dword(hdev, _offset_addr_w));
+        return -1;
+    }
+
+    _data64w = 0;//finish
+    _offset_addr_w = -1;//finish
+
+    return 0;
+}
+
+uint32_t SOF_dev_read_word(SOF_DevHandle_t hdev, uint32_t offset_addr)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    uint32_t src = PAGE_ADDR(sector_index) + offset_addr;
+    DASSERT((offset_addr % sizeof(uint32_t)) == 0);//required address 4 multiple
+
+    uint32_t ret = *(volatile uint32_t*)src;
+    DPRINTF("SOF_dev_read_word src=%08X, ret=%08X\r\n", src, ret);
+    return ret;
+}
+
+int SOF_dev_write_byte(SOF_DevHandle_t hdev, uint32_t offset_addr, uint8_t data)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    uint32_t dst = PAGE_ADDR(sector_index) + offset_addr;
+    DPRINTF("SOF_dev_write_byte dst=%08X ofs=%d, ", dst, offset_addr);
+    // +0     +1     +2     +3     +4             +8
+    //  +------+------+------+------+----   +------+
+    //  |BYTE1 |BYTE2 |BYTE3 |BYTE4 |       |BYTE8 |
+    //  +------+------+------+------+----   +------+
+    if(offset_addr % 8 == 0){//address 4 multiple
+    	_data64b |= ((uint64_t)data << (64-64));
+    	_offset_addr_b = offset_addr;
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;//next waiting
+    } else if(offset_addr % 8 == 1){
+    	_data64b |= ((uint64_t)data << (64-56));
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;
+    } else if(offset_addr % 8 == 2){
+    	_data64b |= ((uint64_t)data << (64-48));
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;
+    } else if(offset_addr % 8 == 3){
+    	_data64b |= ((uint64_t)data << (64-40));
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;
+    } else if(offset_addr % 8 == 4){
+    	_data64b |= ((uint64_t)data << (64-32));
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;
+    } else if(offset_addr % 8 == 5){
+    	_data64b |= ((uint64_t)data << (64-24));
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;
+    } else if(offset_addr % 8 == 6){
+    	_data64b |= ((uint64_t)data << (64-16));
+        DPRINTF("data=%02X\r\n", data);
+    	return 0;
+    } else if(offset_addr % 8 == 7){
+    	_data64b |= ((uint64_t)data << (64-8));
+    	dst = PAGE_ADDR(sector_index) + _offset_addr_b;
+        DPRINTF("data=%02X\r\n", data);
+    }
+
+    HAL_FLASH_Unlock();
+
+    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, dst, _data64b) != HAL_OK) {
+        DPRINTF("FLASH_ProgramByte failed: %#x"DCRLF, dst);
+        HAL_FLASH_Lock();
+        return -1;
+    }
+
+    HAL_FLASH_Lock();
+
+/*--- read back ---*/
+    if (_data64b != SOF_dev_read_dword(hdev, _offset_addr_b)) {
+        DPRINTF("addr=%X %#04X %#04X"DCRLF, dst, data, SOF_dev_read_dword(hdev, _offset_addr_b));
+        return -1;
+    }
+
+    _data64b = 0;//finish
+    _offset_addr_b = -1;//finish
+
+    return 0;
+}
+
+uint8_t SOF_dev_read_byte(SOF_DevHandle_t hdev, uint32_t offset_addr)
+{
+    uint8_t sector_index = handle_to_sector_index(hdev);
+    uint32_t src = PAGE_ADDR(sector_index) + offset_addr;
+    uint8_t ret = *(volatile uint8_t*)src;
+    DPRINTF("SOF_dev_read_byte src=%08X, ret=%02X\r\n", src, ret);
+    return ret;
+}
+
+
+