PIC32MZ - SD Probleme

OP (Firma: Student) #5599152
Lesenswert?

Hallo allerseits,

würde gerne mit meinen ChipKIT WiFire (Rev C.) welches einen 
PIC32MZ2048EFG100 besitzt auf meine SD-Karte (onboard) zugreifen um 
Daten (txt) darauf zu speichern. Ich arbeite auf Mplab X IDE und habe 
mich an dem Beispiel von Aidan Mocke 
(http://www.aidanmocke.com/blog/2018/09/04/spi-fatfs/) orientiert, 
welcher die FatFS Bibliothek von elm-chan benutzt. Leider bleibt mein 
Microcontroller beim disk_initialize vorgang immer hängen. Ich hab alles 
ausprobiert was mir einfällt kriege es jedoch nicht hin das Problem zu 
lösen.

Hab es auch schon auf Mplab Harmony versucht, jedoch ohne erfolg, würde 
es deshalb gerne nicht mit Harmony machen, da es mir dann zu 
unübersichtlich/unverständlich wird.


Deswegen wende ich mich jetzt an euch, vlt hat einer erfahrung oder 
Beispiel-Programme mit dem Board/Controller und kann mir 
Tipps/Ratschläge geben :)


Gruß
Malte
Gast #5599468
Lesenswert?

Ich habe 3 Projekte, wo FATFS auf PIC32MX läuft. Es liegt also weder an 
MPLABX PIC32, noch an FATFS.

Worans liegen kann:
Den 1ms Timer  für FATFS hast du aufgesetzt, und ruft ihn auf?
Die SPI-Routine läuft? Scope dranhängen!

Sonst kann man nur empfehlen: Durchsteppen, und hier Code posten.
OP (Firma: Student) #5600433
Lesenswert?

Hi,

danke für die Ratschläge habe jetzt meine Main und meine Diskio.c 
hochgeladen, die restlichen Dateien sind die von FATFS aus dem Patch 
R13b.
1
#include "ff.h"
2
#include "diskio.h"
3

4

5
/** CONFIGURATION *************************************************************/
6

7
// DEVCFG2
8
//Define SYSCLK = 200 MHz
9
#pragma config FPLLIDIV = DIV_3         // System PLL Input Divider (3x Divider)
10
#pragma config FPLLRNG = RANGE_5_10_MHZ // System PLL Input Range (5-10 MHz Input)
11
#pragma config FPLLICLK = PLL_POSC      // System PLL Input Clock Selection (POSC is input to the System PLL)
12
#pragma config FPLLMULT = MUL_50        // System PLL Multiplier (PLL Multiply by 50)
13
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (2x Divider)
14
#pragma config UPLLFSEL = FREQ_24MHZ    // USB PLL Input Frequency Selection (USB PLL input is 24 MHz)
15

16
// DEVCFG1
17
#pragma config FNOSC = SPLL             // Oscillator Selection Bits (System PLL)
18
#pragma config POSCMOD = EC             // Primary Oscillator Configuration (External clock mode)
19
#pragma config DMTCNT = DMT31           // Deadman Timer Count Selection (2^31 (2147483648))
20
#pragma config FDMTEN = OFF             // Deadman Timer Enable (Deadman Timer is disabled)
21

22
// DEVCFG0
23
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
24

25
#include <xc.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <stdbool.h>
29
#include <proc/p32mz2048efg100.h>
30

31
#define SYS_FREQ 200000000 // Running at 200MHz
32

