dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_flash_jedec.c
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  */
30 #include "pios.h"
31 
32 #if defined(PIOS_INCLUDE_FLASH_JEDEC)
33 
34 #include "pios_flash_jedec_priv.h"
35 #include "pios_semaphore.h"
36 
37 #if defined(PIOS_INCLUDE_RTOS)
38 #include "pios_thread.h"
39 #endif
40 
41 #define JEDEC_WRITE_ENABLE 0x06
42 #define JEDEC_WRITE_DISABLE 0x04
43 #define JEDEC_READ_STATUS 0x05
44 #define JEDEC_WRITE_STATUS 0x01
45 #define JEDEC_READ_DATA 0x03
46 #define JEDEC_FAST_READ 0x0b
47 #define JEDEC_DEVICE_ID 0x9F
48 #define JEDEC_PAGE_WRITE 0x02
49 
50 #define JEDEC_STATUS_BUSY 0x01
51 #define JEDEC_STATUS_WRITEPROTECT 0x02
52 #define JEDEC_STATUS_BP0 0x04
53 #define JEDEC_STATUS_BP1 0x08
54 #define JEDEC_STATUS_BP2 0x10
55 #define JEDEC_STATUS_TP 0x20
56 #define JEDEC_STATUS_SEC 0x40
57 #define JEDEC_STATUS_SRP0 0x80
58 
59 #define JEDED_READ_OPT_DATA 0x4B
60 
61 enum pios_jedec_dev_magic {
62  PIOS_JEDEC_DEV_MAGIC = 0xcb55aa55,
63 };
64 
66 struct jedec_flash_dev {
67  pios_spi_t spi_id;
68  uint32_t slave_num;
69  uint32_t capacity_bytes;
70 
71  uint8_t manufacturer;
72  uint8_t memorytype;
73  uint8_t capacity;
74 
75  const struct pios_flash_jedec_cfg *cfg;
76  struct pios_semaphore *transaction_lock;
77  enum pios_jedec_dev_magic magic;
78 };
79 
81 static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev *flash_dev);
82 static struct jedec_flash_dev *PIOS_Flash_Jedec_alloc(void);
83 
84 static int32_t PIOS_Flash_Jedec_ReadID(struct jedec_flash_dev *flash_dev);
85 static int32_t PIOS_Flash_Jedec_ReadStatus(struct jedec_flash_dev *flash_dev);
86 static int32_t PIOS_Flash_Jedec_ClaimBus(struct jedec_flash_dev *flash_dev);
87 static int32_t PIOS_Flash_Jedec_ReleaseBus(struct jedec_flash_dev *flash_dev);
88 static int32_t PIOS_Flash_Jedec_WriteEnable(struct jedec_flash_dev *flash_dev);
89 static int32_t PIOS_Flash_Jedec_Busy(struct jedec_flash_dev *flash_dev);
90 
94 static struct jedec_flash_dev *PIOS_Flash_Jedec_alloc(void)
95 {
96  struct jedec_flash_dev *flash_dev;
97 
98  flash_dev = (struct jedec_flash_dev *)PIOS_malloc(sizeof(*flash_dev));
99  if (!flash_dev) return (NULL);
100 
101  flash_dev->magic = PIOS_JEDEC_DEV_MAGIC;
102 
103  return(flash_dev);
104 }
105 
109 static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev *flash_dev) {
110  if (flash_dev == NULL)
111  return -1;
112  if (flash_dev->magic != PIOS_JEDEC_DEV_MAGIC)
113  return -2;
114  if (flash_dev->spi_id == 0)
115  return -3;
116  return 0;
117 }
118 
119 uint32_t PIOS_Flash_Jedec_GetCapacity(uintptr_t chip_id)
120 {
121  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
122 
123  if (PIOS_Flash_Jedec_Validate(flash_dev) != 0)
124  return 0;
125 
126  return flash_dev->capacity_bytes;
127 }
128 
132 int32_t PIOS_Flash_Jedec_Init(uintptr_t *chip_id, pios_spi_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg *cfg)
133 {
134  struct jedec_flash_dev *flash_dev = PIOS_Flash_Jedec_alloc();
135  if (flash_dev == NULL)
136  return -1;
137 
138  flash_dev->transaction_lock = PIOS_Semaphore_Create();
139  if (flash_dev->transaction_lock == NULL)
140  return -1;
141 
142  flash_dev->spi_id = spi_id;
143  flash_dev->slave_num = slave_num;
144  flash_dev->cfg = cfg;
145 
146  (void) PIOS_Flash_Jedec_ReadID(flash_dev);
147 
148  if (flash_dev->manufacturer != flash_dev->cfg->expect_manufacturer) {
149  /* Mismatched device has been discovered */
150  if (flash_dev->cfg->expect_manufacturer !=
152  return -1;
153  }
154  }
155 
156  if (flash_dev->memorytype != flash_dev->cfg->expect_memorytype) {
157  if (flash_dev->cfg->expect_memorytype !=
159  return -1;
160  }
161  }
162 
163  if (flash_dev->capacity != flash_dev->cfg->expect_capacity) {
164  return -1;
165  }
166 
167  /* Give back a handle to this flash device */
168  *chip_id = (uintptr_t) flash_dev;
169 
170  return 0;
171 }
172 
173 
178 static int32_t PIOS_Flash_Jedec_ClaimBus(struct jedec_flash_dev *flash_dev)
179 {
180  if (PIOS_SPI_ClaimBus(flash_dev->spi_id) < 0)
181  return -1;
182 
183  PIOS_SPI_RC_PinSet(flash_dev->spi_id, flash_dev->slave_num, 0);
184 
185  return 0;
186 }
187 
191 static int32_t PIOS_Flash_Jedec_ReleaseBus(struct jedec_flash_dev *flash_dev)
192 {
193  PIOS_SPI_RC_PinSet(flash_dev->spi_id, flash_dev->slave_num, 1);
194  PIOS_SPI_ReleaseBus(flash_dev->spi_id);
195  return 0;
196 }
197 
202 static int32_t PIOS_Flash_Jedec_Busy(struct jedec_flash_dev *flash_dev)
203 {
204  int32_t status = PIOS_Flash_Jedec_ReadStatus(flash_dev);
205  if (status < 0)
206  return -1;
207  return status & JEDEC_STATUS_BUSY;
208 }
209 
214 static int32_t PIOS_Flash_Jedec_WriteEnable(struct jedec_flash_dev *flash_dev)
215 {
216  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0)
217  return -1;
218 
219  uint8_t out[] = {
220  JEDEC_WRITE_ENABLE,
221  };
222  PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out));
223  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
224 
225  return 0;
226 }
227 
228 
232 static int32_t PIOS_Flash_Jedec_ReadStatus(struct jedec_flash_dev *flash_dev)
233 {
234  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) < 0)
235  return -1;
236 
237  uint8_t out[2] = {
238  JEDEC_READ_STATUS,
239  0,
240  };
241  uint8_t in[2] = {0,0};
242  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,in,sizeof(out)) < 0) {
243  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
244  return -2;
245  }
246 
247  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
248 
249  return in[1];
250 }
251 
255 static int32_t PIOS_Flash_Jedec_ReadID(struct jedec_flash_dev *flash_dev)
256 {
257  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) < 0)
258  return -2;
259 
260  uint8_t out[] = {
261  JEDEC_DEVICE_ID,
262  0,
263  0,
264  0,
265  };
266  uint8_t in[4];
267  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,in,sizeof(out)) < 0) {
268  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
269  return -3;
270  }
271 
272  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
273 
274  flash_dev->manufacturer = in[1];
275  flash_dev->memorytype = in[2];
276  flash_dev->capacity = in[3];
277  flash_dev->capacity_bytes = 1 << flash_dev->capacity;
278 
279  return flash_dev->manufacturer;
280 }
281 
282 /**********************************
283  *
284  * Provide a PIOS flash driver API
285  *
286  *********************************/
287 #include "pios_flash_priv.h"
288 
294 static int32_t PIOS_Flash_Jedec_StartTransaction(uintptr_t chip_id)
295 {
296  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
297 
298  if (PIOS_Flash_Jedec_Validate(flash_dev) != 0)
299  return -1;
300 
301  if (PIOS_Semaphore_Take(flash_dev->transaction_lock, PIOS_SEMAPHORE_TIMEOUT_MAX) != true)
302  return -2;
303 
304  return 0;
305 }
306 
312 static int32_t PIOS_Flash_Jedec_EndTransaction(uintptr_t chip_id)
313 {
314  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
315 
316  if (PIOS_Flash_Jedec_Validate(flash_dev) != 0)
317  return -1;
318 
319  if (PIOS_Semaphore_Give(flash_dev->transaction_lock) != true)
320  return -2;
321 
322  return 0;
323 }
324 
334 static int32_t PIOS_Flash_Jedec_EraseSector(uintptr_t chip_id, uint32_t chip_sector, uint32_t chip_offset)
335 {
336  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
337 
338  if (PIOS_Flash_Jedec_Validate(flash_dev) != 0)
339  return -1;
340 
341  uint8_t ret;
342  uint8_t out[] = {
343  flash_dev->cfg->sector_erase,
344  (chip_offset >> 16) & 0xff,
345  (chip_offset >> 8) & 0xff,
346  (chip_offset >> 0) & 0xff,
347  };
348 
349  if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0)
350  return ret;
351 
352  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0)
353  return -1;
354 
355  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out)) < 0) {
356  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
357  return -2;
358  }
359 
360  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
361 
362  // Keep polling when bus is busy too
363  while (PIOS_Flash_Jedec_Busy(flash_dev) != 0) {
364 #if defined(PIOS_INCLUDE_RTOS)
366 #endif
367  }
368 
369  return 0;
370 }
371 
383 static int32_t PIOS_Flash_Jedec_WriteData(uintptr_t chip_id, uint32_t chip_offset, const uint8_t *data, uint16_t len)
384 {
385  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
386 
387  if(PIOS_Flash_Jedec_Validate(flash_dev) != 0)
388  return -1;
389 
390  uint8_t ret;
391  uint8_t out[4] = {
392  JEDEC_PAGE_WRITE,
393  (chip_offset >> 16) & 0xff,
394  (chip_offset >> 8) & 0xff,
395  (chip_offset >> 0) & 0xff,
396  };
397 
398  /* Can only write one page at a time */
399  if (len > 0x100)
400  return -2;
401 
402  /* Ensure number of bytes fits after starting address before end of page */
403  if (((chip_offset & 0xff) + len) > 0x100)
404  return -3;
405 
406  if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0)
407  return ret;
408 
409  /* Execute write page command and clock in address. Keep CS asserted */
410  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0)
411  return -1;
412 
413  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out)) < 0) {
414  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
415  return -1;
416  }
417 
418  /* Clock out data to flash */
419  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,data,NULL,len) < 0) {
420  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
421  return -1;
422  }
423 
424  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
425 
426  // Keep polling when bus is busy too
427 #if defined(PIOS_INCLUDE_RTOS)
428  while (PIOS_Flash_Jedec_Busy(flash_dev) != 0) {
430  }
431 #else
432 
433  // Query status this way to prevent accel chip locking us out
434  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) < 0)
435  return -1;
436 
437  PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS);
438  while (PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS) & JEDEC_STATUS_BUSY);
439 
440  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
441 
442 #endif
443  return 0;
444 }
445 
455 static int32_t PIOS_Flash_Jedec_ReadData(uintptr_t chip_id, uint32_t chip_offset, uint8_t *data, uint16_t len)
456 {
457  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
458 
459  if (PIOS_Flash_Jedec_Validate(flash_dev) != 0)
460  return -1;
461 
462  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) == -1)
463  return -1;
464 
465  /* Execute read command and clock in address. Keep CS asserted */
466  uint8_t out[] = {
467  JEDEC_READ_DATA,
468  (chip_offset >> 16) & 0xff,
469  (chip_offset >> 8) & 0xff,
470  (chip_offset >> 0) & 0xff,
471  };
472 
473  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out)) < 0) {
474  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
475  return -2;
476  }
477 
478  /* Copy the transfer data to the buffer */
479  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,NULL,data,len) < 0) {
480  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
481  return -3;
482  }
483 
484  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
485 
486  return 0;
487 }
488 
498 int32_t PIOS_Flash_Jedec_ReadOTPData(uintptr_t chip_id, uint32_t chip_offset, uint8_t *data, uint16_t len)
499 {
500  struct jedec_flash_dev *flash_dev = (struct jedec_flash_dev *)chip_id;
501 
502  if (PIOS_Flash_Jedec_Validate(flash_dev) != 0)
503  return -1;
504 
505  if (PIOS_Flash_Jedec_ClaimBus(flash_dev) == -1)
506  return -1;
507 
508  /* Execute read command and clock in address. Keep CS asserted */
509  uint8_t out[] = {
510  JEDED_READ_OPT_DATA,
511  (chip_offset >> 16) & 0xff,
512  (chip_offset >> 8) & 0xff,
513  (chip_offset >> 0) & 0xff,
514  };
515 
516  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out)) < 0) {
517  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
518  return -2;
519  }
520 
521  /* Copy the transfer data to the buffer */
522  if (PIOS_SPI_TransferBlock(flash_dev->spi_id,NULL,data,len) < 0) {
523  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
524  return -3;
525  }
526 
527  PIOS_Flash_Jedec_ReleaseBus(flash_dev);
528 
529  return 0;
530 }
531 
532 /* Provide a flash driver to external drivers */
534  .start_transaction = PIOS_Flash_Jedec_StartTransaction,
535  .end_transaction = PIOS_Flash_Jedec_EndTransaction,
536  .erase_sector = PIOS_Flash_Jedec_EraseSector,
537  .write_data = PIOS_Flash_Jedec_WriteData,
538  .read_data = PIOS_Flash_Jedec_ReadData,
539 };
540 
541 #endif /* PIOS_INCLUDE_FLASH_JEDEC */
uint8_t capacity[3]
#define PIOS_SEMAPHORE_TIMEOUT_MAX
Main PiOS header to include all the compiled in PiOS options.
const struct pios_flash_driver pios_jedec_flash_driver
int32_t PIOS_SPI_RC_PinSet(pios_spi_t spi_dev, uint32_t slave_id, bool pin_value)
int32_t PIOS_Flash_Jedec_Init(uintptr_t *flash_id, pios_spi_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg *cfg)
int32_t PIOS_SPI_ClaimBus(pios_spi_t spi_dev)
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
uint8_t data[XFER_BYTES_PER_PACKET]
Definition: bl_messages.h:129
int32_t PIOS_Flash_Jedec_ReadOTPData(uintptr_t chip_id, uint32_t chip_offset, uint8_t *data, uint16_t len)
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
#define JEDEC_MEMORYTYPE_ANY
int16_t status
Definition: main.c:61
Driver for talking to most JEDEC flash chips.
struct pios_semaphore * PIOS_Semaphore_Create(void)
Creates a binary semaphore.
uint8_t PIOS_SPI_TransferByte(pios_spi_t spi_dev, uint8_t b)
int32_t PIOS_SPI_TransferBlock(pios_spi_t spi_dev, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len)
bool PIOS_Semaphore_Give(struct pios_semaphore *sema)
Gives binary semaphore.
uint32_t magic
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
bool PIOS_Semaphore_Take(struct pios_semaphore *sema, uint32_t timeout_ms)
Takes binary semaphore.
int32_t PIOS_SPI_ReleaseBus(pios_spi_t spi_dev)
uint32_t PIOS_Flash_Jedec_GetCapacity(uintptr_t chip_id)
#define JEDEC_MANUFACTURER_ANY
int32_t(* start_transaction)(uintptr_t chip_id)