QQ: 971586331
Software environment:
Operating system: Windows 10
IDE: CCS7.4
Code generation tool: HALCoGen 04.07.01
Flash operation library: F021FlashApi-02.01.01
Hardware environment:
Target board: TMDS570LS31HDK
This article describes the internal flash programming method of the TMS570 system chip
1. New CCS project
Create a new project boot_test according to the process in TMS570 Learning 1.
2. Install the F021 library
Download the F021 library from TI's official website, HERCULES F021FLASHAPI . After downloading, it is an exe. After installation, it looks like this:
include: API interface header file
Source: User-defined callback, there is only one Fapi_UserDefinedFunctions.c file, and there is only one function Fapi_serviceWatchdogTimer in the file. According to the description, this function will be called when erasing, writing and reading. The watchdog can be fed in the function to prevent the flash operation time from being too long and causing a reset.
Lib file: lib files are divided into three categories, M3_BE, R4_BE and R4_LE, BE is big-endian mode, LE is little-endian mode, the TMS570 we use is big-endian mode (can be known by reading the ENDIAN_REG register), so we use R4_BE.
SPNA148.pdf: This document is an example of operating flash, which contains operation codes and flow charts
SPNU501G.pdf: This document is the API description
3. Transplant F021 library
Copy the include directory, source directory, and lib files with the R4_BE suffix to the project, and add the header file path to the project.
Refer to the program template in Chapter 3 of SPNA148.pdf and the flowchart in Chapter 5 of SPNU501G.pdf to write the flash operation function. The following is the program template for flash operation:
Sector erase process:
Block erase process:
Programming process:
4. Write flash operation function
According to the operation process in the previous section, write the flash operation interface, mainly implementing the following four interfaces:
Flash_EraseSector: Erase sector
Flash_EraseBanks: Erase Banks
Flash_WriteData: write data
Flash_ReadData: Read data
/*
* flash_handle.h
*
* Created on: 2019年8月15日
* Author: shiyu
*/
#ifndef USER_FLASH_HANDLE_H_
#define USER_FLASH_HANDLE_H_
#include "F021.h"
enum e_flash_status
{
flash_succeed,
flash_failure,
};
struct Sector_List
{
Fapi_FlashBankType banks_num;
uint32_t sector_num;
uint32_t low_addr;
uint32_t size;
};
#define SECTOR_NUM (15+12+4)
enum e_flash_status Flash_EraseSector(Fapi_FlashBankType oNewFlashBank, uint32_t sector);
enum e_flash_status Flash_EraseBanks(Fapi_FlashBankType oNewFlashBank);
enum e_flash_status Flash_WriteData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len);
void Flash_ReadData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len);
#endif /* USER_FLASH_HANDLE_H_ */
/*
* flash_handle.c
*
* Created on: 2019年8月15日
* Author: shiyu
*/
#include "F021.h"
#include "flash_handle.h"
//TMS570LS3137的flash分区表
struct Sector_List gSector_List[SECTOR_NUM] =
{
// 块编号 扇区编号 扇区起始地址 扇区大小
{Fapi_FlashBank0, 0, 0x00000000, 32*1024},
{Fapi_FlashBank0, 1, 0x00008000, 32*1024},
{Fapi_FlashBank0, 2, 0x00010000, 32*1024},
{Fapi_FlashBank0, 3, 0x00018000, 32*1024},
{Fapi_FlashBank0, 4, 0x00020000, 128*1024},
{Fapi_FlashBank0, 5, 0x00040000, 128*1024},
{Fapi_FlashBank0, 6, 0x00060000, 128*1024},
{Fapi_FlashBank0, 7, 0x00080000, 128*1024},
{Fapi_FlashBank0, 8, 0x000A0000, 128*1024},
{Fapi_FlashBank0, 9, 0x000C0000, 128*1024},
{Fapi_FlashBank0, 10, 0x000E0000, 128*1024},
{Fapi_FlashBank0, 11, 0x00100000, 128*1024},
{Fapi_FlashBank0, 12, 0x00012000, 128*1024},
{Fapi_FlashBank0, 13, 0x00014000, 128*1024},
{Fapi_FlashBank0, 14, 0x00016000, 128*1024},
{Fapi_FlashBank1, 0, 0x00018000, 128*1024},
{Fapi_FlashBank1, 1, 0x0001A000, 128*1024},
{Fapi_FlashBank1, 2, 0x0001C000, 128*1024},
{Fapi_FlashBank1, 3, 0x0001E000, 128*1024},
{Fapi_FlashBank1, 4, 0x00020000, 128*1024},
{Fapi_FlashBank1, 5, 0x00022000, 128*1024},
{Fapi_FlashBank1, 6, 0x00024000, 128*1024},
{Fapi_FlashBank1, 7, 0x00026000, 128*1024},
{Fapi_FlashBank1, 8, 0x00028000, 128*1024},
{Fapi_FlashBank1, 9, 0x0002A000, 128*1024},
{Fapi_FlashBank1, 10, 0x0002C000, 128*1024},
{Fapi_FlashBank1, 11, 0x0002E000, 128*1024},
{Fapi_FlashBank7, 0, 0xF0200000, 16*1024},
{Fapi_FlashBank7, 1, 0xF0204000, 16*1024},
{Fapi_FlashBank7, 2, 0xF0208000, 16*1024},
{Fapi_FlashBank7, 3, 0xF020C000, 16*1024},
};
/* [url=home.php?mod=space&uid=159083]@brief[/url] 查找扇区信息
* @param[in] oNewFlashBank:块编号
* @param[in] sector:扇区编号
*
* return:扇区在数据结构中的位置
*/
uint32_t find_sector(Fapi_FlashBankType oNewFlashBank, uint32_t sector)
{
int i=0;
for(i=0; i<SECTOR_NUM; i++)
{
if( (gSector_List[i].banks_num == oNewFlashBank) && (gSector_List[i].sector_num == sector) )
{
return i;
}
}
}
/* @brief 擦除扇区
* @param[in] oNewFlashBank:块编号
* @param[in] sector:扇区编号
*
* return:
*/
enum e_flash_status Flash_EraseSector(Fapi_FlashBankType oNewFlashBank, uint32_t sector)
{
int num = 0;
Fapi_StatusType oReturnCheck = Fapi_Status_Success;
num = find_sector(oNewFlashBank, sector); //根据块ID和扇区ID查找扇区信息
printf("addr = %x\n", gSector_List[num].low_addr);
oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作
if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
{
oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank); //设置活动的Flash Bank
if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) )
oReturnCheck = Fapi_enableMainBankSectors( 1<<(sector+1) ); //设置EEPROM存储区中可用的扇区以进行擦除和编程
else if( oNewFlashBank == Fapi_FlashBank7 )
oReturnCheck = Fapi_enableEepromBankSectors(1<<(sector+1) ,1<<((sector+1)%32)); //设置EEPROM存储区中可用的扇区以进行擦除和编程
while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, gSector_List[num].low_addr); //向Flash状态机发出命令
/* Place specific example code here */
/* Wait for FSM to finish */
while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
/* Check the FSM Status to see if there were no errors */
if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
{
/* Put Error handling code here */
return flash_failure;
}
}
return flash_succeed;
}
/* @brief 擦除块
* @param[in] oNewFlashBank:块编号
*
* return:
*/
enum e_flash_status Flash_EraseBanks(Fapi_FlashBankType oNewFlashBank)
{
int num = 0;
Fapi_StatusType oReturnCheck = Fapi_Status_Success;
num = find_sector(oNewFlashBank, 0);
oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作
if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
{
oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank); //设置活动的Flash Bank
if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) )
oReturnCheck = Fapi_enableMainBankSectors( 0xffffffff ); //设置EEPROM存储区中可用的扇区以进行擦除和编程
else if( oNewFlashBank == Fapi_FlashBank7 )
oReturnCheck = Fapi_enableEepromBankSectors(0xffffffff, 0xffffffff); //设置EEPROM存储区中可用的扇区以进行擦除和编程
while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
Fapi_issueAsyncCommandWithAddress(Fapi_EraseBank, gSector_List[num].low_addr); //向Flash状态机发出命令
/* Place specific example code here */
/* Wait for FSM to finish */
while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
/* Check the FSM Status to see if there were no errors */
if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
{
/* Put Error handling code here */
return flash_failure;
}
}
return flash_succeed;
}
/* @brief 写扇区数据
* @param[in] oNewFlashBank:块编号
* @param[in] sector:扇区编号
* @param[in] offset:扇区偏移地址
* @param[in] buff:数据
* @param[in] len:数据长度
*
* return:
*/
enum e_flash_status Flash_WriteData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len)
{
int num = 0;
Fapi_StatusType oReturnCheck = Fapi_Status_Success;
num = find_sector(oNewFlashBank, sector);
//如果写的大小起过扇区的大小
if( (offset+len) > gSector_List[num].size )
{
return flash_failure;
}
oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作
if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
{
oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank); //设置活动的Flash Bank
if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) )
oReturnCheck = Fapi_enableMainBankSectors( 1<<sector ); //设置EEPROM存储区中可用的扇区以进行擦除和编程
else if( oNewFlashBank == Fapi_FlashBank7 )
oReturnCheck = Fapi_enableEepromBankSectors(1<<sector ,1<<(sector%32)); //设置EEPROM存储区中可用的扇区以进行擦除和编程
while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
Fapi_issueProgrammingCommand(gSector_List[num].low_addr+offset, buff, len, 0, 0, Fapi_DataOnly); //设置数据并将程序命令发送到有效的闪存地址
/* Place specific example code here */
/* Wait for FSM to finish */
while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
/* Check the FSM Status to see if there were no errors */
if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
{
/* Put Error handling code here */
return flash_failure;
}
}
return flash_succeed;
}
/* @brief 读扇区数据
* @param[in] oNewFlashBank:块编号
* @param[in] sector:扇区编号
* @param[in] offset:扇区偏移地址
* @param[in] buff:数据
* @param[in] len:数据长度
*
* return:
*/
void Flash_ReadData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len)
{
int num = 0;
num = find_sector(oNewFlashBank, sector);
//如果读的大小超过扇区的大小
if( (offset+len) > gSector_List[num].size )
{
return flash_failure;
}
memcpy(buff, gSector_List[num].low_addr+offset, len);
}
/* USER CODE BEGIN (0) */
#include "sys_common.h"
#include "gio.h"
#include "rti.h"
#include "delay.h"
#include "het.h"
#include "pinmux.h"
#include "F021.h"
/* USER CODE END */
/* Include Files */
#include "sys_common.h"
/* USER CODE BEGIN (1) */
/* USER CODE END */
/** @fn void main(void)
* @brief Application main function
* @note This function is empty by default.
*
* This function is called after startup.
* The user can use this function to implement the application.
*/
/* USER CODE BEGIN (2) */
uint32 g_ulTransferAddress;
uint8 flash_write_buf0[10] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x10};
uint8 flash_write_buf1[10] = {0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x10};
uint8 flash_write_buf2[10] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x10};
uint8 flash_write_buf3[10] = {0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x10};
uint8 flash_read_buf[10];
/* USER CODE END */
uint8 emacAddress[6U] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
uint32 emacPhyAddress = 1U;
int main(void)
{
/* USER CODE BEGIN (3) */
int i = 0;
gioInit();
muxInit();
rtiInit();
/* Set high end timer GIO port hetPort pin direction to all output */
gioSetDirection(hetPORT1, 0xFFFFFFFF);
/* Enable RTI Compare 0 interrupt notification */
rtiEnableNotification(rtiNOTIFICATION_COMPARE0);
/* Enable IRQ - Clear I flag in CPS register */
/* Note: This is usually done by the OS or in an svc dispatcher */
_enable_IRQ();
/* Start RTI Counter Block 0 */
rtiStartCounter(rtiCOUNTER_BLOCK0);
printf("ENDIAN_REG = %x\n", ENDIAN_REG);
//擦除整个块
Flash_EraseBanks(Fapi_FlashBank7);
//读数据,这时读出来的全是FF
Flash_ReadData(Fapi_FlashBank7, 0, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 1, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 2, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 3, 0, flash_read_buf, 10);
//向4个扇区写不同的数据
Flash_WriteData(Fapi_FlashBank7, 0, 0, flash_write_buf0, 10);
Flash_WriteData(Fapi_FlashBank7, 1, 0, flash_write_buf1, 10);
Flash_WriteData(Fapi_FlashBank7, 2, 0, flash_write_buf2, 10);
Flash_WriteData(Fapi_FlashBank7, 3, 0, flash_write_buf3, 10);
//读数据,这时读出来的是刚才写入的数据
Flash_ReadData(Fapi_FlashBank7, 0, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 1, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 2, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 3, 0, flash_read_buf, 10);
//擦除整个块
Flash_EraseBanks(Fapi_FlashBank7);
//读数据,这时读出来的全是FF
Flash_ReadData(Fapi_FlashBank7, 0, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 1, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 2, 0, flash_read_buf, 10);
Flash_ReadData(Fapi_FlashBank7, 3, 0, flash_read_buf, 10);
while(1)
{
}
/* USER CODE END */
return 0;
}
/* USER CODE BEGIN (4) */
/* Note-You need to remove rtiNotification from notification.c to avoid redefinition */
void rtiNotification(uint32 notification)
{
/* enter user code between the USER CODE BEGIN and USER CODE END. */
/* Toggle HET pin 5 */
gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<5));
}
/* USER CODE END */
Verify that the read, write and erase operations are effective in sys_main.c
1. Erase Fapi_FlashBank7 first
2. Then read the 4 sectors of Fapi_FlashBank7, and all the reads should be FF
3. Then write different data to the 4 sectors of Fapi_FlashBank7
4. Read the 4 sectors of Fapi_FlashBank7 again, and read out the data that should have been written just now
5. Erase Fapi_FlashBank7 again
6. Read the 4 sectors of Fapi_FlashBank7 again, and all the reads should be FF
The above proves that flash reading, writing and erasing are normal
This content is originally created by Shi Yu , a user of EEWORLD forum. If you want to reprint or use it for commercial purposes, you need to obtain the author's consent and indicate the source