33
void set_performance_mode()
34
{   
35
  unsigned int cp0;
36
  
37
    // Unlock Sequence
38
    asm volatile("di"); // Disable all interrupts
39
    SYSKEY = 0xAA996655;
40
    SYSKEY = 0x556699AA;  
41

42
    // PB1DIV
43
    // Peripheral Bus 1 cannot be turned off, so there's no need to turn it on
44
    PB1DIVbits.PBDIV = 1; // Peripheral Bus 1 Clock Divisor Control (PBCLK1 is SYSCLK divided by 2)
45

46
    // PB2DIV
47
    PB2DIVbits.ON = 1; // Peripheral Bus 2 Output Clock Enable (Output clock is enabled)
48
    PB2DIVbits.PBDIV = 1; // Peripheral Bus 2 Clock Divisor Control (PBCLK2 is SYSCLK divided by 2)
49

50
    // PB3DIV
51
    PB3DIVbits.ON = 1; // Peripheral Bus 2 Output Clock Enable (Output clock is enabled)
52
    PB3DIVbits.PBDIV = 1; // Peripheral Bus 3 Clock Divisor Control (PBCLK3 is SYSCLK divided by 2)
53

54
    // PB4DIV
55
    PB4DIVbits.ON = 1; // Peripheral Bus 4 Output Clock Enable (Output clock is enabled)
56
    while (!PB4DIVbits.PBDIVRDY); // Wait until it is ready to write to
57
    PB4DIVbits.PBDIV = 0; // Peripheral Bus 4 Clock Divisor Control (PBCLK4 is SYSCLK divided by 1)
58

59
    // PB5DIV
60
    PB5DIVbits.ON = 1; // Peripheral Bus 5 Output Clock Enable (Output clock is enabled)
61
    PB5DIVbits.PBDIV = 1; // Peripheral Bus 5 Clock Divisor Control (PBCLK5 is SYSCLK divided by 2)
62

63
    // PB7DIV
64
    PB7DIVbits.ON = 1; // Peripheral Bus 7 Output Clock Enable (Output clock is enabled)
65
    PB7DIVbits.PBDIV = 1; // Peripheral Bus 7 Clock Divisor Control (PBCLK7 is SYSCLK divided by 1)
66

67
    // PB8DIV
68
    PB8DIVbits.ON = 1; // Peripheral Bus 8 Output Clock Enable (Output clock is enabled)
69
    PB8DIVbits.PBDIV = 1; // Peripheral Bus 8 Clock Divisor Control (PBCLK8 is SYSCLK divided by 2)
70

71
    // PRECON - Set up prefetch
72
    PRECONbits.PFMSECEN = 0; // Flash SEC Interrupt Enable (Do not generate an interrupt when the PFMSEC bit is set)
73
    PRECONbits.PREFEN = 0b11; // Predictive Prefetch Enable (Enable predictive prefetch for any address)
74
    PRECONbits.PFMWS = 0b010; // PFM Access Time Defined in Terms of SYSCLK Wait States (Two wait states)
75

76
    // Set up caching
77
    cp0 = _mfc0(16, 0);
78
    cp0 &= ~0x07;
79
    cp0 |= 0b011; // K0 = Cacheable, non-coherent, write-back, write allocate
80
    _mtc0(16, 0, cp0);  
81

82
    // Lock Sequence
83
    SYSKEY = 0x33333333;
84
    asm volatile("ei"); // Enable all interrupts
85
}
86

87
// Global variables
88
FIL file; // File handle for the file we open
89
DIR dir; // Directory information for the current directory
90
FATFS fso; // File System Object for the file system we are reading from
91
FILINFO fileInfo; // Information for the file we have opened (not really necessary to have this)
92

93
void init_disk()
94
{
95
    // Wait for the disk to initialise
96
    while(disk_initialize(0));
97
    // Mount the disk
98
    f_mount(&fso, "", 0);
99
    // Change dir to the root directory
100
    f_chdir("/");
101
    // Open the directory
102
    f_opendir(&dir, ".");
103
}
104

105
void main()
106
{
107
  int bytes_read;
108
    unsigned char buffer[32768];
109
  
110
  // Set up all ports to be digital and not analog
111
    ANSELA = 0;
112
    ANSELB = 0;
113
    ANSELC = 0;
114
    ANSELD = 0;
115
    ANSELE = 0;
116
    ANSELF = 0;
117
    ANSELG = 0;
118
  
119
  
120
  // Set up PPS for SPI3 on RB10 and RC4
121
  SDI3R = 0b0110; // RB10 = SDI3
122
  RPC4R = 0b0111; // RC4 = SDO3
123
  TRISBbits.TRISB10 = 1; // Set RB10 as input because it's SDI3
124
  
125
  // Set max performance mode
126
//  set_performance_mode();
127
  
128
  // Initialise the SD card
129
  init_disk();
130
  
131
  // Open the file test.txt
132
  f_open(&file, "/test.txt", FA_WRITE);
133
      
134

135
  while (1);
136
}
1
/*------------------------------------------------------------------------/
2
/  MMCv3/SDv1/SDv2 (in SPI mode) control module
3
/-------------------------------------------------------------------------/
4
/
5
/  Copyright (C) 2010, ChaN, all right reserved.
6
/
7
/ * This software is a free software and there is NO WARRANTY.
8
/ * No restriction on use. You can use, modify and redistribute it for
9
/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
10
/ * Redistributions of source code must retain the above copyright notice.
11
/
12
/-------------------------------------------------------------------------*/
13
//Edited by A. Morrison to function on PIC32.
14

15
// Ported by Riccardo Leonardi to PIC32MX795F512L  (22/11/2011)
16
// Many thanks to Aiden Morrison's good work!
17
// changes: parametrization of SPI port number
18

19
// Modified by Bryn Thomas (11/09/2016) to use Enhanced Buffer SPI mode
20
// and boost read performance with 32-bit transfers
21

