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