arduino_midi_player/Midi/music-box-nv32-master/nv32lib/drivers/nvm/flash.c
2025-03-24 14:30:56 +08:00

318 lines
8.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* 技术讨论QQ群 123763203
* 官网 www.navota.com
*
* @file flash.c
* @brief flash函数库
* @author Navota
* @date 2018-6-19
*/
#include "flash.h"
#define FLASH_ENABLE_STALLING_FLASH_CONTROLLER
/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: Flash_Init
*
* @brief 初始化FLASH
*
* @param
*
* @return none
*
*****************************************************************************/
uint16_t Flash_Init(void)
{
uint16_t err = FLASH_ERR_SUCCESS;
uint32_t clkDIV = BUS_CLK_HZ/1000000L - 1;
uint32_t Tpgs =(285 *(BUS_CLK_HZ/100))/1000000L; //update 2016.8.4 by 光脚板のGG
uint32_t Tprog =(675*(BUS_CLK_HZ/100))/1000000L; //by 光脚板のGG
EFMCR=(clkDIV<<24) + 0x00000001; //divide to 1M hz
EFMETM0=(Tpgs<<16) + 0x00001194; //0x00281194; //
EFMETM1=(Tprog<<16) + 0x000088B8; //
return(err);
}
/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: FlashProgram
*
* @brief flash加载编程总的过程就是给出字节长度先写入满足两个字的个数
* 再写入剩余满足一个字的个数,最后写入剩余的字节数。
*
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
* @param[in] *pData 所要存放的数据
* @param[in] sizeBytes 字节长度
*
* @return none
*
*****************************************************************************/
__ramfunc uint16_t Flash_Program(uint32_t wNVMTargetAddress, uint8_t *pData, uint16_t sizeBytes)
{
uint16_t err = FLASH_ERR_SUCCESS;
uint16_t w2LongWordCount = sizeBytes>>3;//处理一下得到2个字的个数
uint8_t wLeftBytes = (sizeBytes & 0x07);//低位三个字节的个数
uint16_t wLeftLongWords = wLeftBytes>>2;//低位中满一个字个数
uint32_t wTargetAddress = wNVMTargetAddress;
uint32_t dwData0,dwData1;
uint32_t *pdwData = (uint32_t*)pData;//传参
int i;
//判断是否字对齐
if(wNVMTargetAddress & 0x03)
{
err = FLASH_ERR_INVALID_PARAM;
return (err);//返回无效的参数
}
//循环写入两个长字即8个字节共写入w2LongWordCount * 8个字节
for(i = 0; i < w2LongWordCount; i++)
{
dwData0 = *pdwData++;
dwData1 = *pdwData++;
err = Flash_Program2LongWords(wTargetAddress, dwData0, dwData1);//加载两个字的编程
if(err) //地址不为4个字节对齐则直接跳转
{
goto EndP;
//break;
}
wTargetAddress += 8;//循环一次写入8个字节即2个字NV32的flash是字对齐的
}
// 一个字的编程即4bytes
for(i = 0; i < wLeftLongWords; i++)
{
dwData0 = *pdwData++;
err = Flash_Program1LongWord(wTargetAddress, dwData0);
if(err)
{
goto EndP;
//break;
}
wTargetAddress += 4;
}
wLeftBytes = (wLeftBytes-(wLeftLongWords<<2)); //在两字和一字的编程都处理完后剩余的低两位字节数
if(!wLeftBytes){ //若无剩余字节数,返回成功
return (err);
}
#if defined(BIG_ENDIAN)
dwData0 = 0;
pData = (uint8_t*)pdwData;
for(i = wLeftBytes; i >0; i--)
{
dwData0 <<= 8;
dwData0 |= *pData++;
}
wLeftBytes = 4 - wLeftBytes;
for(i = wLeftBytes; i >0; i--)
{
dwData0 <<= 8;
dwData0 |= 0xFF;
}
#else
dwData0 = 0xFFFFFFFFL;
pData = (uint8_t*)pdwData+wLeftBytes-1;
for(i = wLeftBytes; i >0; i--)
{
dwData0 <<= 8;
dwData0 |= *pData--;
}
#endif
err = Flash_Program1LongWord(wTargetAddress, dwData0);
EndP:
return (err);
}
/*****************************************************************************//*!
* @function name: FlashProgram1LongWord
*
* @brief 加载一个字的大小编程到FLASH中(也就是四个字节)
*
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
* @param[in] dwData 所要存放的数据
*
* @return none
*
*****************************************************************************/
__ramfunc uint16_t Flash_Program1LongWord(uint32_t wNVMTargetAddress, uint32_t dwData)
{
uint16_t err = FLASH_ERR_SUCCESS;
//判断是否为字对齐
if(wNVMTargetAddress & 0x03)
{
err = FLASH_ERR_INVALID_PARAM;
return (err);
}
// 清除错误标志
EFMCMD = FLASH_CMD_CLEAR;
//写入数据到对应的地址中
DisableInterrupts;
M32(wNVMTargetAddress) = dwData;
//加载编程命令
EFM_LaunchCMD(FLASH_CMD_PROGRAM);
EnableInterrupts;
return (err);//返回状态
}
/*****************************************************************************//*!
* @function name: FlashProgram2LongWords
*
* @brief 加载两个字的大小编程到FLASH中(也就是八个字节)
*
* @param[in] wNVMTargetAddress 所要存放的FLASH首地址
* @param[in] dwData0 低4个字节
* @param[in] dwData1 高4个字节
*
* @return none
*
*****************************************************************************/
__ramfunc uint16_t Flash_Program2LongWords(uint32_t wNVMTargetAddress, uint32_t dwData0, uint32_t dwData1)
{
uint16_t err = FLASH_ERR_SUCCESS;
//判断是否为字对齐
if(wNVMTargetAddress & 0x03)
{
err = FLASH_ERR_INVALID_PARAM;
return (err);
}
// 清除错误标志
EFMCMD = FLASH_CMD_CLEAR;
DisableInterrupts;
M32(wNVMTargetAddress) = dwData0;//存放数据到以目标地址为起始的4个字节的空间中
EFM_LaunchCMD(FLASH_CMD_PROGRAM);//0x20000000,加载编程命令
EnableInterrupts;
wNVMTargetAddress = wNVMTargetAddress +4;//地址是字对齐的,地址向后移一个字
EFMCMD = FLASH_CMD_CLEAR;
DisableInterrupts;
M32(wNVMTargetAddress) = dwData1;//第二个数据放入处理后的地址的4个字节的空间中
EFM_LaunchCMD(FLASH_CMD_PROGRAM);//加载编程命令
EnableInterrupts;
return (err);//返回处理状态
}
/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: Flash_EraseSector
*
* @brief 擦除目标地址的一个扇区512字节,.
*
* @param[in] wNVMTargetAddress 擦除扇区的首地址
*
* @return none
*
*****************************************************************************/
__ramfunc uint16_t Flash_EraseSector(uint32_t wNVMTargetAddress)
{
uint16_t err = FLASH_ERR_SUCCESS;
// 判断是否字对齐
if(wNVMTargetAddress & 0x03)
{
err = FLASH_ERR_INVALID_PARAM;
return (err);
}
// 清除错误标志
EFMCMD = FLASH_CMD_CLEAR;
DisableInterrupts;
M32(wNVMTargetAddress) = 0xffffffff;
EFM_LaunchCMD(FLASH_CMD_ERASE_SECTOR);//加载擦除命令
EnableInterrupts;
return (err);
}
__ramfunc uint16_t Flash_VerifyBackdoorKey()
{
uint16_t err = FLASH_ERR_SUCCESS;
// Clear error flags
EFMCMD = FLASH_CMD_CLEAR;
// Write index to specify the command code to be loaded
Custombkd = FLASH_FACTORY_KEY;
return (err);
}
/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: NVM_EraseAll
*
* @brief 整片擦除FLASH(慎用注意0X40E这个地址在调试阶段写入0XFE)
*
* @param
*
* @return none
*
*****************************************************************************/
__ramfunc uint16_t NVM_EraseAll(void)
{
uint16_t err = FLASH_ERR_SUCCESS;
EFMCMD = FLASH_CMD_CLEAR;
EFM_LaunchCMD(FLASH_CMD_ERASE_ALL);
// Clear error flags
return err;
}
/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: NVM_Unsecure
*
* @brief unsecure
*
* @param
*
* @return none
*
*****************************************************************************/
__ramfunc uint16_t NVM_Unsecure(void)
{
uint16_t err = FLASH_ERR_SUCCESS;
return err;
}
/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: EFM_LaunchCMD
*
* @brief 命令加载函数(注此函数须放入SRAM中运行)
*
* @param
*
* @return none
*
*****************************************************************************/
#ifdef IAR
void __ramfunc EFM_LaunchCMD(uint32_t EFM_CMD)
#else
__ramfunc void EFM_LaunchCMD(uint32_t EFM_CMD)
#endif
{
DisableInterrupts;
if((EFMCMD&EFM_DONE_MASK)== EFM_STATUS_READY)
{
EFMCMD = EFM_CMD;
}
while(1)
{
if((EFMCMD&EFM_DONE_MASK) == EFM_STATUS_DONE) break;
}
EnableInterrupts;
}