22
// Modified by Aidan Mocke (04/09/2018) to work with the PIC32MZ series
23

24
#define _DISABLE_OPENADC10_CONFIGPORT_WARNING
25
#define _SUPPRESS_PLIB_WARNING
26

27
#include <xc.h>
28
#include "diskio.h"
29

30
/* Definitions for MMC/SDC command */
31
#define CMD0   (0)      /* GO_IDLE_STATE */
32
#define CMD1   (1)      /* SEND_OP_COND */
33
#define ACMD41 (41|0x80)  /* SEND_OP_COND (SDC) */
34
#define CMD8   (8)      /* SEND_IF_COND */
35
#define CMD9   (9)      /* SEND_CSD */
36
#define CMD10  (10)      /* SEND_CID */
37
#define CMD12  (12)      /* STOP_TRANSMISSION */
38
#define ACMD13 (13|0x80)  /* SD_STATUS (SDC) */
39
#define CMD16  (16)      /* SET_BLOCKLEN */
40
#define CMD17  (17)      /* READ_SINGLE_BLOCK */
41
#define CMD18  (18)      /* READ_MULTIPLE_BLOCK */
42
#define CMD23  (23)      /* SET_BLOCK_COUNT */
43
#define ACMD23 (23|0x80)  /* SET_WR_BLK_ERASE_COUNT (SDC) */
44
#define CMD24  (24)      /* WRITE_BLOCK */
45
#define CMD25  (25)      /* WRITE_MULTIPLE_BLOCK */
46
#define CMD41  (41)      /* SEND_OP_COND (ACMD) */
47
#define CMD55  (55)      /* APP_CMD */
48
#define CMD58  (58)      /* READ_OCR */
49

50

51
/* Port Controls  (Platform dependent) */
52
#define CS_SETOUT() TRISCbits.TRISC3 = 0 
53
#define CS_LOW()  LATCbits.LATC3 = 0  //MMC CS = L
54
#define CS_HIGH() LATCbits.LATC3 = 1  //MMC CS = H
55
//Change the SPI port number as needed on the following 5 lines
56
#define SPIBRG  SPI3BRG
57
#define SPIBUF  SPI3BUF
58
#define SPISTATbits SPI3STATbits
59
#define SPICONbits SPI3CONbits
60

61
#define  FCLK_SLOW()  SPIBRG = 128    /* Set slow clock (100k-400k) */
62
#define  FCLK_FAST()  SPIBRG = 16    /* Set fast clock (depends on the CSD) */
63

64

65
static volatile
66
DSTATUS Stat = STA_NOINIT;  /* Disk status */
67

68
static volatile
69
UINT Timer1, Timer2;    /* 1000Hz decrement timer */
70

71
static
72
UINT CardType;
73

74
typedef union 
75
{ 
76
    UINT int_data[128]; 
77
    BYTE byte_data[512];
78
} spi32_data;
79

80
unsigned char __attribute__((coherent)) rcvbuff[8192];
81

82
#define xmit_spi(dat)   xchg_spi(dat)
83
#define rcvr_spi()    xchg_spi(0xFF)
84
#define rcvr_spi_m(p)  SPIBUF = 0xFF; while (SPISTATbits.SPIRBE); *(p) = (BYTE)SPIBUF;
85

86
static
87
BYTE xchg_spi (BYTE dat)
88
{
89
  SPIBUF = dat;
90
  while (!SPISTATbits.SPIRBF);
91
  return (BYTE)SPIBUF;
92
}
93

94
/*-----------------------------------------------------------------------*/
95
/* Wait for card ready                                                   */
96
/*-----------------------------------------------------------------------*/
97

98
static
99
BYTE wait_ready (void)
100
{
101
  BYTE res;
102

103

104
  Timer2 = 500;  /* Wait for ready in timeout of 500ms */
105
  rcvr_spi();
106
  do
107
    res = rcvr_spi();
108
  while ((res != 0xFF) && Timer2);
109

110
  return res;
111
}
112

113

114

115
/*-----------------------------------------------------------------------*/
116
/* Deselect the card and release SPI bus                                 */
117
/*-----------------------------------------------------------------------*/
118

119
static
120
void deselect (void)
121
{
122
  CS_HIGH();
123
  rcvr_spi();
124
}
125

126

127

128
/*-----------------------------------------------------------------------*/
129
/* Select the card and wait ready                                        */
130
/*-----------------------------------------------------------------------*/
131

132
static
133
int select (void)  /* 1:Successful, 0:Timeout */
134
{
135
  CS_LOW();
136
  if (wait_ready() != 0xFF) {
137
    deselect();
138
    return 0;
139
  }
140
  return 1;
141
}
142

