title: Editing FatFS generic example for dsPIC
body: <p>I'm attempting to use FatFS (<a href="http://elm-chan.org/fsw/ff/00index_e.html" rel="nofollow">http://elm-chan.org/fsw/ff/00index_e.html</a>) as a means to communicate with an SD card, using SPI. </p>
  
  <p>The FatFS website has a number of examples, however I'm not finding them easy to understand or follow. Two examples apply to me in the downloadable zip, one for 'generic' microcontrollers and another for a PIC24. Although the PIC24 would seem ideally similar to my dsPIC33F the code is very hard to understand, with a specific application which I don't care for. </p>
  
  <p>The generic code is much easier to understand, and performs a very simple application of creating a txt file, writing to it, then closing it. However, I'm having difficulty altering the code to work with my PIC. </p>
  
  <p>I've got the dsPIC33FJ128GP802. I've added code to the generic example to remap the SPI pins, set up the internal oscillator, and set up and start the SPI module:</p>
  
  <pre><code>// Configure Oscillator to operate the device at 40Mhz
  // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
  // Fosc= 8M*40/(2*2)=80Mhz for 8M input clock
  PLLFBD = 38; // M=40
  CLKDIVbits.PLLPOST = 0; // N1=2
  CLKDIVbits.PLLPRE = 0;  // N2=2
  OSCTUN = 0;             // Tune FRC oscillator, if FRC is used
  
  // Unlocks PPS, make change, and locks again.
  __builtin_write_OSCCONL(OSCCONL &amp; ~(1 &lt;&lt; 6));
  
  // OUTPUT
  RPOR6bits.RP12R = 7; // RP12 = SDO1 which is SPI1 DATA OUTPUT.
  RPOR7bits.RP15R = 8; // RP15 = SCK1OUT which is SPI1 CLOCK OUTPUT.
  
  // INPUT
  RPINR21bits.SS1R = 13; // RP13 = SS1R which is SPI1 SLAVE/CHIP SELECT.
  RPINR20bits.SDI1R = 14; // RP14 = SDI1R which is SPI DATA INTPUT.
  
  __builtin_write_OSCCONL(OSCCONL | (1 &lt;&lt; 6));
  
  SPI1STAT = 0;
  SPI1STATbits.SPIEN = 0; // Disable SPI module.
  SPI1STATbits.SPISIDL = 0; // Continue in idle mode.
  SPI1STATbits.SPIROV = 0; // No overflow.
  SPI1STATbits.SPITBF = 0; // Transmit started, SPIxTXB is empty.
  SPI1STATbits.SPIRBF = 0; // Receive is not complete, SPIxRXB is empty.
  
  SPI1CON1 = 0;
  SPI1CON1bits.DISSCK = 0; // Internal clock enabled.
  SPI1CON1bits.DISSDO = 0; // SD0 controlled by the module.
  SPI1CON1bits.MODE16 = 0; // 8 bit mode.
  SPI1CON1bits.SMP = 0; // Input data sampled at middle of data output time.
  SPI1CON1bits.CKE = 1; // Serial output data changes on transition from idle.
  SPI1CON1bits.SSEN = 0; // Slave select is not used by the module. 
  SPI1CON1bits.CKP = 0; // Idle state for clock is low.
  SPI1CON1bits.MSTEN = 1; // Master mode enabled.
  SPI1CON1bits.SPRE = 0b000; // Secondary prescale 8:1
  SPI1CON1bits.PPRE = 0b01; // Primary prescale 16:1.
  
  SPI1CON2 = 0;
  SPI1CON2bits.FRMEN = 0; // Framed SPI disabled.
  SPI1CON2bits.SPIFSD = 0; // Framed sync pulse output.(N/A)
  SPI1CON2bits.FRMPOL = 0; // Framed sync pulse is active-low.(N/A)
  SPI1CON2bits.FRMDLY = 0; // Framed sync pulse precedes first bit clock.(N/A)
  
  SPI1STATbits.SPIEN = 1; // Enable SPI module.
  </code></pre>
  
  <p>PIC to SD card is:</p>
  
  <ul>
  <li>RP15, SPI clock output, to SCK</li>
  <li>RP14, SPI data input, to DO (data out).</li>
  <li>RP13, SPI slave select, to CS.</li>
  <li>RP12, SPI data output, to DI (data in).</li>
  <li>SD card CD not connected.</li>
  </ul>
  
  <p>Could someone that's experienced with FatFS please help me make the necessary alterations. Running the code so far gets as far as f_open where it returns the error FR_NOT_READY.</p>
  
  <p>For now I'm not trying to do anything fancy, just create a file and write to it. I've seen many applications which use external crystal oscillators, which I don't have. Is this a necessity for SPI? I'm new to SPI, been using I2C before this. </p>
  
  <p>Within the mmcbb.c file for the generic example I had to make some changes to remove some errors I was getting, the delay function of theirs I replaced with my own function to create a delay of a similar timing as it was throwing an error, I also removed the INIT_PORT() that appears in disk_initialize(BYTE pdrv) as it was throwing an error and I initialised the ports before getting into any of the FatFS code, right at the start of the main. At the top of mmcbb.c there are #define which needed the corresponding ports to be added to how I set up the SPI, which I did (RBx pins are the same as the RPx I set above):</p>
  
  <pre><code>#define CS_H()      PORTBbits.RB13 |= 0x01  /* Set MMC CS "high" */
  #define CS_L()      PORTBbits.RB13 &amp;= 0xFE  /* Set MMC CS "low" */
  #define CK_H()      PORTBbits.RB15 |= 0x02  /* Set MMC SCLK "high" */
  #define CK_L()      PORTBbits.RB15 &amp;= 0xFD  /* Set MMC SCLK "low" */
  #define DI_H()      PORTBbits.RB14 |= 0x04  /* Set MMC DI "high" */
  #define DI_L()      PORTBbits.RB14 &amp;= 0xFB  /* Set MMC DI "low" */
  #define DO      (PORTBbits.RB12 &amp; 0x08) /* Test for MMC DO ('H':true, 'L':false) */
  </code></pre>
  
  <p>The bitwise operators were already there, I merely added the PORTBbits.RBxx.</p>
  
  <p>That's all the changes I've made, but I've found finding information on using any library for SD card manipulation particularly hard online (FatFS and MDDFS). Any help will be most appreciated!</p>