A module to store data on a fram.
Dependents: oldheating motorhome heating
Revision 0:e8f4aff306cd, committed 2021-04-23
- Comitter:
- andrewboyson
- Date:
- Fri Apr 23 08:20:00 2021 +0000
- Commit message:
- Stores data on the FRAM
Changed in this revision
diff -r 000000000000 -r e8f4aff306cd fram.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fram.c Fri Apr 23 08:20:00 2021 +0000 @@ -0,0 +1,143 @@ +#include <string.h> +#include <stdbool.h> + +#include "spi.h" +#include "log.h" +#include "fram.h" + +#define WREN 0x06 // Set Write Enable Latch 0000 0110B +#define WRDI 0x04 // Reset Write Enable Latch 0000 0100B +#define RDSR 0x05 // Read Status Register 0000 0101B +#define WRSR 0x01 // Write Status Register 0000 0001B +#define READ 0x03 // Read Memory Code 0000 0011B +#define WRITE 0x02 // Write Memory Code 0000 0010B +#define RDID 0x9F // Read Device ID 1001 1111B + +#define FRAM_ID 0x047f0302 +#define FRAM_MAGIC 42 //Magic number to show that the FRAM has been intialised + +bool FramEmpty; //Set in FramInit +int FramUsed; //Initialised in FramInit and used by FramAllocate to remember the next available location + +int FramAllocate(int size) //Allocates a number of bytes in FRAM +{ + int start = FramUsed; + int used = FramUsed + size; + if (used > FRAM_SIZE - 1) + { + Log("FramAllocate - No more room in FRAM\r\n"); + return -1; + } + FramUsed = used; + return start; +} +int FramInit() +{ + //Configure SPI + SpiInit(); + + //Check if the FRAM is connected and working properly + SpiChipSelect(0); + SpiTransfer(RDID); + int id = 0; + id = (id << 8) + SpiTransfer(0); + id = (id << 8) + SpiTransfer(0); + id = (id << 8) + SpiTransfer(0); + id = (id << 8) + SpiTransfer(0); + SpiChipSelect(1); + if (id != FRAM_ID) + { + LogF("FramInit - Expected FRAM id %08x but got %08x\r\n", FRAM_ID, id); + return -1; + } + + //Check the first byte to see if the FRAM is initialised and zero if not + SpiChipSelect(0); + SpiTransfer(READ); + SpiTransfer(0); + SpiTransfer(0); + char magic = SpiTransfer(0); + SpiChipSelect(1); + FramEmpty = magic != FRAM_MAGIC; + if (FramEmpty) + { + LogF("FramInit - Byte 0 value %d is not the magic value %d so initialising FRAM to zero\r\n", magic, FRAM_MAGIC); + SpiChipSelect(0); + SpiTransfer(WREN); + SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); + SpiChipSelect(0); + SpiTransfer(WRITE); + SpiTransfer(0); + SpiTransfer(0); + SpiTransfer(FRAM_MAGIC); //Set the magic number in byte 0 + for(int i = 1; i < FRAM_SIZE; i++) SpiTransfer(0); //Zero all other locations + SpiChipSelect(1); + } + FramUsed = 1; //Set the next available location to one past the byte used for the magic number + return 0; +} +void FramWrite(int address, int len, void* pVoid) +{ + if (address + len > FRAM_SIZE - 1 || address < 0) + { + Log("FramWrite - Invalid FRAM address\r\n"); + return; + } + SpiChipSelect(0); + SpiTransfer(WREN); + SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); //Deselect must be at least 60ns. One operation at 96MHz is about 10ns + SpiChipSelect(0); + SpiTransfer(WRITE); + SpiTransfer(address >> 8); + SpiTransfer(address & 0xFF); + char* p = (char*)pVoid; + for (int i = 0; i < len; i++) SpiTransfer(*p++); + SpiChipSelect(1); +} +void FramRead(int address, int len, void* pVoid) +{ + if (address + len > FRAM_SIZE - 1 || address < 0) + { + Log("FramRead - Invalid FRAM address\r\n"); + return; + } + SpiChipSelect(0); + SpiTransfer(READ); + SpiTransfer(address >> 8); + SpiTransfer(address & 0xFF); + char* p = (char*)pVoid; + for (int i = 0; i < len; i++) *p++ = SpiTransfer(0); + SpiChipSelect(1); +} + +int FramLoad(int len, void* pValue, void* pDefault) +{ + int address = FramAllocate(len); + if (address >= 0) + { + if (FramEmpty) + { + if (pDefault) + { + int defaultHasContent = 0; + char* pFrom = (char*)pDefault; + char* pTo = (char*)pValue; + for (int i = 0; i < len; i++) + { + if (*pFrom) defaultHasContent = 1; + *pTo++ = *pFrom++; + } + if (defaultHasContent) FramWrite(address, len, pValue); + } + else //pDefault is NULL so zero the setting + { + memset(pValue, 0, len); + } + } + else + { + FramRead(address, len, pValue); + } + } + return address; +}
diff -r 000000000000 -r e8f4aff306cd fram.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fram.h Fri Apr 23 08:20:00 2021 +0000 @@ -0,0 +1,11 @@ +#include <stdbool.h> + +extern bool FramEmpty; +extern int FramUsed; +extern int FramInit(void); +extern int FramAllocate(int size); +extern void FramWrite(int address, int len, void* pVoid); +extern void FramRead (int address, int len, void* pVoid); +extern int FramLoad (int len, void* pValue, void* pDefault); + +#define FRAM_SIZE 8192
diff -r 000000000000 -r e8f4aff306cd spi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spi.c Fri Apr 23 08:20:00 2021 +0000 @@ -0,0 +1,55 @@ +#include "gpio.h" +#include "log.h" + +#define CS_DIR FIO0DIR(6) +#define CS_SET FIO0SET(6) +#define CS_CLR FIO0CLR(6) + +//SSP1 +#define CR0 (*((volatile unsigned *) 0x40030000)) +#define CR1 (*((volatile unsigned *) 0x40030004)) +#define DR (*((volatile unsigned *) 0x40030008)) +#define SR (*((volatile unsigned *) 0x4003000C)) +#define CPSR (*((volatile unsigned *) 0x40030010)) + +void SpiInit(void) +{ + //Configure + CR0 |= 7 << 0; //3:0 8 bit transfer + CR0 |= 0 << 4; //5:4 SPI + CR0 |= 0 << 6; //7:6 Mode 0 + CR0 |= 0 << 8; //divide by 1 + + //Set prescaler bps = PCLK / PS ==> PS = PCLK / bps ==> PS = 96/16 = 6 + CPSR = 6; //Bit 0 must be 0. 6 ==> 16 bps which is within the 20MHz allowed by the FRAM + + //Select the function of the ssel pin: P0.6 + CS_SET; //Deselect the output == CS = 1 + CS_DIR = 1; //Set the direction to 1 == output + + //Enable operation + CR1 |= 2; //Enable the SSP controller +} +void SpiChipSelect(int value) +{ + if (value) CS_SET; + else CS_CLR; +} +void SpiWrite(char byte) +{ + DR = byte; //This loads the next frame in the TX FIFO +} +int SpiBusy(void) +{ + return SR & 0x10; //bit 4 is BSY. This bit is 0 if the SSPn controller is idle, or 1 if it is currently sending/receiving a frame and/or the Tx FIFO is not empty. +} +char SpiRead(void) +{ + return DR & 0xFF; //This reads the oldest frame in the RX FIFO +} +char SpiTransfer(char byte) +{ + SpiWrite(byte); + while(SpiBusy()) /*spin until not busy, at 16 bits per us or 2 bytes per us should be only 48 operations*/; + return SpiRead(); +}
diff -r 000000000000 -r e8f4aff306cd spi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spi.h Fri Apr 23 08:20:00 2021 +0000 @@ -0,0 +1,6 @@ +extern void SpiInit(void); +extern void SpiChipSelect(int value); +extern void SpiWrite(char byte); +extern int SpiBusy(void); +extern char SpiRead(void); +extern char SpiTransfer(char byte); \ No newline at end of file