143

144

145

146
/*-----------------------------------------------------------------------*/
147
/* Write Sector(s)                                                       */
148
/*-----------------------------------------------------------------------*/
149
/*-----------------------------------------------------------------------*/
150
/* Send a command packet to MMC                                          */
151
/*-----------------------------------------------------------------------*/
152

153
static
154
BYTE send_cmd (
155
  BYTE cmd,    /* Command byte */
156
  DWORD arg    /* Argument */
157
)
158
{
159
  BYTE n, res;
160

161

162
  if (cmd & 0x80) {  /* ACMD<n> is the command sequense of CMD55-CMD<n> */
163
    cmd &= 0x7F;
164
    res = send_cmd(CMD55, 0);
165
    if (res > 1) return res;
166
  }
167

168
  /* Select the card and wait for ready */
169
  deselect();
170
  if (!select()) return 0xFF;
171

172
  /* Send command packet */
173
  xmit_spi(0x40 | cmd);      /* Start + Command index */
174
  xmit_spi((BYTE)(arg >> 24));  /* Argument[31..24] */
175
  xmit_spi((BYTE)(arg >> 16));  /* Argument[23..16] */
176
  xmit_spi((BYTE)(arg >> 8));    /* Argument[15..8] */
177
  xmit_spi((BYTE)arg);      /* Argument[7..0] */
178
  n = 0x01;            /* Dummy CRC + Stop */
179
  if (cmd == CMD0) n = 0x95;    /* Valid CRC for CMD0(0) */
180
  if (cmd == CMD8) n = 0x87;    /* Valid CRC for CMD8(0x1AA) */
181
  xmit_spi(n);
182

183
  /* Receive command response */
184
  if (cmd == CMD12) rcvr_spi();  /* Skip a stuff byte when stop reading */
185
  n = 10;              /* Wait for a valid response in timeout of 10 attempts */
186
  do
187
    res = rcvr_spi();
188
  while ((res & 0x80) && --n);
189

190
  return res;      /* Return with the response value */
191
}
192

193
/*-----------------------------------------------------------------------*/
194
/* Send a data packet to MMC                                             */
195
/*-----------------------------------------------------------------------*/
196

197
#if _READONLY == 0
198
static
199
int xmit_datablock (  /* 1:OK, 0:Failed */
200
  const BYTE *buff,  /* 512 byte data block to be transmitted */
201
  BYTE token      /* Data token */
202
)
203
{
204
  BYTE resp;
205
  UINT bc = 512;
206

207

208
  if (wait_ready() != 0xFF) return 0;
209

210
  xmit_spi(token);    /* Xmit a token */
211
  if (token != 0xFD) {  /* Not StopTran token */
212
    do {            /* Xmit the 512 byte data block to the MMC */
213
      xmit_spi(*buff++);
214
      xmit_spi(*buff++);
215
    } while (bc -= 2);
216
    xmit_spi(0xFF);        /* CRC (Dummy) */
217
    xmit_spi(0xFF);
218
    resp = rcvr_spi();      /* Receive a data response */
219
    if ((resp & 0x1F) != 0x05)  /* If not accepted, return with error */
220
      return 0;
221
  }
222

223
  return 1;
224
}
225
#endif  /* _READONLY */
226

227

