加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
tiny_kvdb_port_hc32f4a0.c 6.60 KB
一键复制 编辑 原始数据 按行查看 历史
/**
*******************************************************************************
* @file tiny_kvdb_port.c
* @brief port functions for tiny kvdb.
*******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "string.h"
#include "hc32_ll.h"
#include "tiny_kvdb.h"
/* Private Defines -----------------------------------------------------------*/
#define SECTOR_MASK (SECTOR_SIZE - 1U)
#define SECTOR_START_ADDR(addr) ((addr) & ~SECTOR_MASK)
#define SECTOR_OF_ADDR(addr) ((addr) / SECTOR_SIZE)
/* Private TypeDefs ----------------------------------------------------------*/
/* Private Macros ------------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
/* Extern Variables ----------------------------------------------------------*/
/* Private FunctionPrototypes ------------------------------------------------*/
/* Extern FunctionPrototypes -------------------------------------------------*/
/* Private Functions ---------------------------------------------------------*/
static uint32_t get_sector_count(uint32_t addr, uint32_t len)
{
uint32_t end_addr = addr + len;
uint32_t start_sector = SECTOR_OF_ADDR(addr);
uint32_t end_sector = SECTOR_OF_ADDR(end_addr);
return end_sector - start_sector + 1;
}
int flash_init (void)
{
return 1;
}
int flash_read (uint32_t addr, void * p_dst, uint32_t len)
{
if ((addr + len) > EFM_END_ADDR)
{
return -1;
}
if (LL_OK != EFM_ReadByte(addr, p_dst, len))
{
return -1;
}
return len;
}
int flash_write (uint32_t addr, void * p_src, uint32_t len)
{
uint32_t data_write;
uint32_t write_addr = addr;
uint32_t remain, offset;
const uint8_t *p = (const uint8_t *)p_src;
int32_t result;
if (p_src == 0 || len == 0)
{
return -1;
}
if ((addr + len) > EFM_END_ADDR)
{
return -1;
}
uint32_t start_sector = SECTOR_OF_ADDR(addr);
uint32_t sector_count = get_sector_count(addr, len);
EFM_REG_Unlock();
EFM_FWMC_Cmd(ENABLE); /* EFM_FWMC write enable */
if (sector_count == 1)
{
EFM_SingleSectorOperateCmd(start_sector, ENABLE);
}
else
{
EFM_SequenceSectorOperateCmd(start_sector, sector_count, ENABLE); /* Disable sector write protection */
}
uint32_t level = __get_PRIMASK();
__set_PRIMASK(1); /* disable irq */
/* dest address is not word-aligned */
if (write_addr & 0x03)
{
uint8_t temp_buf[4] __ALIGNED(4) = {0xFF, 0xFF, 0xFF, 0xFF};
offset = write_addr & 0x03;
remain = 4 - offset;
write_addr = write_addr & 0xFFFFFFFCU;
result = EFM_ReadByte(write_addr, temp_buf, offset);
if (result != LL_OK)
{
goto end;
}
if (len < remain)
{
remain = len;
}
len -= remain;
while (remain)
{
temp_buf[offset] = *p;
offset++;
p++;
remain--;
}
data_write = *(uint32_t *)temp_buf;
result = EFM_ProgramWord(write_addr, data_write);
if (result != LL_OK)
{
goto end;
}
if (len == 0)
{
goto end;
}
write_addr += 4;
}
/* source address is word-aligned */
if (IS_ADDR_ALIGN_WORD(p))
{
result = EFM_SequenceProgram(write_addr, (uint8_t *)p, len);
if(result != LL_OK)
{
goto end;
}
p += len;
}
/* source address is not word-aligned */
else
{
while (len >= 4)
{
data_write = ((uint32_t) *(p + 3) << 24) + ((uint32_t) *(p + 2) << 16) + ((uint32_t) *(p + 1) << 8) + *p;
result = EFM_ProgramWord(write_addr, data_write);
if (result != LL_OK)
{
goto end;
}
write_addr += 4;
len -= 4;
p += 4;
}
if (len != 0)
{
data_write = ((uint32_t) *(p + 3) << 24) + ((uint32_t) *(p + 2) << 16) + ((uint32_t) *(p + 1) << 8) + *p;
data_write |= 0xFFFFFFFFU << (len * 8U);
result = EFM_ProgramWord(write_addr, data_write);
p += len;
}
}
end:
__set_PRIMASK(level); /* __enable_irq */
if (sector_count == 1)
{
EFM_SingleSectorOperateCmd(start_sector, DISABLE);
}
else
{
EFM_SequenceSectorOperateCmd(start_sector, sector_count, DISABLE); /* Enable sector write protection */
}
EFM_FWMC_Cmd(DISABLE); /* EFM_FWMC write disable */
EFM_REG_Lock();
if (result != LL_OK)
return result;
return p - (const uint8_t *)p_src;
}
int flash_erase (uint32_t addr, uint32_t len)
{
int32_t result;
uint32_t end_addr = addr + len;
uint32_t start_sector = SECTOR_OF_ADDR(addr);
uint32_t sector_count = get_sector_count(addr, len);
addr = SECTOR_START_ADDR(addr);
EFM_REG_Unlock();
EFM_FWMC_Cmd(ENABLE); /* EFM_FWMC write enable */
if (sector_count == 1)
{
EFM_SingleSectorOperateCmd(start_sector, ENABLE);
}
else
{
EFM_SequenceSectorOperateCmd(start_sector, sector_count, ENABLE); /* Disable sector write protection */
}
uint32_t level = __get_PRIMASK();
__set_PRIMASK(1); /* disable irq */
while (addr < end_addr)
{
result = EFM_SectorErase(addr);
if (result != LL_OK)
{
goto end;
}
addr += SECTOR_SIZE;
}
end:
__set_PRIMASK(level); /* __enable_irq */
if (sector_count == 1)
{
EFM_SingleSectorOperateCmd(start_sector, DISABLE);
}
else
{
EFM_SequenceSectorOperateCmd(start_sector, sector_count, DISABLE); /* Enable sector write protection */
}
EFM_FWMC_Cmd(DISABLE); /* EFM_FWMC write disable */
EFM_REG_Lock();
if (result != LL_OK)
return result;
return len;
}
tiny_db_device_t hc32f4a0_onchip_flash =
{
.device_id = 0x48433441, /* HC4A */
.start_addr = 1024*1024,
.max_size = 1024*1024,
.sector_size= SECTOR_SIZE,
.write_unit = 4,
.init = flash_init,
.read = flash_read,
.write = flash_write,
.erase = flash_erase
};
/******************************** END OF FILE *********************************/
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化