A module to store data on a fram.

Dependents:   oldheating motorhome heating

Committer:
andrewboyson
Date:
Fri Apr 23 08:20:00 2021 +0000
Revision:
0:e8f4aff306cd
Stores data on the FRAM

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 0:e8f4aff306cd 1 #include <string.h>
andrewboyson 0:e8f4aff306cd 2 #include <stdbool.h>
andrewboyson 0:e8f4aff306cd 3
andrewboyson 0:e8f4aff306cd 4 #include "spi.h"
andrewboyson 0:e8f4aff306cd 5 #include "log.h"
andrewboyson 0:e8f4aff306cd 6 #include "fram.h"
andrewboyson 0:e8f4aff306cd 7
andrewboyson 0:e8f4aff306cd 8 #define WREN 0x06 // Set Write Enable Latch 0000 0110B
andrewboyson 0:e8f4aff306cd 9 #define WRDI 0x04 // Reset Write Enable Latch 0000 0100B
andrewboyson 0:e8f4aff306cd 10 #define RDSR 0x05 // Read Status Register 0000 0101B
andrewboyson 0:e8f4aff306cd 11 #define WRSR 0x01 // Write Status Register 0000 0001B
andrewboyson 0:e8f4aff306cd 12 #define READ 0x03 // Read Memory Code 0000 0011B
andrewboyson 0:e8f4aff306cd 13 #define WRITE 0x02 // Write Memory Code 0000 0010B
andrewboyson 0:e8f4aff306cd 14 #define RDID 0x9F // Read Device ID 1001 1111B
andrewboyson 0:e8f4aff306cd 15
andrewboyson 0:e8f4aff306cd 16 #define FRAM_ID 0x047f0302
andrewboyson 0:e8f4aff306cd 17 #define FRAM_MAGIC 42 //Magic number to show that the FRAM has been intialised
andrewboyson 0:e8f4aff306cd 18
andrewboyson 0:e8f4aff306cd 19 bool FramEmpty; //Set in FramInit
andrewboyson 0:e8f4aff306cd 20 int FramUsed; //Initialised in FramInit and used by FramAllocate to remember the next available location
andrewboyson 0:e8f4aff306cd 21
andrewboyson 0:e8f4aff306cd 22 int FramAllocate(int size) //Allocates a number of bytes in FRAM
andrewboyson 0:e8f4aff306cd 23 {
andrewboyson 0:e8f4aff306cd 24 int start = FramUsed;
andrewboyson 0:e8f4aff306cd 25 int used = FramUsed + size;
andrewboyson 0:e8f4aff306cd 26 if (used > FRAM_SIZE - 1)
andrewboyson 0:e8f4aff306cd 27 {
andrewboyson 0:e8f4aff306cd 28 Log("FramAllocate - No more room in FRAM\r\n");
andrewboyson 0:e8f4aff306cd 29 return -1;
andrewboyson 0:e8f4aff306cd 30 }
andrewboyson 0:e8f4aff306cd 31 FramUsed = used;
andrewboyson 0:e8f4aff306cd 32 return start;
andrewboyson 0:e8f4aff306cd 33 }
andrewboyson 0:e8f4aff306cd 34 int FramInit()
andrewboyson 0:e8f4aff306cd 35 {
andrewboyson 0:e8f4aff306cd 36 //Configure SPI
andrewboyson 0:e8f4aff306cd 37 SpiInit();
andrewboyson 0:e8f4aff306cd 38
andrewboyson 0:e8f4aff306cd 39 //Check if the FRAM is connected and working properly
andrewboyson 0:e8f4aff306cd 40 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 41 SpiTransfer(RDID);
andrewboyson 0:e8f4aff306cd 42 int id = 0;
andrewboyson 0:e8f4aff306cd 43 id = (id << 8) + SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 44 id = (id << 8) + SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 45 id = (id << 8) + SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 46 id = (id << 8) + SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 47 SpiChipSelect(1);
andrewboyson 0:e8f4aff306cd 48 if (id != FRAM_ID)
andrewboyson 0:e8f4aff306cd 49 {
andrewboyson 0:e8f4aff306cd 50 LogF("FramInit - Expected FRAM id %08x but got %08x\r\n", FRAM_ID, id);
andrewboyson 0:e8f4aff306cd 51 return -1;
andrewboyson 0:e8f4aff306cd 52 }
andrewboyson 0:e8f4aff306cd 53
andrewboyson 0:e8f4aff306cd 54 //Check the first byte to see if the FRAM is initialised and zero if not
andrewboyson 0:e8f4aff306cd 55 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 56 SpiTransfer(READ);
andrewboyson 0:e8f4aff306cd 57 SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 58 SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 59 char magic = SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 60 SpiChipSelect(1);
andrewboyson 0:e8f4aff306cd 61 FramEmpty = magic != FRAM_MAGIC;
andrewboyson 0:e8f4aff306cd 62 if (FramEmpty)
andrewboyson 0:e8f4aff306cd 63 {
andrewboyson 0:e8f4aff306cd 64 LogF("FramInit - Byte 0 value %d is not the magic value %d so initialising FRAM to zero\r\n", magic, FRAM_MAGIC);
andrewboyson 0:e8f4aff306cd 65 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 66 SpiTransfer(WREN);
andrewboyson 0:e8f4aff306cd 67 SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1); SpiChipSelect(1);
andrewboyson 0:e8f4aff306cd 68 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 69 SpiTransfer(WRITE);
andrewboyson 0:e8f4aff306cd 70 SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 71 SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 72 SpiTransfer(FRAM_MAGIC); //Set the magic number in byte 0
andrewboyson 0:e8f4aff306cd 73 for(int i = 1; i < FRAM_SIZE; i++) SpiTransfer(0); //Zero all other locations
andrewboyson 0:e8f4aff306cd 74 SpiChipSelect(1);
andrewboyson 0:e8f4aff306cd 75 }
andrewboyson 0:e8f4aff306cd 76 FramUsed = 1; //Set the next available location to one past the byte used for the magic number
andrewboyson 0:e8f4aff306cd 77 return 0;
andrewboyson 0:e8f4aff306cd 78 }
andrewboyson 0:e8f4aff306cd 79 void FramWrite(int address, int len, void* pVoid)
andrewboyson 0:e8f4aff306cd 80 {
andrewboyson 0:e8f4aff306cd 81 if (address + len > FRAM_SIZE - 1 || address < 0)
andrewboyson 0:e8f4aff306cd 82 {
andrewboyson 0:e8f4aff306cd 83 Log("FramWrite - Invalid FRAM address\r\n");
andrewboyson 0:e8f4aff306cd 84 return;
andrewboyson 0:e8f4aff306cd 85 }
andrewboyson 0:e8f4aff306cd 86 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 87 SpiTransfer(WREN);
andrewboyson 0:e8f4aff306cd 88 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
andrewboyson 0:e8f4aff306cd 89 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 90 SpiTransfer(WRITE);
andrewboyson 0:e8f4aff306cd 91 SpiTransfer(address >> 8);
andrewboyson 0:e8f4aff306cd 92 SpiTransfer(address & 0xFF);
andrewboyson 0:e8f4aff306cd 93 char* p = (char*)pVoid;
andrewboyson 0:e8f4aff306cd 94 for (int i = 0; i < len; i++) SpiTransfer(*p++);
andrewboyson 0:e8f4aff306cd 95 SpiChipSelect(1);
andrewboyson 0:e8f4aff306cd 96 }
andrewboyson 0:e8f4aff306cd 97 void FramRead(int address, int len, void* pVoid)
andrewboyson 0:e8f4aff306cd 98 {
andrewboyson 0:e8f4aff306cd 99 if (address + len > FRAM_SIZE - 1 || address < 0)
andrewboyson 0:e8f4aff306cd 100 {
andrewboyson 0:e8f4aff306cd 101 Log("FramRead - Invalid FRAM address\r\n");
andrewboyson 0:e8f4aff306cd 102 return;
andrewboyson 0:e8f4aff306cd 103 }
andrewboyson 0:e8f4aff306cd 104 SpiChipSelect(0);
andrewboyson 0:e8f4aff306cd 105 SpiTransfer(READ);
andrewboyson 0:e8f4aff306cd 106 SpiTransfer(address >> 8);
andrewboyson 0:e8f4aff306cd 107 SpiTransfer(address & 0xFF);
andrewboyson 0:e8f4aff306cd 108 char* p = (char*)pVoid;
andrewboyson 0:e8f4aff306cd 109 for (int i = 0; i < len; i++) *p++ = SpiTransfer(0);
andrewboyson 0:e8f4aff306cd 110 SpiChipSelect(1);
andrewboyson 0:e8f4aff306cd 111 }
andrewboyson 0:e8f4aff306cd 112
andrewboyson 0:e8f4aff306cd 113 int FramLoad(int len, void* pValue, void* pDefault)
andrewboyson 0:e8f4aff306cd 114 {
andrewboyson 0:e8f4aff306cd 115 int address = FramAllocate(len);
andrewboyson 0:e8f4aff306cd 116 if (address >= 0)
andrewboyson 0:e8f4aff306cd 117 {
andrewboyson 0:e8f4aff306cd 118 if (FramEmpty)
andrewboyson 0:e8f4aff306cd 119 {
andrewboyson 0:e8f4aff306cd 120 if (pDefault)
andrewboyson 0:e8f4aff306cd 121 {
andrewboyson 0:e8f4aff306cd 122 int defaultHasContent = 0;
andrewboyson 0:e8f4aff306cd 123 char* pFrom = (char*)pDefault;
andrewboyson 0:e8f4aff306cd 124 char* pTo = (char*)pValue;
andrewboyson 0:e8f4aff306cd 125 for (int i = 0; i < len; i++)
andrewboyson 0:e8f4aff306cd 126 {
andrewboyson 0:e8f4aff306cd 127 if (*pFrom) defaultHasContent = 1;
andrewboyson 0:e8f4aff306cd 128 *pTo++ = *pFrom++;
andrewboyson 0:e8f4aff306cd 129 }
andrewboyson 0:e8f4aff306cd 130 if (defaultHasContent) FramWrite(address, len, pValue);
andrewboyson 0:e8f4aff306cd 131 }
andrewboyson 0:e8f4aff306cd 132 else //pDefault is NULL so zero the setting
andrewboyson 0:e8f4aff306cd 133 {
andrewboyson 0:e8f4aff306cd 134 memset(pValue, 0, len);
andrewboyson 0:e8f4aff306cd 135 }
andrewboyson 0:e8f4aff306cd 136 }
andrewboyson 0:e8f4aff306cd 137 else
andrewboyson 0:e8f4aff306cd 138 {
andrewboyson 0:e8f4aff306cd 139 FramRead(address, len, pValue);
andrewboyson 0:e8f4aff306cd 140 }
andrewboyson 0:e8f4aff306cd 141 }
andrewboyson 0:e8f4aff306cd 142 return address;
andrewboyson 0:e8f4aff306cd 143 }