228
#if _READONLY == 0
229
DRESULT disk_write (
230
  BYTE pdrv,        /* Physical drive nmuber (0) */
231
  const BYTE *buff,    /* Pointer to the data to be written */
232
  DWORD sector,      /* Start sector number (LBA) */
233
  UINT count        /* Sector count (1..255) */
234
)
235
{
236
  if (pdrv || !count) return RES_PARERR;
237
  if (Stat & STA_NOINIT) return RES_NOTRDY;
238
  if (Stat & STA_PROTECT) return RES_WRPRT;
239

240
  if (!(CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
241

242
  if (count == 1) {    /* Single block write */
243
    if ((send_cmd(CMD24, sector) == 0)  /* WRITE_BLOCK */
244
      && xmit_datablock(buff, 0xFE))
245
      count = 0;
246
  }
247
  else {        /* Multiple block write */
248
    if (CardType & CT_SDC) send_cmd(ACMD23, count);
249
    if (send_cmd(CMD25, sector) == 0) {  /* WRITE_MULTIPLE_BLOCK */
250
      do {
251
        if (!xmit_datablock(buff, 0xFC)) break;
252
        buff += 512;
253
      } while (--count);
254
      if (!xmit_datablock(0, 0xFD))  /* STOP_TRAN token */
255
        count = 1;
256
    }
257
  }
258
  deselect();
259

260
  return count ? RES_ERROR : RES_OK;
261
}
262
#endif /* _READONLY */
263

264

265
/*-----------------------------------------------------------------------*/
266
/* Power Control  (Platform dependent)                                   */
267
/*-----------------------------------------------------------------------*/
268
/* When the target system does not support socket power control, there   */
269
/* is nothing to do in these functions and chk_power always returns 1.   */
270

271
static
272
void power_on (void)
273
{
274
    int cnt;
275
    
276
    /* Setup SPI */
277
  // Setup CS as output
278
  CS_SETOUT();
279
    SPICONbits.ON = 0;
280

281
    SPISTATbits.SPIROV = 0;
282

283
    SPICONbits.MSTEN = 1;
284
    SPICONbits.CKP = 1;
285
    SPICONbits.CKE = 0;
286
    SPICONbits.SMP = 1;
287
    SPICONbits.MODE16 = 0;
288
    SPICONbits.MODE32 = 0;
289
    SPICONbits.SRXISEL = 1;
290
    // Enables SPI port to run in Enhanced Buffer mode
291
    SPICONbits.ENHBUF = 0;
292
  SPICONbits.ON = 1;
293
}
294

295
static
296
void power_off (void)
297
{
298
  select();      /* Wait for card ready */
299
  deselect();
300

301
  SPICONbits.ON = 0;      /* Disable SPI */
302

303
  Stat |= STA_NOINIT;  /* Set STA_NOINIT */
304
}
305

306
/*-----------------------------------------------------------------------*/
307
/* Receive a data packet from MMC                                        */
308
/*-----------------------------------------------------------------------*/
309
static
310
int rcvr_datablock (  /* 1:OK, 0:Failed */
311
  BYTE *buff,      /* Data buffer to store received data */
312
  UINT btr      /* Byte count (must be multiple of 4) */
313
)
314
{
315
  BYTE token;
316

317

318
  Timer1 = 100;
319
  do {              /* Wait for data packet in timeout of 100ms */
320
    token = rcvr_spi();
321
  } while ((token == 0xFF) && Timer1);
322

323
  if(token != 0xFE) return 0;    /* If not valid data token, retutn with error */
324

325
  do {              /* Receive the data block into buffer */
326
    rcvr_spi_m(buff++);
327
    rcvr_spi_m(buff++);
328
    rcvr_spi_m(buff++);
329
    rcvr_spi_m(buff++);
330
  } while (btr -= 4);
331
  rcvr_spi();            /* Discard CRC */
332
  rcvr_spi();
333

334
  return 1;            /* Return with success */
335
}
336
/*--------------------------------------------------------------------------
337

338
   Public Functions
339

340
---------------------------------------------------------------------------*/
341

342

343
/*-----------------------------------------------------------------------*/
344
/* Initialize Disk Drive                                                 */
345
/*-----------------------------------------------------------------------*/
346

347
DSTATUS disk_initialize (
348
  BYTE drv    /* Physical drive nmuber (0) */
349
)
350
{
351
  BYTE n, cmd, ty, ocr[4];
352

353
  power_on();              /* Force socket power on */
354
        FCLK_SLOW();
355
  for (n = 80; n; n--) rcvr_spi();  /* 80 dummy clocks */
356

357
  ty = 0;
358
  if (send_cmd(CMD0, 0) == 1) {      /* Enter Idle state */
359
    Timer1 = 100;            /* Initialization timeout of 1000 msec */
360
    if (send_cmd(CMD8, 0x1AA) == 1) {  /* SDv2? */
361
      for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();      /* Get trailing return value of R7 resp */
362
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {        /* The card can work at vdd range of 2.7-3.6V */
363
        while (Timer1 && send_cmd(ACMD41, 0x40000000));  /* Wait for leaving idle state (ACMD41 with HCS bit) */
364
        if (Timer1 && send_cmd(CMD58, 0) == 0) {      /* Check CCS bit in the OCR */
365
          for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
366
          ty = (ocr[0] & 0x40) ? CT_SD2|CT_BLOCK : CT_SD2;  /* SDv2 */
367
        }
368
      }
369
    } else {              /* SDv1 or MMCv3 */
370
      if (send_cmd(ACMD41, 0) <= 1)   {
371
        ty = CT_SD1; cmd = ACMD41;  /* SDv1 */
372
      } else {
373
        ty = CT_MMC; cmd = CMD1;  /* MMCv3 */
374
      }
375
      while (Timer1 && send_cmd(cmd, 0));    /* Wait for leaving idle state */
376
      if (!Timer1 || send_cmd(CMD16, 512) != 0)  /* Set read/write block length to 512 */
377
        ty = 0;
378
    }
379
  }
380
  CardType = ty;
381
  deselect();
382

383
  if (ty) {      /* Initialization succeded */
384
    Stat &= ~STA_NOINIT;  /* Clear STA_NOINIT */
385
    FCLK_FAST();
386
  } else {      /* Initialization failed */
387
    power_off();
388
  }
389

390
  return Stat;
391
}
392

393

394

395
/*-----------------------------------------------------------------------*/
396
/* Get Disk Status                                                       */
397
/*-----------------------------------------------------------------------*/
398

399
DSTATUS disk_status (
400
  BYTE drv    /* Physical drive nmuber (0) */
401
)
402
{
403
  if (drv) return STA_NOINIT;    /* Supports only single drive */
404
  return Stat;
405
}
406

407

408

409
/*-----------------------------------------------------------------------*/
410
/* Read Sector(s)                                                        */
411
/*-----------------------------------------------------------------------*/
412

413
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count)
414
{
415
  if (pdrv || !count) return RES_PARERR;
416
  if (Stat & STA_NOINIT) return RES_NOTRDY;
417

418
  if (!(CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
419

420
  if (count == 1) {    /* Single block read */
421
    if ((send_cmd(CMD17, sector) == 0)  /* READ_SINGLE_BLOCK */
422
      && rcvr_datablock(buff, 512))
423
      count = 0;
424
  }
425
  else {        /* Multiple block read */
426
    if (send_cmd(CMD18, sector) == 0) {  /* READ_MULTIPLE_BLOCK */
427
      do {
428
        if (!rcvr_datablock(buff, 512)) break;
429
        buff += 512;
430
      } while (--count);
431
      send_cmd(CMD12, 0);        /* STOP_TRANSMISSION */
432
    }
433
  }
434
  deselect();
435

436
  return count ? RES_ERROR : RES_OK;
437
}
438

439
/*-----------------------------------------------------------------------*/
440
/* Write Sector(s)                                                       */
441
/*-----------------------------------------------------------------------*/
442

443
#if _READONLY == 0
444
DRESULT w (
445
  BYTE drv,        /* Physical drive nmuber (0) */
446
  const BYTE *buff,    /* Pointer to the data to be written */
447
  DWORD sector,      /* Start sector number (LBA) */
448
  BYTE count        /* Sector count (1..255) */
449
)
450
{
451
  if (drv || !count) return RES_PARERR;
452
  if (Stat & STA_NOINIT) return RES_NOTRDY;
453
  if (Stat & STA_PROTECT) return RES_WRPRT;
454

455
  if (!(CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
456

457
  if (count == 1) {    /* Single block write */
458
    if ((send_cmd(CMD24, sector) == 0)  /* WRITE_BLOCK */
459
      && xmit_datablock(buff, 0xFE))
460
      count = 0;
461
  }
462
  else {        /* Multiple block write */
463
    if (CardType & CT_SDC) send_cmd(ACMD23, count);
464
    if (send_cmd(CMD25, sector) == 0) {  /* WRITE_MULTIPLE_BLOCK */
465
      do {
466
        if (!xmit_datablock(buff, 0xFC)) break;
467
        buff += 512;
468
      } while (--count);
469
      if (!xmit_datablock(0, 0xFD))  /* STOP_TRAN token */
470
        count = 1;
471
    }
472
  }
473
  deselect();
474

475
  return count ? RES_ERROR : RES_OK;
476
}
477
#endif /* _READONLY */
478

479

480

481
/*-----------------------------------------------------------------------*/
482
/* Miscellaneous Functions                                               */
483
/*-----------------------------------------------------------------------*/
484

485
DRESULT disk_ioctl (
486
  BYTE drv,    /* Physical drive nmuber (0) */
487
  BYTE ctrl,    /* Control code */
488
  void *buff    /* Buffer to send/receive data block */
489
)
490
{
491
  DRESULT res;
492
  BYTE n, csd[16], *ptr = buff;
493
  DWORD csize;
494

495

496
  if (drv) return RES_PARERR;
497
  if (Stat & STA_NOINIT) return RES_NOTRDY;
498

499
  res = RES_ERROR;
500
  switch (ctrl) {
501
    case CTRL_SYNC :  /* Flush dirty buffer if present */
502
      if (select()) {
503
        deselect();
504
        res = RES_OK;
505
      }
506
      break;
507

508
    case GET_SECTOR_COUNT :  /* Get number of sectors on the disk (WORD) */
509
      if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
510
        if ((csd[0] >> 6) == 1) {  /* SDv2? */
511
          csize = csd[9] + ((WORD)csd[8] << 8) + 1;
512
          *(DWORD*)buff = (DWORD)csize << 10;
513
        } else {          /* SDv1 or MMCv2 */
514
          n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
515
          csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
516
          *(DWORD*)buff = (DWORD)csize << (n - 9);
517
        }
518
        res = RES_OK;
519
      }
520
      break;
521

522
    case GET_SECTOR_SIZE :  /* Get sectors on the disk (WORD) */
523
      *(WORD*)buff = 512;
524
      res = RES_OK;
525
      break;
526

527
    case GET_BLOCK_SIZE :  /* Get erase block size in unit of sectors (DWORD) */
528
      if (CardType & CT_SD2) {  /* SDv2? */
529
        if (send_cmd(ACMD13, 0) == 0) {    /* Read SD status */
530
          rcvr_spi();
531
          if (rcvr_datablock(csd, 16)) {        /* Read partial block */
532
            for (n = 64 - 16; n; n--) rcvr_spi();  /* Purge trailing data */
533
            *(DWORD*)buff = 16UL << (csd[10] >> 4);
534
            res = RES_OK;
535
          }
536
        }
537
      } else {          /* SDv1 or MMCv3 */
538
        if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {  /* Read CSD */
539
          if (CardType & CT_SD1) {  /* SDv1 */
540
            *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
541
          } else {          /* MMCv3 */
542
            *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
543
          }
544
          res = RES_OK;
545
        }
546
      }
547
      break;
548

549
    case MMC_GET_TYPE :    /* Get card type flags (1 byte) */
550
      *ptr = CardType;
551
      res = RES_OK;
552
      break;
553

554
    case MMC_GET_CSD :  /* Receive CSD as a data block (16 bytes) */
555
      if ((send_cmd(CMD9, 0) == 0)  /* READ_CSD */
556
        && rcvr_datablock(buff, 16))
557
        res = RES_OK;
558
      break;
559

560
    case MMC_GET_CID :  /* Receive CID as a data block (16 bytes) */
561
      if ((send_cmd(CMD10, 0) == 0)  /* READ_CID */
562
        && rcvr_datablock(buff, 16))
563
        res = RES_OK;
564
      break;
565

566
    case MMC_GET_OCR :  /* Receive OCR as an R3 resp (4 bytes) */
567
      if (send_cmd(CMD58, 0) == 0) {  /* READ_OCR */
568
        for (n = 0; n < 4; n++)
569
          *((BYTE*)buff+n) = rcvr_spi();
570
        res = RES_OK;
571
      }
572
      break;
573

574
    case MMC_GET_SDSTAT :  /* Receive SD statsu as a data block (64 bytes) */
575
      if (send_cmd(ACMD13, 0) == 0) {  /* SD_STATUS */
576
        rcvr_spi();
577
        if (rcvr_datablock(buff, 64))
578
          res = RES_OK;
579
      }
580
      break;
581

582
    default:
583
      res = RES_PARERR;
584
  }
585

586
  deselect();
587

588
  return res;
589
}
590

591

592

593
/*-----------------------------------------------------------------------*/
594
/* Device Timer Interrupt Procedure  (Platform dependent)                */
595
/*-----------------------------------------------------------------------*/
596
/* This function must be called in period of 1ms                         */
597

598

599
void disk_timerproc (void)
600
{
601
}

Beim Debuggen hänge ich in dem wait_ready block
1
static
2
BYTE wait_ready (void)
3
{
4
  BYTE res;
5

6

7
  Timer2 = 500;  /* Wait for ready in timeout of 500ms */
8
  rcvr_spi();
9
  do
10
    res = rcvr_spi();
11
  while ((res != 0xFF) && Timer2);
12

13
  return res;
14
}

bei der do while schleife
1
while ((res != 0xFF) && Timer2);
hängt der Microcontroller sich auf, obwohl die Bedingung erfüllt ist.
res = 0x00 und Timer2 =500

An soso:
Was genau meinst du mit den 1ms Timer? Bin davon ausgegangen, das in dem 
Beispiel, das dementsprechend aufgerufen wird...
Wie kann ich das feststellen ob die SPI-Routine läuft?
Was meinst du mit Scope dranhängen?

LG
Malte
Gast #5600533
Lesenswert?

Wenn du in "wait_ready" hängst, heißt dass, dass du kein "ready" von der 
SD-Karte bekommst. Das kann eine defekte SPI-Routine sein. Dass er 
überhaupt hängenbleiben kann, hängt mit dem Timer zusammen.

Deine "disk_timerproc (void)" ist leer, das ist vermutlich schon mal 
falsch. Und außerdem musst du die jede ms aufrufen, sonst kann FATFs 
keine Zeit messen.

Was die SPI angeht:
Man muss auch mal schauen, ob die Versorgung da ist, ob bei SCK der Takt 
komt, MOSI, MISO Daten daherbringen und Chipselect betätigt wird. Sehr 
schnell hat man ein ANSEL-Bit vergessen oder ein obskures Bit in der 
SPI-Config und so weiter.
Darum ist es immer eine gute Idee sich zunächst anzusehen, ob das 
überhaupt generell funktionieren kann. Idealerweise mit dem Oszilloskop, 
dann sieht man elektrische Probleme auch gleich. Nicht dass du einen 
Hardwarefehler in Software suchst ;-)

Mein Rat wäre:
Schau dir die Seite von elm chan an, der hat eine brauchbare Doku:
http://elm-chan.org/fsw/ff/00index_e.html
Leg dein aktuelles Projekt zunächst zur Seite. Lade dir die "FatFs 
sample projects for various platforms October 14, 2018", nimm das PIC24 
example (das ist glaube ich mit Software-SPI) und bring das zum Laufen. 
PIC24 und PIC32 sind sich sehr ähnlich, das lässt sich ziemlich einfach 
portieren. Wenn das funktioniert, ist das Austauschen der SPI-Routinen 
gegen Hardware-SPI ist sehr viel einfacher.

Und nicht aufgeben. Es lohnt sich, sich da durchzubeißen.
Gast #5600736
Lesenswert?

Michael E. schrieb:
> Vielleicht die blöde Standard-Falle Compiler-Optimierung?

Ich vermute eher, das Problem ist die Abbruchbedingung der 
while-Schleife:
1
    res = rcvr_spi();
2
  while ((res != 0xFF) && Timer2);

Er bekommt VERMUTLICH (wissen tun wir es nicht!) weder etwas !=0xFF von 
der SPI zurück (res!=0xFF), noch kann der Timer2 auf 0 gehen.

Die Schleife bricht nie ab.

Dass die SPI keine Date ungleich 0xFF liefert, deutet auf ein Problem 
mit der SPI-Routine hin. Oder auf ein generelles Problem mit den 
Leitungen zur SD-Karte. Drum: Nachprüfen mit dem Oszilloskop.

Dass der Timer nicht abläuft liegt schlicht daran, dass die 
Tiemer-routine nicht behandelt wird.

Die Frage ist, was mit Aufhängen gemeint ist. Aber PIC32 haben 
Exceptions, wenn man die nutzt, kann man jeden "Aufhänge" abfangen. Ich 
verwende Exceptions oft für  Debugzwecke. Code:
1
/*exception handlers*/
2
/*
3
 * Exception cause:
4
    0       0x00 Int Interrupt
5
   1-3      0x01 ? Reserved
6
   4        0x04 AdEL Address error exception (load or instruction fetch)
7
   5        0x05 AdES Address error exception (store)
8
   6        0x06 IBE Bus error exception (instruction fetch)
9
   7        0x07 DBE Bus error exception (data reference: load or store)
10
   8        0x08 Sys Syscall exception
11
   9        0x09 Bp Breakpoint exception
12
   10       0x0A RI Reserved instruction exception
13
   11       0x0B CPU Coprocessor Unusable exception
14
   12       0x0C Ov Arithmetic Overflow exception
15
   13       0x0D Tr Trap exception
16
   14-31    0x0E-0x1F ? Reserved
17
 */
18
static uint32_t excep_addr, excep_vaddr, excep_cause, exception;
19
void _simple_tlb_refill_exception_handler(void){
20
    uint32_t cause;
21
    asm volatile("mfc0 %0,$8" : "=r" (excep_vaddr)); 
22
    asm volatile("mfc0 %0,$13" : "=r" (cause)); 
23
    asm volatile("mfc0 %0,$14" : "=r" (excep_addr)); 
24
    excep_cause = (cause&0x000000FF) >> 2;
25
    exception = 1;
26
}
27
void _general_exception_handler (void){
28
    uint32_t cause;
29
    asm volatile("mfc0 %0,$8" : "=r" (excep_vaddr)); 
30
    asm volatile("mfc0 %0,$13" : "=r" (cause)); 
31
    asm volatile("mfc0 %0,$14" : "=r" (excep_addr)); 
32
    excep_cause = (cause&0x000000FF) >> 2;
33
    exception = 2;
34
}
Da hab ich immer Breakpoints sitzen. Es ist manchmal nützlich zu wissen, 
was genau die Ursache des "Aufhängers" ist. Und wenn man beim 
Durchsteppen im Exceptionhandler landet (z.B. cause = 0x07) sollte man 
sich seine Pointer genau ansehen ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren