-
Notifications
You must be signed in to change notification settings - Fork 0
/
adesto.c
285 lines (238 loc) · 12.3 KB
/
adesto.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*
* adesto.c
*
* Created on: Aug 19, 2019
* Author: junaidkhan
*/
#include "adesto.h"
#include "utils/uartstdio.h"
/*
* UART Pin Configuration
*
* PA0 -> UART0_RX
* PA1 <- UART0_TX
*/
/*
* Function used for Initializing UART Module 0 for printing Serial Data - for testing the SPI communication
*/
void UART_Init(void)
{
// Enable clock access to the GPIO Peripheral used by the UART - Use GPIO Port A, as we're already using it for SPI com
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// Enable clock access to UART0
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
// Configure GPIO Pins for UART mode.
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// Use the internal 16MHz oscillator as the UART clock source.
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
// Initialize the UART for console I/O.
UARTStdioConfig(0, 9600, 16000000);
}
/*
* This function selects the Adesto External Flash for communication.
*
* @value is used to assert and deassert the CS pin of the external flash.
*
*/
void ChipSelect(uint32_t value)
{
// Set the CS of External Flash; Pin normally HIGH, i.e. PA3 = 1 when not in use.
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, value);
}
/*
* This function is used to read the External Flash's Manufacturing and Device ID.
* It is used to ensure for Device identity to ensure communication with the right device.
*
* First Byte Sent = Adesto SPI Command for Read ID - Check Datasheet of Adesto.
* Next 3 bytes sent are Dummy Bytes, Slave data output is garbage for all 3 dummy bytes
* Next 2 bytes sent are Dummy bytes but bytes received are Manufacturing ID of 1Fh, followed by Device ID of 14h.
*
*/
void ReadId(void)
{
uint8_t manufacturingId, deviceId; // Create Place holders for Manufacturing and Device ID
UARTprintf("Acquiring Flash Info...\n");
ChipSelect(~GPIO_PIN_3); //Assert External Flash Chip-select
TransferByte(AT_READ_ID); // Adesto's Instruction Command to retrieve Device Information
TransferByte(0x00); // Dummy byte
TransferByte(0x00); // Dummy byte
TransferByte(0x00); // Dummy byte
manufacturingId = TransferByte(0x00); // Manufacturing ID
deviceId= TransferByte(0x00); // Device ID
ChipSelect(GPIO_PIN_3); // Deassert External Flash Chip-Select
UARTprintf("Manufacturing ID: \n", manufacturingId);
UARTprintf("Device ID: \n", deviceId);
}
/*
* This function is used to Program a page of the External FLash. Page = 256 Bytes.
* First, you need to send Write Enable Command after assertion of Chip-Select. To indicate End of Communication, deassert Chip-Select.
* Next, send Page Program Command, followed by 24-bit start Address, followed by the 256 Bytes of data - A byte at a time.
* After 256th Byte, Deassert Chip-Select - Indicates the data to be stored in the Flash has been sent.
* After Deassertion, the Flash starts Programming its Memory starting at the 24-bit address - you need to wait until the device has finished writing
* all 256 bytes to its Memory.
*
*/
void PageWrite(uint32_t startAddress, uint32_t numberOfBytes, uint8_t *Data)
{
ChipSelect(~GPIO_PIN_3); // Assert External Flash Chip-Select
TransferByte(AT_WRITE_ENABLE); // Send Write-Enable Command to the External Flash
ChipSelect(GPIO_PIN_3); // Deassert External Flash Chip-Select
ChipSelect(~GPIO_PIN_3); // Assert External Flash Chip-Select Program Page
TransferByte(AT_PAGE_PROGRAM); // Send Page Program Command to Flash
TransferByte((startAddress >> 16) & 0xFF); // Extracting Address Byte A23:A16 and Sending to Flash
TransferByte((startAddress >> 8) & 0xFF); // Extracting Address Byte A15:A08 and Sending to Flash
TransferByte((startAddress >> 0) & 0xFF); // Extracting Address Byte A07:A00 and Sending to Flash
// Now transfer Data
int i;
for (i = 0; i < numberOfBytes; i++) {
TransferByte(Data[i]);
}
ChipSelect(GPIO_PIN_3); // Deassert External Flash Chip-Select to signal end of communication.
DeviceBusyDelay(); // Wait till Flash Programs a page; Flash programs its memory after Chip-Select Deasserted.
}
/*
* This function is used to read device status; The 8-bit data returned by Adesto is used to determine device status.
* Returned Byte value = 1 Device Busy
* Returned Byte value = 0 Device Ready
*/
void DeviceBusyDelay(void)
{
ChipSelect(~GPIO_PIN_3); //Assert Flash Chip-Select
TransferByte(AT_READ_STATUS_FORMAT_1); //Request Device Status
while (TransferByte(0x00) & 1); //Wait till Device is Ready
ChipSelect(GPIO_PIN_3); //Deassert Flash Chip-Select
}
/*
* This function is used to Write Data to the External Flash given the StartingAddress, number of Bytes to write and Pointer
* to the data to be written to the External Flash.
* The function checks if the starting address aligns with the a 256 Byte page Address and based on the alignment result,
* sends bytes of Data to Flash's internal buffer via the PageWrite Method.
*/
void WriteToFlash(uint32_t startAddress, uint32_t numberOfBytes, uint8_t *Data)
{
uint8_t numberOfFullPages = 0, numberOfSingleBytes = 0, pageNotAligned = 0, leftOverBytes = 0;
pageNotAligned = startAddress % AT_PAGE_SIZE_256; // Checking if start Address aligns with 256 Byte Page Boundary (i.e. checking if A07:A00 = 0x00)
// number of Full pages
numberOfFullPages = numberOfBytes / AT_PAGE_SIZE_256;
// number of Single bytes remaining
numberOfSingleBytes = numberOfBytes % AT_PAGE_SIZE_256;
if (pageNotAligned == 0) // Start Address is Aligned with Page Boundaries ; 0-FF => 100h, 256 Bytes = 1 Page = 100h
{
while (numberOfFullPages--)
{
PageWrite(startAddress, AT_PAGE_SIZE_256, Data);
startAddress += AT_PAGE_SIZE_256;
Data += AT_PAGE_SIZE_256;
}
if (numberOfSingleBytes > 0) // If total pages not a whole number, the remaining bytes are written on the next page.
{
PageWrite(startAddress, numberOfSingleBytes, Data);
}
}
else // Start Address is not Aligned with Page Boundaries
{
leftOverBytes = AT_PAGE_SIZE_256 - pageNotAligned; // The number of bytes remaining to form a page of 256 Bytes.
if(numberOfBytes<leftOverBytes)
{
PageWrite(startAddress, numberOfBytes, Data);
}
else if (numberOfBytes>leftOverBytes)
{
PageWrite(startAddress,leftOverBytes,Data); // Page completely programmed.
startAddress+=leftOverBytes; // Moving address to the start of Next Page.
Data+=leftOverBytes; // Increment Data Index
// Now we can write pages to the External Flash - First calculate number of bytes remaining
numberOfBytes-=leftOverBytes;
numberOfFullPages = numberOfBytes % AT_PAGE_SIZE_256;
numberOfSingleBytes = numberOfBytes % AT_PAGE_SIZE_256;
while (numberOfFullPages--)
{
PageWrite(startAddress, AT_PAGE_SIZE_256, Data);
startAddress += AT_PAGE_SIZE_256;
Data += AT_PAGE_SIZE_256;
}
if (numberOfSingleBytes > 0) // If total pages not a whole number, the remaining bytes are written on the next page.
{
PageWrite(startAddress, numberOfSingleBytes, Data);
}
}
}
}
void ReadFlash(uint32_t startAddress, uint32_t numberOfBytes, uint8_t *DataRx)
{
ChipSelect(~GPIO_PIN_3); // Assert External Flash Chip select
TransferByte(AT_READ_DATA); // Send Adesto Command for requesting Data from Flash.
TransferByte((startAddress >> 16) & 0xFF); // Extract A23-A16 from the 32-bit Start Address and send to Flash
TransferByte((startAddress >> 8) & 0xFF); // Extract A15-A08 from the 32-bit Start Address and send to Flash
TransferByte((startAddress >> 0) & 0xFF); // Extract A07-A00 from the 32-bit Start Address and send to Flash
int i;
for (i = 0; i < numberOfBytes; i++)
{
DataRx[i] = TransferByte(0x00); // Send dummy data to retrieve Data from the sent startAddress.
}
ChipSelect(GPIO_PIN_3); // Deassert External Flash Chip select
DeviceBusyDelay(); // Wait till the Device has sent all the Bytes
UARTprintf("Received all %n bytes from starting address 0x%2",numberOfBytes,(startAddress>>16));
UARTprintf("%2", (startAddress >> 8)); //Prints A15-A8
UARTprintf("%2\r\n", startAddress); // Prints bits A7-A0
PrintPage(DataRx);
}
void PrintPage(uint8_t *Data)
{
uint8_t row, column;
for (row = 0; row < 16; row++) {
for (column = 0; column < 16; column++) {
//UARTprintf("\%2\r\n", Data[((row * 16) + column)]);
}
UARTprintf("\n"); // Jump to next row.
}
}
void EraseFlash(uint32_t startAddress, uint32_t numberOfBytes)
{
UARTprintf("Erasing %n Bytes of Data from Starting Address 0x%2", numberOfBytes, (startAddress >> 16)); // Prints bits A23-A16 of Address
UARTprintf("%2", (startAddress >> 8)); //Prints A15-A8
UARTprintf("%2\r\n", startAddress); // Prints bits A7-A0
uint8_t numberOf_64KB_Blocks = 0, numberOfSingleBytes = 0;
numberOf_64KB_Blocks = numberOfBytes / AT_BLOCK_SIZE_64; //number of 64KB blocks
numberOfSingleBytes = numberOfBytes % AT_BLOCK_SIZE_64; // number of Single Bytes - leftovers
while (numberOf_64KB_Blocks--) {
EraseBlock(startAddress);
startAddress += AT_BLOCK_SIZE_64;
numberOfBytes -= AT_BLOCK_SIZE_64;
}
if (numberOfSingleBytes > 0) {
EraseBlock(startAddress);
}
UARTprintf("Done\r\n\r\n");
UARTprintf("Erased %n Bytes of Data from Starting Address 0x%2", numberOfBytes, (startAddress >> 16)); // Prints bits A23-A16 of Address
UARTprintf("%x", (startAddress >> 8)); //Prints bits A15-A8
UARTprintf("%x\r\n", startAddress); // Prints bits A7-A0
}
void EraseBlock(uint32_t startAddress)
{
ChipSelect(~GPIO_PIN_3); // Assert External Flash Chip Select
TransferByte(AT_WRITE_ENABLE); // Enable Write to Flash Memory
ChipSelect(GPIO_PIN_3); // Deassert Flash ChipSelect to signal end of command
ChipSelect(~GPIO_PIN_3); // Assert Flash ChipSelect again
TransferByte(AT_BLOCK_ERASE_64);
TransferByte((startAddress >> 16) & 0xFF); // Extract Address bits A23-A16
TransferByte((startAddress >> 8) & 0xFF); // Extract Address bits A15-A8
TransferByte((startAddress >> 0) & 0xFF); // Extract Address bits A7-A0
ChipSelect(GPIO_PIN_3); // Deassert Flash Chip Select to signal end of transmission.
//Wait for the Device to be ready again. The device needs time to erase.
DeviceBusyDelay();
}
void EraseChip(void)
{
ChipSelect(~GPIO_PIN_3); // Assert Flash Chip Select
TransferByte(AT_WRITE_ENABLE); // Enable Write to Flash Memory
ChipSelect(GPIO_PIN_3); // Deassert Chip Select to signal end of command.
ChipSelect(~GPIO_PIN_3); // Assert Chip Select again to send Chip Erase command.
TransferByte(AT_CHIP_ERASE);
ChipSelect(GPIO_PIN_3); // Deasset Chip Select to signal end of command.
UARTprintf("Erasing Chip ...\n");
DeviceBusyDelay();
UARTprintf("Chip has been successfully erased!\n\n");
}