-
Notifications
You must be signed in to change notification settings - Fork 0
/
spi_nb.c
273 lines (221 loc) · 7.54 KB
/
spi_nb.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
#include <stdio.h>
#include "spi_nb.h"
#include "hardware/gpio.h"
#include "hardware/structs/spi.h"
#include "hardware/spi.h"
#include "hardware/irq.h"
#include "hardware/regs/dreq.h"
uint16_t spi0_slave_register;
uint8_t* spi0_buffer;
uint8_t spi0_nb_data_to_read;
void cs_select(void) {
asm volatile("nop \n nop \n nop");
gpio_put(PIN_CS, 0); // Active low
asm volatile("nop \n nop \n nop");
}
void cs_deselect(void) {
asm volatile("nop \n nop \n nop");
gpio_put(PIN_CS, 1);
asm volatile("nop \n nop \n nop");
}
int spi_nb_read_register_8bits(spi_inst_t * spi, uint16_t spi_slave_register, uint8_t *buffer, uint8_t nb_data_to_read){
uint16_t dummy_buffer[8]={0, 0, 0, 0,0, 0, 0, 0};
uint8_t nb_data_read;
static enum {
INIT,
WAIT_SPI_IDLE,
SEND_REGISTER_ADRESS,
WAIT_SENDING_DATA,
SEND_DUMMY_DATA,
WAIT_RECIEVING_DATA,
READ_DATA,
SPI_IN_ERROR,
}status=INIT;
switch(status){
case INIT:
if(spi == spi0){
spi0_slave_register = spi_slave_register;
spi0_buffer = buffer;
spi0_nb_data_to_read = nb_data_to_read;
}
cs_select();
case WAIT_SPI_IDLE:
if(spi_nb_busy(spi) == SPI_IDLE){
status = SEND_REGISTER_ADRESS;
//puts("SEND_REGISTER_ADRESS");
}
break;
case SEND_REGISTER_ADRESS:
spi_slave_register = spi_slave_register | 0x80 | 0X40;
if(spi_nb_write_data(spi, &spi_slave_register, 1) == SPI_OK){
status = WAIT_SENDING_DATA;
// Ici on veut tester une interruption
// Armement de l'interruption
//puts("WAIT_SENDING_DATA");
}else{
status = SPI_IN_ERROR;
}
break;
case WAIT_SENDING_DATA:
if(!spi_nb_busy(spi)){
spi_nb_flush_recieve_fifo(spi);
status = SEND_DUMMY_DATA;
//puts("SEND_DUMMY_DATA");
}
break;
case SEND_DUMMY_DATA:
if(spi_nb_write_data(spi, dummy_buffer, nb_data_to_read) == SPI_OK){
status = WAIT_RECIEVING_DATA;
//puts("WAIT_RECIEVING_DATA");
}else{
status = SPI_IN_ERROR;
}
break;
case WAIT_RECIEVING_DATA:
if(!spi_nb_busy(spi)){
status = READ_DATA;
//puts("READ_DATA");
}
break;
case READ_DATA:
cs_deselect();
nb_data_read = spi_nb_read_data_8bits(spi, buffer);
if(nb_data_read == nb_data_to_read){
//puts("SPI_SUCCESS");
status = INIT;
return SPI_SUCCESS;
}
//puts("SPI_FAILED");
status = SPI_IN_ERROR;
return SPI_FAILED;
break;
case SPI_IN_ERROR:
//puts("SPI_IN_ERROR");
spi_nb_flush_recieve_fifo(spi);
cs_deselect();
status = INIT;
return SPI_FAILED;
break;
}
return SPI_IN_PROGRESS;
}
/// @brief Tell if the SPI is busy
/// @param spi SPI device to use (spi0 or spi1)
/// @return SPI_BUSY of SPI_IDLE
int spi_nb_busy(spi_inst_t * spi){
return (spi_get_hw(spi)->sr & SPI_SSPSR_BSY_BITS);
}
/// @brief Empty SPI Recieve FIFO
/// @param spi SPI device to use (spi0 or spi1)
void spi_nb_flush_recieve_fifo(spi_inst_t * spi){
uint16_t dummy;
while(spi_get_hw(spi)->sr & SPI_SSPSR_RNE_BITS){
dummy = spi_get_hw(spi)->dr;
}
}
/// @brief read the SPI Recieve FIFO
/// @param spi SPI device to use (spi0 or spi1)
/// @param buffer To store data recieved
/// @return Number of byte read
uint8_t spi_nb_read_data_8bits(spi_inst_t * spi, uint8_t * buffer){
uint8_t index = 0;
while(spi_get_hw(spi)->sr & SPI_SSPSR_RNE_BITS){
buffer[index] = (uint8_t)spi_get_hw(spi)->dr ;//& SPI_SSPDR_DATA_BITS;
index++;
}
return index;
}
/// @brief Write severals byte to the SPI Transmit FIFO
/// @param spi SPI device to use (spi0 or spi1)
/// @param buffer data to transmit
/// @param size size of the data to transmit
/// @return SPI_OK or SPI_ERR_TRANSMIT_FIFO_FULL
inline int spi_nb_write_data(spi_inst_t * spi, uint16_t * buffer, uint8_t size){
int status_spi;
uint8_t index=0;
do
{
if(spi_get_hw(spi)->sr & SPI_SSPSR_TNF_BITS){
spi_get_hw(spi)->dr = buffer[index];
status_spi = SPI_OK;
}else{
status_spi = SPI_ERR_TRANSMIT_FIFO_FULL;
}
//while (spi_nb_busy(spi));// <== ça, c'est bizarre !
//statu_spi = spi_nb_write_byte(spi, buffer[index]);
//printf("envoi : %x\n", buffer[index]);
//sleep_ms(1);
index++;
} while ( (status_spi == SPI_OK) && (index < size));
return status_spi;
}
/// @brief Write one "byte", 4 to 16 bits to the SPI Transmit FIFO.
/// @param spi
/// @param data : Data to send
/// @return SPI_OK if Ok, SPI_ERR_TRANSMIT_FIFO_FULL if fifo is full
int spi_nb_write_byte(spi_inst_t * spi, uint16_t data){
if(spi_get_hw(spi)->sr & SPI_SSPSR_TNF_BITS){
spi_get_hw(spi)->dr = data;
return SPI_OK;
}
return SPI_ERR_TRANSMIT_FIFO_FULL;
}
int spi_read_register(spi_inst_t * spi, uint16_t spi_slave_register, uint8_t *buffer, uint8_t nb_to_read){
int statu;
uint8_t nb_read;
uint16_t tampon[15]={0,0,0,0,0,0,0,0,0,0,0,0};
spi_slave_register = spi_slave_register | 0x80 | 0X40;
tampon[0]= spi_slave_register;
spi_nb_flush_recieve_fifo(spi0);
cs_select();
statu = spi_nb_write_data(spi, tampon, 1 + nb_to_read);
if(statu == SPI_ERR_TRANSMIT_FIFO_FULL){
printf("Erreur: spi_read_register: SPI_ERR_TRANSMIT_FIFO_FULL");
return statu;
}
while(spi_nb_busy(spi0));
cs_deselect();
nb_read = spi_nb_read_data_8bits(spi0, buffer);
if(nb_read != nb_to_read+1){
printf("Erreur: spi_read_register, nb de valeurs lues incoherentes");
}
return nb_read;
}
void spi_test(){
// Gyro_Init
uint16_t tampon_ecriture[] = {'a','b','c','d','e','f','g','h','i','j',0};
uint8_t tampon_lecture[10] = {0,0,0,0,0,0,0,0,0,0};
uint8_t nb_lu, statu;
uint8_t config = 0b11101111;
uint16_t config_gyro[2] = {0x20, config};
gpio_set_function(16, GPIO_FUNC_SPI); // SDI
gpio_set_function(18, GPIO_FUNC_SPI); // SCK
gpio_set_function(19, GPIO_FUNC_SPI); // SDO
gpio_set_function(PIN_CS, GPIO_OUT); // CSn
gpio_init(PIN_CS);
gpio_set_dir(PIN_CS, GPIO_OUT);
cs_deselect();
//spi_init(spi0, 100 * 1000); // SPI init @ 100 kHz
uint speed = spi_init(spi0, 2 * 1000 * 1000); // SPI init @ 2 MHz
printf("vitesse SPI : %d\n", speed);
//Ça doit être les valeurs par défaut, mais ça marche !
spi_set_format(spi0, 8, SPI_CPHA_1, SPI_CPOL_1, SPI_MSB_FIRST);
// Gyro_Init
// gyro_config
cs_select();
statu = spi_nb_write_data(spi0, config_gyro, 2);
if(statu == SPI_ERR_TRANSMIT_FIFO_FULL){
printf("Erreur: spi_read_register: SPI_ERR_TRANSMIT_FIFO_FULL\n");
}
while(spi_nb_busy(spi0));
cs_deselect();
nb_lu = spi_read_register(spi0, 0x20, tampon_lecture, 1);
printf("Nb lu: %d\n", nb_lu);
//puts(tampon_lecture);
if(tampon_lecture[1] == config){
puts("gyro_config ok !");
}else{
puts("gyro_config FAILED !");
printf("gyro_config FAILED ! :%#4x\n", tampon_lecture[1]);
}
}