【TOSHIBA MCU】TMPM3HQ Data Flash 資料存取

一、 前言

本文主要介紹在 TOSHIBA TMPM3HQ 開發板進行 MCU 內部 Data Flash的資料存取。


二、 開發板介紹

AdBun-M3HQ ( TMPM3HQ MCU 開發板 ): 



三、 Data Flash 記憶體的組成

TMPM3HQ 內部的 Flash 分為 Code Flash 與 Data Flash,Code Flash 用於存放程式碼,Data Flash 則可用於存放使用者的資料。

以下是 Code Flash 與Data Flash 在記憶體中對應的位置;Data Flash 所佔的大小為 32 KB,從 0x30000000 ~ 0x30008000。 


Data Flash 記憶體結構由“Area”、“Block”、“Page”單元組成。
● Area  : Data Flash 只有一個 Area,大小為 32 KB。
● Block : 一個 Block 大小為 4 KB。
● Page  : 一個 Page  大小為 256 byte。

下表表示一個 Area (32KB) Block的配置方式,共分為 8 個 Block,每個 Block 為 4 KB 


下表表示一個 Area (32KB) Page 的配置方式,共分為 128 個 Page,每個 Page 為 256 Byte 


 Area = 8 Block x 4 KB = 128 Page x 256 byte = 32KB


四、 Data Flash 資料的存取

東芝提供軟體開發包:TMPM3HQA_V113.zip,本文採用其中的 FLASH_Data 範例加以介紹。

Data Flash 的處理方式概述如下:
(1) 存取 Data Flash 的初始化設定: 
{
flash_t *p_flash = &instance.flash;

/*--- Construct ---*/
/* Register Allocation */
p_flash->p_instance = TSB_FC; // 指向 Flash 暫存器起始的位置

/*--- Initialize ---*/
p_flash->init.status = FC_SR0_RDYBSY; // 設定 Flash 為預備存取的狀態
p_flash->init.first_page_data = FC_DATA_FLASH_PAGE0; // 設定從 PAGE0 開始存取資料
p_flash->init.num_of_pages_data = 1; // 設定存取一個 page 的資料
p_flash->init.first_block = FC_DATA_FLASH_BLOCK0; // 設定從 BLOCK0 開始存取資料
p_flash->init.num_of_block = 1; // 設定存取一個 block 的資料
p_flash->init.area = FC_DATA_FLASH_AREA4; // 設定存取 AREA4 (data flash) 的資料
}​

(2) 驗證存取功能的測試資料: 
#pragma location="DATA_A"
const unsigned char data_a[256] =
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
};

#pragma section = "DATA_A"
#define DEMO_A_RAM ((uint32_t *)__section_begin("DATA_A"))
#define SIZE_DEMO_A ((uint32_t) __section_size ("DATA_A"))​

(3)  擦除 Data Flash 的 API:
fc_erase_page_data_flash(&instance.flash)		// Page	 的擦除
fc_erase_block_data_flash(&instance.flash) // Block 的擦除
fc_erase_area_data_flash(&instance.flash) // Area 的擦除​

instance.flash.init.first_page_data  = FC_DATA_FLASH_PAGE0;        // 設定要存取PAGE

fc_erase_page_data_flash(&instance.flash)

instance.flash.init.first_block_data = FC_DATA_FLASH_BLOCK0;      // 設定要存取的 BLOCK 
fc_erase_block_data_flash(&instance.flash)

instance.flash.init.first_area_data   = FC_DATA_FLASH_AREA4;        // 設定要存取 AREA
fc_erase_area_data_flash(&instance.flash)

(4)  將資料寫入 Data Flash 的 API
使用 fc_write_data_flash(p_flash) 將資料寫入Flash;
在呼叫前,必須先設定好以下內容
  1. 資料來源地址,    例如 :     p_flash->init.src_address = DEMO_A_RAM;
  2. 寫入目的地址,    例如 :     p_flash->init.dst_address = PAGE_1_FRAM;
  3. 寫入資料的大小,例如 :     p_flash->init.size               = SIZE_DEMO_A;
參考代碼如下:
#define PAGE_0_FRAM             (uint32_t *)0x30000000
#define PAGE_1_FRAM (uint32_t *)0x30000100

{
TXZ_Result retval = TXZ_SUCCESS;
flash_t *p_flash = &instance.flash;

p_flash->init.src_address = DEMO_A_RAM;
p_flash->init.dst_address = PAGE_1_FRAM;
p_flash->init.size = SIZE_DEMO_A;

if(fc_write_data_flash(p_flash) == TXZ_ERROR){
retval = TXZ_ERROR;
}
else {
p_flash->init.src_address = DEMO_A_RAM;
p_flash->init.dst_address = PAGE_2_FRAM;
p_flash->init.size = SIZE_DEMO_A;
if(fc_write_data_flash(p_flash) == TXZ_ERROR){
retval = TXZ_ERROR;
}
else {
/* do nothing */
}
}
return (retval);
}​

(5)  驗證寫入 Data Flash 的資料
使用 memcmp(src_address, dst_address, size) 驗證目的和來源資料是否相符。  

也可以在 IAR 的記憶體視窗中直接檢驗結果


(6)  讀取 Data Flash 的資料
使用 memcpy(src_address, dst_address, size) 讀取指定位置的資料。
例如: 
#define DEMO_A_RAM			((uint32_t *)__section_begin("DATA_A"))
uint8_t *ptr_A = (uint8_t *)DEMO_A_RAM;
memcpy(ptr_A, PAGE_1_FRAM, SIZE_DEMO_A); // 將資料拷貝到 ptr_A​


[程式修改部分]
可在 main.c 中找到以下的“case PROC_VERIFY:”,增加以下的程式碼,可印出寫入 Flash 中的資料:
    case PROC_VERIFY:
if(verify_fc_func() == TXZ_ERROR){
proc = PROC_ERROR;
}else{
#if 1
uint8_t *ptr_A = (uint8_t *)DEMO_A_RAM;
uint8_t *ptr_B = (uint8_t *)DEMO_A_RAM;

printf("Verify the Flash data\n");
memcpy(ptr_A, PAGE_1_FRAM, SIZE_DEMO_A);
printf("The Data Flash Page1 data as below:\n");
for(uint32_t i = 0; i < SIZE_DEMO_A; i++) {
printf("%02x ", (uint8_t)(*ptr_A++));

if((i % 0x10) == 0xfU){
printf("\n");
}

if(i==0xff){
printf("\n");
}
}

memcpy(ptr_B, PAGE_2_FRAM, SIZE_DEMO_A);
printf("The Data Flash Page2 data as below:\n");
for(uint32_t j = 0; j < SIZE_DEMO_A; j++) {
if(i < 0xff){
printf("%02x ", (uint8_t)(*ptr_B++));

if((j % 0x10) == 0xfU){
printf("\n");
}
} else {
printf("\n");
}
}
##endif
proc = PROC_PAGE_ERASING;
}
break;​


[執行結果] 


最後,以下是 TMPM3HQ Data Flash 寫入及擦除所需時間的相關資料,提供參考: 




參考資料文檔
1. 東芝 TMPM3HQA _v113 軟件開發包:TMPM3HQA_V113.zip
請洽 世平興業 東芝產品線 FAE Chad Lee : chad.lee@wpi-group.com

2. 東芝 Flash Memory 參考手冊
TXZ-FLASH512-32-A_en_20180720.pdf

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★博文作者未開放評論功能

參考來源