362 lines
8.5 KiB
C
362 lines
8.5 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* IAR Development Kits
|
||
* on the
|
||
*
|
||
* M451
|
||
*
|
||
* Filename : spi_fram.c
|
||
* Version : V1.00
|
||
* Programmer(s) : Qian Xianghong
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#include "includes.h"
|
||
|
||
// 铁电操作命令码
|
||
#define FRAM_OP_WREN 0x06 // Set write enable latch
|
||
#define FRAM_OP_WRDI 0x04 // Reset write enable latch
|
||
#define FRAM_OP_RDSR 0x05 // Read Status Register
|
||
#define FRAM_OP_WRSR 0x01 // Write Status Register
|
||
#define FRAM_OP_READ 0x03 // Read memory data
|
||
#define FRAM_OP_FSTRD 0x0B // Fast read memory data
|
||
#define FRAM_OP_WRITE 0x02 // Write memory data
|
||
#define FRAM_OP_SLEEP 0xB9 // Enter sleep mode
|
||
#define FRAM_OP_RDID 0x9F // Read device ID
|
||
|
||
// 铁电状态寄存器(SR)写允许(WEL)标志位
|
||
#define FRAM_WEL_Pos 1
|
||
#define FRAM_WEL_Msk (0x01 << FRAM_WEL_Pos)
|
||
|
||
void FRAM_Init()
|
||
{
|
||
/* Set SPI0 multi-function pins */
|
||
/* Set SPI1 multi-function pins */
|
||
SYS->PE_L_MFP &= ~(SYS_PE_L_MFP_PE1_MFP_Msk | SYS_PE_L_MFP_PE2_MFP_Msk | SYS_PE_L_MFP_PE3_MFP_Msk | SYS_PE_L_MFP_PE4_MFP_Msk);
|
||
SYS->PE_L_MFP |= (SYS_PE_L_MFP_PE1_MFP_SPI0_SS0 | SYS_PE_L_MFP_PE2_MFP_SPI0_SCLK | SYS_PE_L_MFP_PE3_MFP_SPI0_MISO0 | SYS_PE_L_MFP_PE4_MFP_SPI0_MOSI0);
|
||
|
||
// 允许外设时钟
|
||
CLK_EnableModuleClock(SPI0_MODULE);
|
||
}
|
||
|
||
void FRAM_Open()
|
||
{
|
||
/*---------------------------------------------------------------------------------------------------------*/
|
||
/* Init SPI */
|
||
/*---------------------------------------------------------------------------------------------------------*/
|
||
/* Configure SPI0 as a master, SPI clock rate 36 MHz,
|
||
clock idle low, 8-bit transaction, drive output on falling clock edge and latch input on rising edge. */
|
||
SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 8, 36000000ul);
|
||
|
||
/* Disable the automatic hardware slave selection function. */
|
||
SPI_DisableAutoSS(SPI0);
|
||
SPI_SET_MSB_FIRST(SPI0);
|
||
|
||
/* Set TX FIFO threshold, enable TX FIFO threshold interrupt and RX FIFO time-out interrupt */
|
||
SPI_EnableFIFO(SPI0, 1, 1);
|
||
}
|
||
|
||
void FRAM_ReadID()
|
||
{
|
||
uint8_t i;
|
||
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_RDID);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
|
||
printf("\nFRAM ID is: ");
|
||
for(i = 0; i < 9; i++)
|
||
{
|
||
SPI_WRITE_TX0(SPI0, 0); // 提供CLK
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
printf(" %02X", SPI_READ_RX0(SPI0));
|
||
}
|
||
printf("\n");
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
}
|
||
|
||
uint8_t FRAM_WriteEN()
|
||
{
|
||
uint8_t SR = 0x00;
|
||
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
// Write Enabled
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_WREN);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
// Read SR
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_RDSR);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
|
||
SPI_WRITE_TX0(SPI0, 0); // 提供CLK
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SR = SPI_READ_RX0(SPI0);
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
// Check WEL
|
||
if(SR & FRAM_WEL_Msk)
|
||
return 1;
|
||
printf("\nFRam write enable failed\n");
|
||
return 0;
|
||
}
|
||
|
||
uint8_t FRAM_WriteDI()
|
||
{
|
||
uint8_t SR = 0xFF;
|
||
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
// Write Enabled
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_WRDI);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
// Read SR
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_RDSR);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
|
||
SPI_WRITE_TX0(SPI0, 0); // 提供CLK
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SR = SPI_READ_RX0(SPI0);
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
// Check WEL
|
||
if(SR & FRAM_WEL_Msk)
|
||
{
|
||
printf("\nWrite disable failed\n");
|
||
return 0;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
uint16_t FRAM_BufferWrite(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
uint16_t i;
|
||
|
||
__disable_irq();
|
||
|
||
FRAM_WriteEN();
|
||
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
// Write
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_WRITE);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// address high byte
|
||
SPI_WRITE_TX0(SPI0, Addr >> 8);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// address low byte
|
||
SPI_WRITE_TX0(SPI0, Addr & 0xFF);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// data
|
||
for(i = 0; i < nbytes && Addr + i < FRAM_SIZE; i++)
|
||
{
|
||
SPI_WRITE_TX0(SPI0, buf[i]);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
}
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
__enable_irq();
|
||
|
||
return i;
|
||
}
|
||
|
||
uint16_t FRAM_BufferRead(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
uint16_t i;
|
||
|
||
__disable_irq();
|
||
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
// Read
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_READ);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// address high byte
|
||
SPI_WRITE_TX0(SPI0, Addr >> 8);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// address low byte
|
||
SPI_WRITE_TX0(SPI0, Addr & 0xFF);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// data
|
||
for(i = 0; i < nbytes && Addr + i < FRAM_SIZE; i++)
|
||
{
|
||
SPI_WRITE_TX0(SPI0, 0); // 提供CLK
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
buf[i] = SPI_READ_RX0(SPI0);
|
||
}
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
__enable_irq();
|
||
|
||
return i;
|
||
}
|
||
|
||
uint32_t FRAM_BufferVerify(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
uint32_t ret = TRUE;
|
||
uint16_t i;
|
||
|
||
__disable_irq();
|
||
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
// Read
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_READ);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// address high byte
|
||
SPI_WRITE_TX0(SPI0, Addr >> 8);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// address low byte
|
||
SPI_WRITE_TX0(SPI0, Addr & 0xFF);
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
SPI_READ_RX0(SPI0);
|
||
// data
|
||
for(i = 0; i < nbytes && Addr + i < FRAM_SIZE; i++)
|
||
{
|
||
SPI_WRITE_TX0(SPI0, 0); // 提供CLK
|
||
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
|
||
if(buf[i] != SPI_READ_RX0(SPI0))
|
||
{
|
||
ret = FALSE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
|
||
__enable_irq();
|
||
|
||
return ret;
|
||
}
|
||
|
||
void FRAM_Sleep(uint8_t sleep)
|
||
{
|
||
SPI_SET_SS0_LOW(SPI0);
|
||
|
||
// Chip erase
|
||
if(sleep)
|
||
SPI_WRITE_TX0(SPI0, FRAM_OP_SLEEP);
|
||
else
|
||
SPI_WRITE_TX0(SPI0, 0);
|
||
|
||
SPI_SET_SS0_HIGH(SPI0);
|
||
}
|
||
|
||
// 从FRAM读取记录(前面2个字节为标志0x55AA,最后两个字节为crc)
|
||
uint32_t FRAM_LoadInfo(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
if(FRAM_BufferRead(Addr, buf, nbytes) == nbytes && Byte2IntS(buf, 0) == 0x55AA && do_crc_16(0, buf, nbytes) == 0)
|
||
return 1;
|
||
|
||
memset(buf, 0, nbytes);
|
||
return 0;
|
||
}
|
||
|
||
// 保存记录到FRAM中(前面2个字节为标志0x55AA,最后两个字节为crc)
|
||
uint32_t FRAM_SaveInfo(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
Int2ByteS(buf, 0, 0x55AA);
|
||
Int2ByteS(buf, nbytes - 2, do_crc_16(0, buf, nbytes - 2));
|
||
return (FRAM_BufferWrite(Addr, buf, nbytes) == nbytes);
|
||
}
|
||
|
||
// 循环缓冲实现部分
|
||
|
||
// 因为当读写指针相同表示缓冲区满(浪费了一个数据空间),故需要多分配一个数据空间
|
||
void LoopBuff_Create(loopbuff_t *lpbuf, uint16_t itemSize, uint16_t maxItemCount, uint32_t info_base, uint32_t data_base)
|
||
{
|
||
memset(&lpbuf->info, 0, sizeof(loopbuff_info_t));
|
||
lpbuf->itemSize = itemSize;
|
||
lpbuf->maxItemCount = maxItemCount;
|
||
lpbuf->info_base = info_base;
|
||
|
||
// if(info_base == 0) // 分配扩展内存
|
||
// lpbuf->data = SRAM_Alloc(itemSize * (maxItemCount + 1));
|
||
// else // 记录铁电或系统内存位置
|
||
lpbuf->data_base = data_base;
|
||
}
|
||
|
||
void LoopBuff_Clear(loopbuff_t *lpbuf)
|
||
{
|
||
lpbuf->info.rdPtr = lpbuf->info.wtPtr;
|
||
}
|
||
|
||
uint16_t LoopBuff_GetCount(loopbuff_t *lpbuf)
|
||
{
|
||
if(lpbuf->info.rdPtr <= lpbuf->info.wtPtr)
|
||
return lpbuf->info.wtPtr - lpbuf->info.rdPtr;
|
||
return (lpbuf->maxItemCount + 1) - lpbuf->info.rdPtr + lpbuf->info.wtPtr;
|
||
}
|
||
|
||
uint16_t LoopBuff_GetNextPtr(loopbuff_t *lpbuf, uint16_t ptr)
|
||
{
|
||
if(ptr == lpbuf->maxItemCount)
|
||
return 0;
|
||
return (ptr + 1);
|
||
}
|
||
|
||
void LoopBuff_PutItem(loopbuff_t *lpbuf, uint8_t *item)
|
||
{
|
||
uint16_t nextPtr;
|
||
|
||
// 移动写指针
|
||
nextPtr = LoopBuff_GetNextPtr(lpbuf, lpbuf->info.wtPtr);
|
||
|
||
// 如果队列未满
|
||
if(nextPtr != lpbuf->info.rdPtr)
|
||
{
|
||
// 将新数据加到最后
|
||
memmove(lpbuf->data + lpbuf->info.wtPtr * lpbuf->itemSize, item, lpbuf->itemSize);
|
||
lpbuf->info.wtPtr = nextPtr;
|
||
}
|
||
else
|
||
{
|
||
// 如果队列已满,则丢弃最新数据
|
||
}
|
||
}
|
||
|
||
void LoopBuff_RemoveItems(loopbuff_t *lpbuf, uint16_t count)
|
||
{
|
||
while(lpbuf->info.rdPtr != lpbuf->info.wtPtr && count--)
|
||
lpbuf->info.rdPtr = LoopBuff_GetNextPtr(lpbuf, lpbuf->info.rdPtr);
|
||
}
|
||
|
||
uint32_t LoopBuff_GetDataPos(loopbuff_t *lpbuf, uint16_t ptr)
|
||
{
|
||
return lpbuf->data_base + lpbuf->itemSize * ptr;
|
||
}
|
||
|
||
uint8_t *LoopBuff_GetDataPtr(loopbuff_t *lpbuf, uint16_t ptr)
|
||
{
|
||
return lpbuf->data + lpbuf->itemSize * ptr;
|
||
}
|