Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
sst25vfxxxx.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Freek van Tienen <freek.v.tienen@gmail.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
27 #include "sst25vfxxxx.h"
28 
29 /* Static function defines */
30 
34 void sst25vfxxxx_init(struct SST25VFxxxx *sst, struct spi_periph *spi_p, const uint8_t slave_idx, SPICallback spi_cb)
35 {
36  /* Set spi_peripheral and start flash address */
37  sst->spi_p = spi_p;
38  sst->flash_addr = 0x0;
39 
40  /* Set the spi transaction */
41  sst->spi_t.cpol = SPICpolIdleLow;
42  sst->spi_t.cpha = SPICphaEdge1;
43  sst->spi_t.dss = SPIDss8bit;
44  sst->spi_t.bitorder = SPIMSBFirst;
45  sst->spi_t.cdiv = SPIDiv32;
46 
47  sst->spi_t.input_length = 0;
48  sst->spi_t.output_length = 0;
49  sst->spi_t.input_buf = sst->input_buf;
50  sst->spi_t.output_buf = sst->output_buf;
51  sst->spi_t.slave_idx = slave_idx;
53  sst->spi_t.status = SPITransDone;
54  sst->spi_t.after_cb = spi_cb;
55 
56  /* Update the status and start with enabling writing */
57  sst->status = SST25VFXXXX_IDLE;
59 }
60 
65 {
66  switch (sst->status) {
67  // Enabling writing to blocks
69  // When last transmit is done
70  if (sst->status_idx >= 1) {
71  sst->status = SST25VFXXXX_IDLE;
72  break;
73  }
74 
75  // Write to the status register
76  sst->status_idx = 1;
77  sst->output_buf[0] = SST25VFXXXX_WRSR;
78  sst->output_buf[1] = 0x0;
79  sst->spi_t.output_length = 2;
80  sst->spi_t.input_length = 0;
81  spi_submit(sst->spi_p, &sst->spi_t);
82  break;
83 
84  // Erase the full chip
86  switch (sst->status_idx) {
87  // Execute full erase command
88  case 0:
89  sst->status_idx = 1;
91  sst->spi_t.output_length = 1;
92  sst->spi_t.input_length = 0;
93  spi_submit(sst->spi_p, &sst->spi_t);
94  break;
95 
96  // Wait for chip to finish
97  case 1:
98  // Disable writing when finished erasing
99  if (sst->spi_t.input_length == 2 && !(sst->input_buf[1] & 0x1)) {
100  sst->status_idx = 2;
101  sst->output_buf[0] = SST25VFXXXX_WRDI;
102  sst->spi_t.output_length = 1;
103  sst->spi_t.input_length = 0;
104  spi_submit(sst->spi_p, &sst->spi_t);
105  break;
106  }
107  sst->status_idx = 1;
108  sst->output_buf[0] = SST25VFXXXX_RDSR;
109  sst->spi_t.output_length = 1;
110  sst->spi_t.input_length = 2;
111  spi_submit(sst->spi_p, &sst->spi_t);
112  break;
113 
114  // Goto idle
115  default:
116  sst->status = SST25VFXXXX_IDLE;
117  break;
118  }
119  break;
120 
121  // Write bytes to flash
123  switch (sst->status_idx) {
124  // Send the address with 2 or 1 byte(s) of data
125  case 0:
126  sst->status_idx = 1;
127 
128  if ((sst->transfer_length - sst->transfer_idx) > 1) {
130  } else {
132  }
133  sst->output_buf[1] = (sst->flash_addr >> 16) & 0xFF;
134  sst->output_buf[2] = (sst->flash_addr >> 8) & 0xFF;
135  sst->output_buf[3] = sst->flash_addr & 0xFF;
136  sst->output_buf[4] = sst->transfer_buf[sst->transfer_idx++];
137 
138  if ((sst->transfer_length - sst->transfer_idx) > 1) {
139  sst->output_buf[5] = sst->transfer_buf[sst->transfer_idx++];
140  sst->spi_t.output_length = 6;
141  } else {
142  sst->spi_t.output_length = 5;
143  }
144 
145  sst->spi_t.input_length = 0;
146  spi_submit(sst->spi_p, &sst->spi_t);
147  break;
148 
149  // Read the status register
150  case 1:
151  sst->status_idx = 2;
152  sst->output_buf[0] = SST25VFXXXX_RDSR;
153  sst->spi_t.output_length = 1;
154  sst->spi_t.input_length = 2;
155  spi_submit(sst->spi_p, &sst->spi_t);
156  break;
157 
158  // Check the status register and send new bytes if possible
159  case 2:
160  // Still busy
161  if (sst->input_buf[1] & 0x1) {
162  sst->output_buf[0] = SST25VFXXXX_RDSR;
163  sst->spi_t.output_length = 1;
164  sst->spi_t.input_length = 2;
165  spi_submit(sst->spi_p, &sst->spi_t);
166  break;
167  }
168 
169  // Write disabeling
170  if ((sst->transfer_length - sst->transfer_idx) <= 0) {
171  sst->status_idx = 3;
172  sst->output_buf[0] = SST25VFXXXX_WRDI;
173  sst->spi_t.output_length = 1;
174  sst->spi_t.input_length = 0;
175  spi_submit(sst->spi_p, &sst->spi_t);
176  break;
177  }
178 
179  // Transfer new bytes
180  sst->status_idx = 1;
182  sst->output_buf[1] = sst->transfer_buf[sst->transfer_idx++];
183 
184  if ((sst->transfer_length - sst->transfer_idx) <= 0) {
185  sst->output_buf[2] = sst->transfer_buf[sst->transfer_idx++]; //FIXME: uneven packets!!!!!
186  } else {
187  sst->output_buf[2] = 0x0;
188  }
189 
190  sst->spi_t.output_length = 3;
191  sst->spi_t.input_length = 0;
192  spi_submit(sst->spi_p, &sst->spi_t);
193  break;
194 
195  // Goto idle and update the flash address
196  default:
197  sst->flash_addr += sst->transfer_length;
198  sst->status = SST25VFXXXX_IDLE;
199  break;
200  }
201  break;
202 
203  // Read bytes from flash memory
205  // Reset the buffer pointer and goto idle
206  sst->spi_t.input_buf = sst->input_buf;
207  sst->status = SST25VFXXXX_IDLE;
208  break;
209 
210  // Default goto idle
211  default:
212  sst->status = SST25VFXXXX_IDLE;
213  break;
214  }
215 }
216 
221 {
222  if (sst->status != SST25VFXXXX_IDLE) {
223  return;
224  }
225 
226  // Write the read id command to the chip
228  sst->output_buf[0] = SST25VFXXXX_RDID;
229  sst->output_buf[1] = 0x0;
230  sst->output_buf[2] = 0x0;
231  sst->output_buf[3] = 0x0; //READ the MFG ID first
232  sst->spi_t.output_length = 4;
233  sst->spi_t.input_length = 8;
234  spi_submit(sst->spi_p, &sst->spi_t);
235 }
236 
241 {
242  if (sst->status != SST25VFXXXX_IDLE) {
243  return;
244  }
245 
246  // Enable writing to the status register
248  sst->status_idx = 0;
249  sst->output_buf[0] = SST25VFXXXX_EWSR;
250  sst->spi_t.output_length = 1;
251  sst->spi_t.input_length = 0;
252  spi_submit(sst->spi_p, &sst->spi_t);
253 }
254 
259 {
260  if (sst->status != SST25VFXXXX_IDLE) {
261  return;
262  }
263 
264  // Enable writing
266  sst->status_idx = 0;
267  sst->output_buf[0] = SST25VFXXXX_WREN;
268  sst->spi_t.output_length = 1;
269  sst->spi_t.input_length = 0;
270  spi_submit(sst->spi_p, &sst->spi_t);
271 }
272 
276 void sst25vfxxxx_write(struct SST25VFxxxx *sst, uint8_t *transfer_buffer, uint8_t transfer_length)
277 {
278  if (sst->status != SST25VFXXXX_IDLE) {
279  return;
280  }
281 
282  // Set the transfer buffer
283  sst->transfer_buf = transfer_buffer; // Not copied so keep buffer available!
284  sst->transfer_idx = 0;
285  sst->transfer_length = transfer_length;
286 
287  // Enable writing
289  sst->status_idx = 0;
290  sst->output_buf[0] = SST25VFXXXX_WREN;
291  sst->spi_t.output_length = 1;
292  sst->spi_t.input_length = 0;
293  spi_submit(sst->spi_p, &sst->spi_t);
294 }
295 
300 void sst25vfxxxx_read(struct SST25VFxxxx *sst, uint8_t *transfer_buffer, uint8_t transfer_length)
301 {
302  if (sst->status != SST25VFXXXX_IDLE) {
303  return;
304  }
305 
306  // Read all bytes at once
308  sst->status_idx = 0;
310  sst->output_buf[1] = (sst->flash_addr >> 16) & 0xFF;
311  sst->output_buf[2] = (sst->flash_addr >> 8) & 0xFF;
312  sst->output_buf[3] = sst->flash_addr & 0xFF;
313  sst->output_buf[4] = 0x0;
314  sst->spi_t.output_length = 5;
315  sst->spi_t.input_buf = transfer_buffer; // Need to reset this afterwards
316  sst->spi_t.input_length = transfer_length + 5;
317  spi_submit(sst->spi_p, &sst->spi_t);
318 }
SST25VFXXXX_CHIP_ERASE
@ SST25VFXXXX_CHIP_ERASE
The chip is busy erasing itself.
Definition: sst25vfxxxx.h:57
SST25VFXXXX_AAI_PROG
#define SST25VFXXXX_AAI_PROG
Definition: sst25vfxxxx.h:40
spi_transaction::cdiv
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:159
SST25VFxxxx::output_buf
uint8_t output_buf[16]
The output buffer for the SPI transaction.
Definition: sst25vfxxxx.h:69
SST25VFXXXX_WRITE_BYTES
@ SST25VFXXXX_WRITE_BYTES
The chip is busy writing bytes.
Definition: sst25vfxxxx.h:58
SST25VFxxxx::transfer_idx
uint8_t transfer_idx
The transfer idx is used for counting input/output bytes.
Definition: sst25vfxxxx.h:73
spi_transaction::cpol
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:155
SST25VFXXXX_READ_BYTES
@ SST25VFXXXX_READ_BYTES
The chip is busy reading bytes.
Definition: sst25vfxxxx.h:59
SST25VFXXXX_RDSR
#define SST25VFXXXX_RDSR
Definition: sst25vfxxxx.h:41
sst25vfxxxx_write
void sst25vfxxxx_write(struct SST25VFxxxx *sst, uint8_t *transfer_buffer, uint8_t transfer_length)
Write bytes.
Definition: sst25vfxxxx.c:276
spi_transaction::output_length
uint16_t output_length
number of data words to write
Definition: spi.h:152
SST25VFXXXX_WRDI
#define SST25VFXXXX_WRDI
Definition: sst25vfxxxx.h:45
SST25VFxxxx::spi_t
struct spi_transaction spi_t
The SPI transaction used for the writing and reading of registers.
Definition: sst25vfxxxx.h:67
SST25VFxxxx
Definition: sst25vfxxxx.h:63
SST25VFXXXX_READ_ID
@ SST25VFXXXX_READ_ID
The chip is busy with getting the chip ID.
Definition: sst25vfxxxx.h:55
sst25vfxxxx.h
SST25VFxxxx::transfer_buf
uint8_t * transfer_buf
The transfer buffer.
Definition: sst25vfxxxx.h:72
SPISelectUnselect
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition: spi.h:63
SST25VFxxxx::status_idx
uint8_t status_idx
The counter of substatuses.
Definition: sst25vfxxxx.h:65
spi_transaction::bitorder
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:158
spi_transaction::output_buf
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:150
spi_periph
SPI peripheral structure.
Definition: spi.h:174
spi_transaction::select
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:154
SST25VFxxxx::spi_p
struct spi_periph * spi_p
The SPI peripheral for the connection.
Definition: sst25vfxxxx.h:66
SPICphaEdge1
@ SPICphaEdge1
CPHA = 0.
Definition: spi.h:74
SPIMSBFirst
@ SPIMSBFirst
Definition: spi.h:112
SPICpolIdleLow
@ SPICpolIdleLow
CPOL = 0.
Definition: spi.h:83
spi_transaction::cpha
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:156
spi_transaction::after_cb
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:161
spi_submit
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:511
SDCard::spi_p
struct spi_periph * spi_p
The SPI peripheral for the connection.
Definition: sdcard_spi.h:110
SST25VFXXXX_ERASE_CHIP
#define SST25VFXXXX_ERASE_CHIP
Definition: sst25vfxxxx.h:38
SST25VFXXXX_WRSR
#define SST25VFXXXX_WRSR
Definition: sst25vfxxxx.h:43
uint8_t
unsigned char uint8_t
Definition: types.h:14
sst25vfxxxx_read
void sst25vfxxxx_read(struct SST25VFxxxx *sst, uint8_t *transfer_buffer, uint8_t transfer_length)
Read bytes Need 5 more extra bytes because of SPI overhead.
Definition: sst25vfxxxx.c:300
SST25VFxxxx::status
enum SST25VFxxxxStatus status
The status of the SST25VFxxxx flash chip.
Definition: sst25vfxxxx.h:64
SST25VFxxxx::flash_addr
uint32_t flash_addr
The flash address to write at.
Definition: sst25vfxxxx.h:70
SPIDss8bit
@ SPIDss8bit
Definition: spi.h:90
SPICallback
void(* SPICallback)(struct spi_transaction *trans)
SPI Callback function.
Definition: spi.h:136
SPIDiv32
@ SPIDiv32
Definition: spi.h:124
SST25VFXXXX_WRITE_EN
@ SST25VFXXXX_WRITE_EN
The chip is busy enabeling writing to blocks.
Definition: sst25vfxxxx.h:56
sst25vfxxxx_block_write_en
void sst25vfxxxx_block_write_en(struct SST25VFxxxx *sst)
Enable block writing.
Definition: sst25vfxxxx.c:240
SST25VFXXXX_IDLE
@ SST25VFXXXX_IDLE
The chip is idle and can be used.
Definition: sst25vfxxxx.h:54
SST25VFxxxx::input_buf
uint8_t input_buf[16]
The input buffer for the SPI transaction.
Definition: sst25vfxxxx.h:68
spi_transaction::input_length
uint16_t input_length
number of data words to read
Definition: spi.h:151
sst25vfxxxx_chip_erase
void sst25vfxxxx_chip_erase(struct SST25VFxxxx *sst)
Full chip erase.
Definition: sst25vfxxxx.c:258
spi_transaction::dss
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:157
spi_transaction::slave_idx
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:153
SPITransDone
@ SPITransDone
Definition: spi.h:101
spi_transaction::input_buf
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:149
SST25VFXXXX_WREN
#define SST25VFXXXX_WREN
Definition: sst25vfxxxx.h:44
sst25vfxxxx_after_cb
void sst25vfxxxx_after_cb(struct SST25VFxxxx *sst)
Callback of the SPI after going one level higher for gathering the sst pointer.
Definition: sst25vfxxxx.c:64
SST25VFXXXX_RDID
#define SST25VFXXXX_RDID
Definition: sst25vfxxxx.h:46
SST25VFXXXX_BYTE_PROG
#define SST25VFXXXX_BYTE_PROG
Definition: sst25vfxxxx.h:39
spi_transaction::status
enum SPITransactionStatus status
Definition: spi.h:162
SST25VFXXXX_HGIH_SPEAD_READ
#define SST25VFXXXX_HGIH_SPEAD_READ
Definition: sst25vfxxxx.h:34
sst25vfxxxx_read_id
void sst25vfxxxx_read_id(struct SST25VFxxxx *sst)
Read the chip identifier.
Definition: sst25vfxxxx.c:220
sst25vfxxxx_init
void sst25vfxxxx_init(struct SST25VFxxxx *sst, struct spi_periph *spi_p, const uint8_t slave_idx, SPICallback spi_cb)
Initializing the sst25vfxxxx chip.
Definition: sst25vfxxxx.c:34
SST25VFXXXX_EWSR
#define SST25VFXXXX_EWSR
Definition: sst25vfxxxx.h:42
SST25VFxxxx::transfer_length
uint8_t transfer_length
The transfer buffer length.
Definition: sst25vfxxxx.h:74