-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSD_Card.h
257 lines (208 loc) · 6.29 KB
/
SD_Card.h
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
/********************************************************************
Fichier : SD_Card
---------------------------------------------------------------------
Auteur : ISMAIL BEN SALAH
Compilateur : MPLAB X
Date : 19 août 2014
Version : 2.05
---------------------------------------------------------------------
Description : Librairie de fonctionnement de la Carte SD
--------------------------Modifications------------------------------
Version : 1.0
Modification : Version initiale
*********************************************************************/
#include "SPI_function.h"
#include "General_func.h"
#include "FSconfig.h"
#ifndef SD_CARD_H
#define SD_CARD_H
//Typedefs
typedef unsigned LBA;
//Command for the SD card
#define RESET 0 //a.k.a GO_IDLE (CMD0)
#define INIT 1 //a.k.a SEND_OP_CMD (CMD1)
#define READ_SINGLE 17
#define WRITE_SINGLE 24
//Macros definitions
#define clockSPI() writeSPI2(0xFF);
#define readSPI() writeSPI2(0xFF);
#define disableSD() SD_CS = 1; clockSPI()
#define enableSD() SD_CS = 0
//Hardware definition
#define SD_CS PORTGbits.RG15
#define SD_IO TRISGbits.TRISG15
//Error definition
#define E_COMMAND_ACK 0x80
#define E_INIT_TIMEOUT 0x81
#define FAIL FALSE
//Function definition
#define I_TIMEOUT 100000 //100 ms
#define R_TIMEOUT 1000 //1 ms
#define W_TIMEOUT 100000 //100 ms
//SD definition
#define DATA_START 0xFE
#define DATA_ACCEPT 0x05
//Prototypes
void InitSD(void);
int sendSDCmd (unsigned char cmd,unsigned address);
int initMedia(void);
int readSECTOR (LBA ,char *);
int writeSECTOR (LBA ,char *);
//Functions
void InitSD (void)
{
SD_IO = 0;
SD_CS = 1;
//config SPI2
SPI2CONbits.ON = 0; // disable SPI port
SPI2CONbits.SIDL = 0; // Continue module operation in Idle mode
SPI2BUF = 0; // clear SPI buffer
SPI2CONbits.MODE16 = 0; //Mode 16 bits inactif
SPI2CONbits.MODE32 = 0; //Mode 32 bits inactif
SPI2CONbits.DISSDO = 0; // SDOx pin is controlled by the module
SPI2CONbits.MODE16 = 0; // set in 8-bit mode, clear in 16-bit mode
SPI2CONbits.SMP = 0; // Input data sampled at middle of data output time,dans ce cas middle of time
SPI2CONbits.CKP = 0; // On indique que IDLE est 0 et ACTIVE est 1
SPI2CONbits.CKE = 1; // Le changement de la donnée se fait au flanc descdant
SPI2CONbits.MSTEN = 1; // 1 = Master mode; 0 = Slave mode
SPI2CONbits.FRMEN = 0; // non-framed mode
SPI2BRG = 71; //Il s'agit du diviseur de fréquence Fsck = Fpb / 2* (SPIxBRG+1)
SPI2CONbits.ON = 1; // enable SPI port, clear status
}
int sendSDCmd (unsigned char cmd,unsigned address)
{
//Local variable
char i;
int reponse;
writeSPI2(cmd | 0x40);//Send command
writeSPI2(address>>24);//MSB de l'adresse
writeSPI2(address>>16);
writeSPI2(address>>8);
writeSPI2(address);//LSB de l'adresse
writeSPI2( 0x95); // send CMD0 CRC
// now wait for a response, allow for up to 8 bytes delay
for( i=0; i<8; i++)
{
reponse=writeSPI2(0xFF);
if ( reponse != 0xFF) break;
}
return reponse;
//SD card is always activated
}
//Initialize SD cards
int initMedia(void)
{
int i,reponse;
//La carte SD n'est pas sélectionné
disableSD();
//On envoit 80 clocks avant de sélectionner la carte Sd
for (i=0;i<10;i++)
{
clockSPI();
}
//On sélectionne la carte
enableSD();
//Envoi de la commande RESET à la carte SD
reponse = sendSDCmd(RESET,0);
disableSD();
//On retourne au mode IDLE
if(reponse != 1)
{
return E_COMMAND_ACK;//On indique que la commande à été rejetée
}
//On envoie la commande INIT jusqu'à ce que IDLE se termine
for (i=0; i<I_TIMEOUT; i++)
{
reponse = sendSDCmd( INIT, 0);
disableSD();
if ( !reponse) break;
}
if ( i == I_TIMEOUT)
{
return E_INIT_TIMEOUT; //Init timed out
}
//6.On reconfigure le SPI à Haute Vitesse
SPI2CONbits.ON = 0;
SPI2BRG = 15;
SPI2CONbits.ON = 1;
return 0;//Fin de l'initialisation
}
//Fonction pour lire un secteur de la carte SD
int readSECTOR (LBA address,char *pointer)
{
//Pointeur sur le buffer du secteur
//LBA du secteur requis
int reponse,i;
//1. send READ command
reponse = sendSDCmd(READ_SINGLE,(address<<9));
//Si la commande à été acceptée
if(reponse == 0)
{
//Attente d'une réponse
for( i=0; i<R_TIMEOUT; i++)
{
reponse = readSPI();
if ( reponse == DATA_START)
break;
}
//Si il n'y a pas eu de Timeout on effectue la lecture
if(i != R_TIMEOUT)
{
i = 512; //Pour la lecture des 512 bytes (du secteur en fait)
do
{
*pointer++= readSPI();
}while(--i>0);
//On ignore le CRC
readSPI();
readSPI();
}
//On désactive la carte SD
disableSD();
return (reponse == DATA_START);//Si la transmission à été faite correctement on retourne TRUE
}
}
//Fonction pour écrire dans un secteur de la carte SD
int writeSECTOR (LBA address, char* pointer)
{
unsigned i,reponse;
//On envoie la commande d'écriture
reponse = sendSDCmd(WRITE_SINGLE,(address << 9));
//On vérifie si la commande est acceptée
if (reponse == 0)
{
//On envoie les données
writeSPI2(DATA_START);
//On envoie ensuite les 512 bytes;
for(i = 0;i<512;i++)
{
writeSPI2(*pointer++);
}
//On envoie un CRC bidon
clockSPI();
clockSPI();
//On vérifie si les données sont acceptées
reponse = readSPI();
if((reponse & 0xF) == DATA_ACCEPT)
{
for(i = 0;i<W_TIMEOUT;i++)
{
reponse = readSPI();
if(reponse != 0)//Si accepté on quitte l'attente
{
break;
}
}
}
else
{
//Il n'y a pas eu d'acceptation
reponse = FAIL;
}
}
//On désactive la carte SD
disableSD();
//On renvoit true si tout c'est bien passé
return reponse;
}
#endif /* SD_CARD_H */