Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Committer:
AjK
Date:
Mon Oct 11 10:34:55 2010 +0000
Revision:
0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:0a841b89d614 1 /*-----------------------------------------------------------------------*/
AjK 0:0a841b89d614 2 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
AjK 0:0a841b89d614 3 /*-----------------------------------------------------------------------*/
AjK 0:0a841b89d614 4 /* This is a stub disk I/O module that acts as front end of the existing */
AjK 0:0a841b89d614 5 /* disk I/O modules and attach it to FatFs module with common interface. */
AjK 0:0a841b89d614 6 /*-----------------------------------------------------------------------*/
AjK 0:0a841b89d614 7
AjK 0:0a841b89d614 8 #include "diskio.h"
AjK 0:0a841b89d614 9 #include "sowb.h"
AjK 0:0a841b89d614 10 #include "user.h"
AjK 0:0a841b89d614 11 #include "gpio.h"
AjK 0:0a841b89d614 12 #include "gps.h"
AjK 0:0a841b89d614 13 #include "ssp0.h"
AjK 0:0a841b89d614 14
AjK 0:0a841b89d614 15 #define R1_IDLE_STATE (1 << 0)
AjK 0:0a841b89d614 16 #define R1_ERASE_RESET (1 << 1)
AjK 0:0a841b89d614 17 #define R1_ILLEGAL_COMMAND (1 << 2)
AjK 0:0a841b89d614 18 #define R1_COM_CRC_ERROR (1 << 3)
AjK 0:0a841b89d614 19 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
AjK 0:0a841b89d614 20 #define R1_ADDRESS_ERROR (1 << 5)
AjK 0:0a841b89d614 21 #define R1_PARAMETER_ERROR (1 << 6)
AjK 0:0a841b89d614 22
AjK 0:0a841b89d614 23 //******************************************************************************************************************
AjK 0:0a841b89d614 24 // MBED SPI/CS Select functions.... Modify for your layout.
AjK 0:0a841b89d614 25 //**************************************************************************************
AjK 0:0a841b89d614 26
AjK 0:0a841b89d614 27 //SPI _spi(p5, p6, p7); // mosi, miso, sclk
AjK 0:0a841b89d614 28 //DigitalOut _cs(p8);
AjK 0:0a841b89d614 29 //DigitalOut P20(p20);
AjK 0:0a841b89d614 30 //SPI * _spi;
AjK 0:0a841b89d614 31
AjK 0:0a841b89d614 32
AjK 0:0a841b89d614 33 //******************************************************************************************************************
AjK 0:0a841b89d614 34 // Low Level Sector Access Function Prototypes('C' Castrated versions of Simon Ford's C++ MBED SDFileSystem class
AjK 0:0a841b89d614 35 //******************************************************************************************************************
AjK 0:0a841b89d614 36 int _cmd(int cmd, int arg);
AjK 0:0a841b89d614 37 int _cmd8(void);
AjK 0:0a841b89d614 38 int _cmdR2(int cmd, int arg);
AjK 0:0a841b89d614 39 int _read(BYTE *buffer, int length);
AjK 0:0a841b89d614 40 int _write(BYTE *buffer, int length);
AjK 0:0a841b89d614 41 int ext_bits(BYTE *data, int msb, int lsb);
AjK 0:0a841b89d614 42 int _sd_sectors();
AjK 0:0a841b89d614 43 int _sectors;
AjK 0:0a841b89d614 44
AjK 0:0a841b89d614 45 #define SD_COMMAND_TIMEOUT 5000
AjK 0:0a841b89d614 46
AjK 0:0a841b89d614 47 void deassert_cs(void) {
AjK 0:0a841b89d614 48 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 49 }
AjK 0:0a841b89d614 50
AjK 0:0a841b89d614 51 //******************************************************************************************************************
AjK 0:0a841b89d614 52 // Sector Access functions for CHAN FatFs
AjK 0:0a841b89d614 53 //******************************************************************************************************************
AjK 0:0a841b89d614 54
AjK 0:0a841b89d614 55 DRESULT disk_ioctl (
AjK 0:0a841b89d614 56 BYTE drv, /* Physical drive nmuber (0..) */
AjK 0:0a841b89d614 57 BYTE ctrl, /* Control code */
AjK 0:0a841b89d614 58 void *buff /* Buffer to send/receive control data */
AjK 0:0a841b89d614 59 )
AjK 0:0a841b89d614 60 {
AjK 0:0a841b89d614 61 DRESULT res;
AjK 0:0a841b89d614 62
AjK 0:0a841b89d614 63 switch(ctrl)
AjK 0:0a841b89d614 64 {
AjK 0:0a841b89d614 65 case CTRL_SYNC:
AjK 0:0a841b89d614 66 res = RES_OK;
AjK 0:0a841b89d614 67 break;
AjK 0:0a841b89d614 68
AjK 0:0a841b89d614 69 case GET_SECTOR_SIZE:
AjK 0:0a841b89d614 70 res = RES_OK;
AjK 0:0a841b89d614 71 *(WORD *)buff = 512;
AjK 0:0a841b89d614 72 break;
AjK 0:0a841b89d614 73
AjK 0:0a841b89d614 74 case GET_SECTOR_COUNT:
AjK 0:0a841b89d614 75 res = RES_OK;
AjK 0:0a841b89d614 76 *(DWORD *)buff = (WORD)_sd_sectors();
AjK 0:0a841b89d614 77 break;
AjK 0:0a841b89d614 78
AjK 0:0a841b89d614 79 case GET_BLOCK_SIZE:
AjK 0:0a841b89d614 80 res = RES_OK;
AjK 0:0a841b89d614 81 *(DWORD *)buff = 1;
AjK 0:0a841b89d614 82 break;
AjK 0:0a841b89d614 83
AjK 0:0a841b89d614 84 default:
AjK 0:0a841b89d614 85 res = RES_OK;
AjK 0:0a841b89d614 86 break;
AjK 0:0a841b89d614 87 }
AjK 0:0a841b89d614 88 return res;
AjK 0:0a841b89d614 89 }
AjK 0:0a841b89d614 90
AjK 0:0a841b89d614 91 int _cmd58() {
AjK 0:0a841b89d614 92 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 93 int arg = 0;
AjK 0:0a841b89d614 94
AjK 0:0a841b89d614 95 /* Request use of SSP0. */
AjK 0:0a841b89d614 96 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 97
AjK 0:0a841b89d614 98 // send a command
AjK 0:0a841b89d614 99 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 100 SSP0_WRITE_BYTE(0x40 | 58);
AjK 0:0a841b89d614 101 SSP0_WRITE_BYTE(arg >> 24);
AjK 0:0a841b89d614 102 SSP0_WRITE_BYTE(arg >> 16);
AjK 0:0a841b89d614 103 SSP0_WRITE_BYTE(arg >> 8);
AjK 0:0a841b89d614 104 SSP0_WRITE_BYTE(arg >> 0);
AjK 0:0a841b89d614 105 SSP0_WRITE_BYTE(0x95);
AjK 0:0a841b89d614 106 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 107 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 108
AjK 0:0a841b89d614 109 //_spi->write(0x40 | 58);
AjK 0:0a841b89d614 110 //_spi->write(arg >> 24);
AjK 0:0a841b89d614 111 //_spi->write(arg >> 16);
AjK 0:0a841b89d614 112 //_spi->write(arg >> 8);
AjK 0:0a841b89d614 113 //_spi->write(arg >> 0);
AjK 0:0a841b89d614 114 //_spi->write(0x95);
AjK 0:0a841b89d614 115
AjK 0:0a841b89d614 116 // wait for the repsonse (response[7] == 0)
AjK 0:0a841b89d614 117 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 118 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 119 for(int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
AjK 0:0a841b89d614 120 int response = LPC_SSP0->DR;
AjK 0:0a841b89d614 121 if(!(response & 0x80)) {
AjK 0:0a841b89d614 122 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 123 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 124 int ocr = LPC_SSP0->DR << 24;
AjK 0:0a841b89d614 125 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 126 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 127 ocr |= LPC_SSP0->DR << 16;
AjK 0:0a841b89d614 128 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 129 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 130 ocr |= LPC_SSP0->DR << 8;
AjK 0:0a841b89d614 131 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 132 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 133 ocr |= LPC_SSP0->DR << 0;
AjK 0:0a841b89d614 134 // printf("OCR = 0x%08X\n", ocr);
AjK 0:0a841b89d614 135 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 136 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 137 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 138 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 139 // _spi->write(0xFF);
AjK 0:0a841b89d614 140 SSP0_release();
AjK 0:0a841b89d614 141 return response;
AjK 0:0a841b89d614 142 }
AjK 0:0a841b89d614 143 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 144 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 145 }
AjK 0:0a841b89d614 146 SDCARD_CS_DEASSERT;
AjK 0:0a841b89d614 147 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 148 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 149 SSP0_release();
AjK 0:0a841b89d614 150 return -1; // timeout
AjK 0:0a841b89d614 151 }
AjK 0:0a841b89d614 152
AjK 0:0a841b89d614 153 int initialise_card_v1() {
AjK 0:0a841b89d614 154
AjK 0:0a841b89d614 155 /* Request use of SSP0. */
AjK 0:0a841b89d614 156 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 157
AjK 0:0a841b89d614 158 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
AjK 0:0a841b89d614 159 _cmd(55, 0);
AjK 0:0a841b89d614 160 if(_cmd(41, 0) == 0) {
AjK 0:0a841b89d614 161 SSP0_release();
AjK 0:0a841b89d614 162 return 0; //SDCARD_V1;
AjK 0:0a841b89d614 163 }
AjK 0:0a841b89d614 164 }
AjK 0:0a841b89d614 165
AjK 0:0a841b89d614 166 //fprintf(stderr, "Timeout waiting for v1.x card\n");
AjK 0:0a841b89d614 167 SSP0_release();
AjK 0:0a841b89d614 168 return STA_NOINIT;
AjK 0:0a841b89d614 169 }
AjK 0:0a841b89d614 170
AjK 0:0a841b89d614 171 int initialise_card_v2() {
AjK 0:0a841b89d614 172 int c41, c58, r;
AjK 0:0a841b89d614 173
AjK 0:0a841b89d614 174 /* Request use of SSP0. */
AjK 0:0a841b89d614 175 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 176
AjK 0:0a841b89d614 177 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
AjK 0:0a841b89d614 178 _cmd(55, 0);
AjK 0:0a841b89d614 179 c41 = _cmd(41, 0);
AjK 0:0a841b89d614 180 if(c41 == 0) {
AjK 0:0a841b89d614 181 SSP0_release();
AjK 0:0a841b89d614 182 c58 = _cmd58();
AjK 0:0a841b89d614 183 //fprintf(stderr, "C41 returned %02x and C58 returned %02x\r\n", c41, c58);
AjK 0:0a841b89d614 184 return 0; //SDCARD_V2;
AjK 0:0a841b89d614 185 }
AjK 0:0a841b89d614 186 }
AjK 0:0a841b89d614 187
AjK 0:0a841b89d614 188
AjK 0:0a841b89d614 189 //fprintf(stderr, "Timeout waiting for v2.x card response=0x%04x\r\n", c41);
AjK 0:0a841b89d614 190 SSP0_release();
AjK 0:0a841b89d614 191 return STA_NOINIT;
AjK 0:0a841b89d614 192 }
AjK 0:0a841b89d614 193
AjK 0:0a841b89d614 194 DSTATUS disk_initialize(BYTE Drive) {
AjK 0:0a841b89d614 195 int i, cmd8_r;
AjK 0:0a841b89d614 196 uint32_t cpsr = LPC_SSP0->CPSR;
AjK 0:0a841b89d614 197
AjK 0:0a841b89d614 198 //_spi = new SPI(p5, p6, p7);
AjK 0:0a841b89d614 199
AjK 0:0a841b89d614 200 /* Request use of SSP0. */
AjK 0:0a841b89d614 201 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 202
AjK 0:0a841b89d614 203 //_spi->frequency(100000); // Set to 100kHz for initialisation
AjK 0:0a841b89d614 204 LPC_SSP0->CPSR = 0x64;
AjK 0:0a841b89d614 205 SDCARD_CS_ASSERT; //_cs = 1;
AjK 0:0a841b89d614 206
AjK 0:0a841b89d614 207 // Initialise the card by clocking it a bit (cs = 1)
AjK 0:0a841b89d614 208 for(int i=0; i < 16; i++) {
AjK 0:0a841b89d614 209 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 210 }
AjK 0:0a841b89d614 211 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 212 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 213
AjK 0:0a841b89d614 214
AjK 0:0a841b89d614 215
AjK 0:0a841b89d614 216 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
AjK 0:0a841b89d614 217 if(_cmd(0, 0) != 0x01) {
AjK 0:0a841b89d614 218 //fprintf(stderr, "Not in idle state\n");
AjK 0:0a841b89d614 219 SSP0_release();
AjK 0:0a841b89d614 220 return STA_NOINIT;
AjK 0:0a841b89d614 221 }
AjK 0:0a841b89d614 222
AjK 0:0a841b89d614 223 for(i = 0; i < SD_COMMAND_TIMEOUT; i++) {
AjK 0:0a841b89d614 224 cmd8_r = _cmd8();
AjK 0:0a841b89d614 225 if (cmd8_r == 0 || cmd8_r == 1 || cmd8_r == R1_ILLEGAL_COMMAND) break;
AjK 0:0a841b89d614 226 if (cmd8_r == 0 || cmd8_r == R1_ILLEGAL_COMMAND) break;
AjK 0:0a841b89d614 227 }
AjK 0:0a841b89d614 228
AjK 0:0a841b89d614 229 if ( (cmd8_r & R1_ILLEGAL_COMMAND) != 0) {
AjK 0:0a841b89d614 230 //fprintf(stderr, "V1 %d\r\n", cmd8_r);
AjK 0:0a841b89d614 231 SSP0_release();
AjK 0:0a841b89d614 232 return initialise_card_v1();
AjK 0:0a841b89d614 233 }
AjK 0:0a841b89d614 234
AjK 0:0a841b89d614 235 if (cmd8_r == 0 || cmd8_r == 1) {
AjK 0:0a841b89d614 236 //fprintf(stderr, "V2 %d\r\n", cmd8_r);
AjK 0:0a841b89d614 237 SSP0_release();
AjK 0:0a841b89d614 238 return initialise_card_v2();
AjK 0:0a841b89d614 239 }
AjK 0:0a841b89d614 240
AjK 0:0a841b89d614 241
AjK 0:0a841b89d614 242 //fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?) response = %d\r\n", cmd8_r);
AjK 0:0a841b89d614 243 SSP0_release();
AjK 0:0a841b89d614 244 return STA_NOINIT;
AjK 0:0a841b89d614 245
AjK 0:0a841b89d614 246 // ACMD41 to give host capacity support (repeat until not busy)
AjK 0:0a841b89d614 247 // ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand
AjK 0:0a841b89d614 248 for(int i=0;; i++) {
AjK 0:0a841b89d614 249 _cmd(55, 0);
AjK 0:0a841b89d614 250 int response = _cmd(41, 0);
AjK 0:0a841b89d614 251 if(response == 0) {
AjK 0:0a841b89d614 252 break;
AjK 0:0a841b89d614 253 } else if(i > SD_COMMAND_TIMEOUT) {
AjK 0:0a841b89d614 254 //fprintf(stderr, "Timeout waiting for card\n");
AjK 0:0a841b89d614 255 SSP0_release();
AjK 0:0a841b89d614 256 return STA_NOINIT;
AjK 0:0a841b89d614 257 }
AjK 0:0a841b89d614 258 }
AjK 0:0a841b89d614 259
AjK 0:0a841b89d614 260 _sectors = _sd_sectors();
AjK 0:0a841b89d614 261
AjK 0:0a841b89d614 262 // Set block length to 512 (CMD16)
AjK 0:0a841b89d614 263 if(_cmd(16, 512) != 0) {
AjK 0:0a841b89d614 264 //fprintf(stderr, "Set block timeout\n");
AjK 0:0a841b89d614 265 SSP0_release();
AjK 0:0a841b89d614 266 return STA_NOINIT;
AjK 0:0a841b89d614 267 }
AjK 0:0a841b89d614 268
AjK 0:0a841b89d614 269 LPC_SSP0->CPSR = cpsr;
AjK 0:0a841b89d614 270 SSP0_release();
AjK 0:0a841b89d614 271 //_spi->frequency(10000000); // Set to 10MHz for data transfer
AjK 0:0a841b89d614 272 return 0;
AjK 0:0a841b89d614 273 }
AjK 0:0a841b89d614 274
AjK 0:0a841b89d614 275 DRESULT disk_write(BYTE Drive,const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount)
AjK 0:0a841b89d614 276 {
AjK 0:0a841b89d614 277 BYTE i;
AjK 0:0a841b89d614 278
AjK 0:0a841b89d614 279 BYTE * MyBufOut = (BYTE *)Buffer;
AjK 0:0a841b89d614 280
AjK 0:0a841b89d614 281 /* Request use of SSP0. */
AjK 0:0a841b89d614 282 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 283
AjK 0:0a841b89d614 284 for(i=0;i<SectorCount;i++)
AjK 0:0a841b89d614 285 {
AjK 0:0a841b89d614 286 // set write address for single block (CMD24)
AjK 0:0a841b89d614 287 if(_cmd(24, (SectorNumber + i) * 512 ) != 0) {
AjK 0:0a841b89d614 288 SSP0_release();
AjK 0:0a841b89d614 289 return RES_ERROR;
AjK 0:0a841b89d614 290 }
AjK 0:0a841b89d614 291
AjK 0:0a841b89d614 292 // send the data block
AjK 0:0a841b89d614 293 _write(MyBufOut, 512);
AjK 0:0a841b89d614 294
AjK 0:0a841b89d614 295 MyBufOut+=512;
AjK 0:0a841b89d614 296 }
AjK 0:0a841b89d614 297
AjK 0:0a841b89d614 298 SSP0_release();
AjK 0:0a841b89d614 299 return RES_OK;
AjK 0:0a841b89d614 300 }
AjK 0:0a841b89d614 301
AjK 0:0a841b89d614 302 DRESULT disk_read(BYTE Drive, BYTE * Buffer,DWORD SectorNumber, BYTE SectorCount)
AjK 0:0a841b89d614 303 {
AjK 0:0a841b89d614 304 BYTE i;
AjK 0:0a841b89d614 305
AjK 0:0a841b89d614 306 /* Request use of SSP0. */
AjK 0:0a841b89d614 307 while(!SSP0_request()) WHILE_WAITING_DO_PROCESS_FUNCTIONS;
AjK 0:0a841b89d614 308
AjK 0:0a841b89d614 309 for(i=0;i<SectorCount;i++)
AjK 0:0a841b89d614 310 {
AjK 0:0a841b89d614 311 // set read address for single block (CMD17)
AjK 0:0a841b89d614 312 if(_cmd(17, (SectorNumber+i) * 512) != 0)
AjK 0:0a841b89d614 313 {
AjK 0:0a841b89d614 314 SSP0_release();
AjK 0:0a841b89d614 315 return RES_ERROR;
AjK 0:0a841b89d614 316 }
AjK 0:0a841b89d614 317 // receive the data
AjK 0:0a841b89d614 318 _read(Buffer, 512);
AjK 0:0a841b89d614 319
AjK 0:0a841b89d614 320 Buffer+=512;
AjK 0:0a841b89d614 321 }
AjK 0:0a841b89d614 322
AjK 0:0a841b89d614 323 SSP0_release();
AjK 0:0a841b89d614 324 return RES_OK;
AjK 0:0a841b89d614 325 }
AjK 0:0a841b89d614 326
AjK 0:0a841b89d614 327
AjK 0:0a841b89d614 328 extern "C" DWORD get_fattime(void) {
AjK 0:0a841b89d614 329 GPS_TIME the_time;
AjK 0:0a841b89d614 330
AjK 0:0a841b89d614 331 gps_get_time(&the_time);
AjK 0:0a841b89d614 332
AjK 0:0a841b89d614 333 uint32_t year = (the_time.year - 1980) << 25;
AjK 0:0a841b89d614 334 uint32_t month = the_time.month << 21;
AjK 0:0a841b89d614 335 uint32_t day = the_time.day << 16;
AjK 0:0a841b89d614 336 uint32_t hour = the_time.hour << 11;
AjK 0:0a841b89d614 337 uint32_t minute = the_time.minute << 5;
AjK 0:0a841b89d614 338 uint32_t second = (the_time.second / 2) &0xF;
AjK 0:0a841b89d614 339 return (DWORD)(year | month | day | hour | minute | second);
AjK 0:0a841b89d614 340 }
AjK 0:0a841b89d614 341
AjK 0:0a841b89d614 342 DSTATUS disk_status(BYTE Drive)
AjK 0:0a841b89d614 343 {
AjK 0:0a841b89d614 344 return 0;
AjK 0:0a841b89d614 345 }
AjK 0:0a841b89d614 346
AjK 0:0a841b89d614 347 //**************************************************************************************
AjK 0:0a841b89d614 348 // Low Level Sector Access Functions (Castrated versions of Simon Fords C++ MBED class
AjK 0:0a841b89d614 349 //**************************************************************************************
AjK 0:0a841b89d614 350
AjK 0:0a841b89d614 351 int _cmd(int cmd, int arg) {
AjK 0:0a841b89d614 352 volatile int delay;
AjK 0:0a841b89d614 353
AjK 0:0a841b89d614 354 for (delay = 500; delay; delay--);
AjK 0:0a841b89d614 355 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 356 for (delay = 500; delay; delay--);
AjK 0:0a841b89d614 357
AjK 0:0a841b89d614 358 // send a command
AjK 0:0a841b89d614 359 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 360 SSP0_WRITE_BYTE(0x40 | cmd);
AjK 0:0a841b89d614 361 SSP0_WRITE_BYTE(arg >> 24);
AjK 0:0a841b89d614 362 SSP0_WRITE_BYTE(arg >> 16);
AjK 0:0a841b89d614 363 SSP0_WRITE_BYTE(arg >> 8);
AjK 0:0a841b89d614 364 SSP0_WRITE_BYTE(arg >> 0);
AjK 0:0a841b89d614 365 SSP0_WRITE_BYTE(0x95);
AjK 0:0a841b89d614 366 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 367 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 368
AjK 0:0a841b89d614 369 //_spi->write(0x40 | cmd);
AjK 0:0a841b89d614 370 //_spi->write(arg >> 24);
AjK 0:0a841b89d614 371 //_spi->write(arg >> 16);
AjK 0:0a841b89d614 372 //_spi->write(arg >> 8);
AjK 0:0a841b89d614 373 //_spi->write(arg >> 0);
AjK 0:0a841b89d614 374 //_spi->write(0x95);
AjK 0:0a841b89d614 375
AjK 0:0a841b89d614 376 // wait for the repsonse (response[7] == 0)
AjK 0:0a841b89d614 377 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 378 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 379 for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
AjK 0:0a841b89d614 380 int response = LPC_SSP0->DR;
AjK 0:0a841b89d614 381 if(!(response & 0x80)) {
AjK 0:0a841b89d614 382 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 383 return response;
AjK 0:0a841b89d614 384 }
AjK 0:0a841b89d614 385 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 386 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 387 }
AjK 0:0a841b89d614 388
AjK 0:0a841b89d614 389 SDCARD_CS_ASSERT; //_cs = 1;
AjK 0:0a841b89d614 390 return -1; // timeout
AjK 0:0a841b89d614 391 }
AjK 0:0a841b89d614 392
AjK 0:0a841b89d614 393 int _cmdR2(int cmd, int arg) {
AjK 0:0a841b89d614 394 int response;
AjK 0:0a841b89d614 395
AjK 0:0a841b89d614 396 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 397
AjK 0:0a841b89d614 398 // send a command
AjK 0:0a841b89d614 399 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 400 SSP0_WRITE_BYTE(0x40 | cmd);
AjK 0:0a841b89d614 401 SSP0_WRITE_BYTE(arg >> 24);
AjK 0:0a841b89d614 402 SSP0_WRITE_BYTE(arg >> 16);
AjK 0:0a841b89d614 403 SSP0_WRITE_BYTE(arg >> 8);
AjK 0:0a841b89d614 404 SSP0_WRITE_BYTE(arg >> 0);
AjK 0:0a841b89d614 405 SSP0_WRITE_BYTE(0x95);
AjK 0:0a841b89d614 406 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 407 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 408 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 409
AjK 0:0a841b89d614 410 //_spi->write(0x40 | cmd);
AjK 0:0a841b89d614 411 //_spi->write(arg >> 24);
AjK 0:0a841b89d614 412 //_spi->write(arg >> 16);
AjK 0:0a841b89d614 413 //_spi->write(arg >> 8);
AjK 0:0a841b89d614 414 //_spi->write(arg >> 0);
AjK 0:0a841b89d614 415 //_spi->write(0x95);
AjK 0:0a841b89d614 416 //_spi->write(0xFF);
AjK 0:0a841b89d614 417
AjK 0:0a841b89d614 418 // wait for the repsonse (response[7] == 0)
AjK 0:0a841b89d614 419 //for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
AjK 0:0a841b89d614 420 response = 0;
AjK 0:0a841b89d614 421 SSP0_WRITE_BYTE(0x00);
AjK 0:0a841b89d614 422 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 423 response = (LPC_SSP0->DR & 0xFF);
AjK 0:0a841b89d614 424 response = (response << 8) & 0xFF00;
AjK 0:0a841b89d614 425 SSP0_WRITE_BYTE(0x00);
AjK 0:0a841b89d614 426 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 427 response |= (LPC_SSP0->DR & 0xFF);
AjK 0:0a841b89d614 428 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 429 return response;
AjK 0:0a841b89d614 430 //}
AjK 0:0a841b89d614 431 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 432 return -1; // timeout
AjK 0:0a841b89d614 433 }
AjK 0:0a841b89d614 434
AjK 0:0a841b89d614 435 int _cmd8(void) {
AjK 0:0a841b89d614 436 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 437
AjK 0:0a841b89d614 438 // send a command
AjK 0:0a841b89d614 439 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 440 SSP0_WRITE_BYTE(0x40 | 8);
AjK 0:0a841b89d614 441 SSP0_WRITE_BYTE(00);
AjK 0:0a841b89d614 442 SSP0_WRITE_BYTE(00);
AjK 0:0a841b89d614 443 SSP0_WRITE_BYTE(01);
AjK 0:0a841b89d614 444 SSP0_WRITE_BYTE(0xAA);
AjK 0:0a841b89d614 445 SSP0_WRITE_BYTE(0x87);
AjK 0:0a841b89d614 446 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 447 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 448
AjK 0:0a841b89d614 449 //_spi->write(0x40 | 8); // CMD8
AjK 0:0a841b89d614 450 //_spi->write(0x00); // reserved
AjK 0:0a841b89d614 451 //_spi->write(0x00); // reserved
AjK 0:0a841b89d614 452 //_spi->write(0x01); // 3.3v
AjK 0:0a841b89d614 453 //_spi->write(0xAA); // check pattern
AjK 0:0a841b89d614 454 //_spi->write(0x87); // crc
AjK 0:0a841b89d614 455
AjK 0:0a841b89d614 456 // wait for the repsonse (response[7] == 0)
AjK 0:0a841b89d614 457 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 458 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 459 for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
AjK 0:0a841b89d614 460 char response[5];
AjK 0:0a841b89d614 461 response[0] = LPC_SSP0->DR;
AjK 0:0a841b89d614 462 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 463 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 464 for(int j=1; j<5; j++) {
AjK 0:0a841b89d614 465 response[i] = LPC_SSP0->DR;
AjK 0:0a841b89d614 466 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 467 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 468 }
AjK 0:0a841b89d614 469 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 470 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 471 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 472 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 473 return response[0];
AjK 0:0a841b89d614 474 }
AjK 0:0a841b89d614 475
AjK 0:0a841b89d614 476 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 477 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 478 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 479 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 480 //_spi->write(0xFF);
AjK 0:0a841b89d614 481 return -1; // timeout
AjK 0:0a841b89d614 482 }
AjK 0:0a841b89d614 483
AjK 0:0a841b89d614 484 int _cmd8original(void) {
AjK 0:0a841b89d614 485 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 486
AjK 0:0a841b89d614 487 // send a command
AjK 0:0a841b89d614 488 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 489 SSP0_WRITE_BYTE(0x40 | 8);
AjK 0:0a841b89d614 490 SSP0_WRITE_BYTE(00);
AjK 0:0a841b89d614 491 SSP0_WRITE_BYTE(00);
AjK 0:0a841b89d614 492 SSP0_WRITE_BYTE(01);
AjK 0:0a841b89d614 493 SSP0_WRITE_BYTE(0xAA);
AjK 0:0a841b89d614 494 SSP0_WRITE_BYTE(0x87);
AjK 0:0a841b89d614 495 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 496 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 497
AjK 0:0a841b89d614 498 //_spi->write(0x40 | 8); // CMD8
AjK 0:0a841b89d614 499 //_spi->write(0x00); // reserved
AjK 0:0a841b89d614 500 //_spi->write(0x00); // reserved
AjK 0:0a841b89d614 501 //_spi->write(0x01); // 3.3v
AjK 0:0a841b89d614 502 //_spi->write(0xAA); // check pattern
AjK 0:0a841b89d614 503 //_spi->write(0x87); // crc
AjK 0:0a841b89d614 504
AjK 0:0a841b89d614 505 // wait for the repsonse (response[7] == 0)
AjK 0:0a841b89d614 506 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 507 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 508 for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
AjK 0:0a841b89d614 509 char response[5];
AjK 0:0a841b89d614 510 response[0] = LPC_SSP0->DR;
AjK 0:0a841b89d614 511 if(!(response[0] & 0x80)) {
AjK 0:0a841b89d614 512 //fprintf(stderr, "RS = %d\r\n", response[0]);
AjK 0:0a841b89d614 513 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 514 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 515 for(int j=1; j<5; j++) {
AjK 0:0a841b89d614 516 response[i] = LPC_SSP0->DR;
AjK 0:0a841b89d614 517 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 518 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 519 }
AjK 0:0a841b89d614 520 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 521 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 522 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 523 //_spi->write(0xFF);
AjK 0:0a841b89d614 524 return response[0];
AjK 0:0a841b89d614 525 }
AjK 0:0a841b89d614 526 }
AjK 0:0a841b89d614 527
AjK 0:0a841b89d614 528 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 529 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 530 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 531 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 532 //_spi->write(0xFF);
AjK 0:0a841b89d614 533 return -1; // timeout
AjK 0:0a841b89d614 534 }
AjK 0:0a841b89d614 535
AjK 0:0a841b89d614 536 int _read(BYTE *buffer, int length) {
AjK 0:0a841b89d614 537 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 538
AjK 0:0a841b89d614 539 // read until start byte (0xFF)
AjK 0:0a841b89d614 540 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 541 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 542 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 543 while(LPC_SSP0->DR != 0xFE) {
AjK 0:0a841b89d614 544 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 545 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 546 }
AjK 0:0a841b89d614 547
AjK 0:0a841b89d614 548 // read data
AjK 0:0a841b89d614 549 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 550 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 551 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 552 for(int i=0; i<length; i++) {
AjK 0:0a841b89d614 553 buffer[i] = LPC_SSP0->DR;
AjK 0:0a841b89d614 554 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 555 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 556 }
AjK 0:0a841b89d614 557 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 558 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 559 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 560 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 561 //_spi->write(0xFF); // checksum
AjK 0:0a841b89d614 562 //_spi->write(0xFF);
AjK 0:0a841b89d614 563
AjK 0:0a841b89d614 564 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 565 return 0;
AjK 0:0a841b89d614 566 }
AjK 0:0a841b89d614 567
AjK 0:0a841b89d614 568 int _write(BYTE *buffer, int length) {
AjK 0:0a841b89d614 569 SDCARD_CS_ASSERT; //_cs = 0;
AjK 0:0a841b89d614 570
AjK 0:0a841b89d614 571 // indicate start of block
AjK 0:0a841b89d614 572 SSP0_WRITE_BYTE(0xFE);
AjK 0:0a841b89d614 573 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 574 //_spi->write(0xFE);
AjK 0:0a841b89d614 575
AjK 0:0a841b89d614 576 // write the data
AjK 0:0a841b89d614 577 for(int i=0; i<length; i++) {
AjK 0:0a841b89d614 578 SSP0_WRITE_BYTE(buffer[i]);
AjK 0:0a841b89d614 579 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 580 //_spi->write(buffer[i]);
AjK 0:0a841b89d614 581 }
AjK 0:0a841b89d614 582
AjK 0:0a841b89d614 583 // write the checksum
AjK 0:0a841b89d614 584 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 585 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 586 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 587 //_spi->write(0xFF);
AjK 0:0a841b89d614 588 //_spi->write(0xFF);
AjK 0:0a841b89d614 589
AjK 0:0a841b89d614 590 // check the repsonse token
AjK 0:0a841b89d614 591 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 592 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 593 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 594 if((LPC_SSP0->DR & 0x1F) != 0x05) {
AjK 0:0a841b89d614 595 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 596 return 1;
AjK 0:0a841b89d614 597 }
AjK 0:0a841b89d614 598
AjK 0:0a841b89d614 599 // wait for write to finish
AjK 0:0a841b89d614 600 SSP0_FLUSH_RX_FIFO;
AjK 0:0a841b89d614 601 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 602 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 603 while(LPC_SSP0->DR == 0) {
AjK 0:0a841b89d614 604 SSP0_WRITE_BYTE(0xFF);
AjK 0:0a841b89d614 605 while(SSP0_IS_BUSY);
AjK 0:0a841b89d614 606 }
AjK 0:0a841b89d614 607
AjK 0:0a841b89d614 608 SDCARD_CS_DEASSERT; //_cs = 1;
AjK 0:0a841b89d614 609 return 0;
AjK 0:0a841b89d614 610 }
AjK 0:0a841b89d614 611
AjK 0:0a841b89d614 612 int ext_bits(BYTE *data, int msb, int lsb) {
AjK 0:0a841b89d614 613 int bits = 0;
AjK 0:0a841b89d614 614 int size = 1 + msb - lsb;
AjK 0:0a841b89d614 615 for(int i=0; i<size; i++) {
AjK 0:0a841b89d614 616 int position = lsb + i;
AjK 0:0a841b89d614 617 int byte = 15 - (position >> 3);
AjK 0:0a841b89d614 618 int bit = position & 0x7;
AjK 0:0a841b89d614 619 int value = (data[byte] >> bit) & 1;
AjK 0:0a841b89d614 620 bits |= value << i;
AjK 0:0a841b89d614 621 }
AjK 0:0a841b89d614 622 return bits;
AjK 0:0a841b89d614 623 }
AjK 0:0a841b89d614 624
AjK 0:0a841b89d614 625 int _sd_sectors() {
AjK 0:0a841b89d614 626
AjK 0:0a841b89d614 627 // CMD9, Response R2 (R1 byte + 16-byte block read)
AjK 0:0a841b89d614 628 if(_cmd(9, 0) != 0) {
AjK 0:0a841b89d614 629 //fprintf(stderr, "Didn't get a response from the disk\n");
AjK 0:0a841b89d614 630 return 0;
AjK 0:0a841b89d614 631 }
AjK 0:0a841b89d614 632
AjK 0:0a841b89d614 633 BYTE csd[16];
AjK 0:0a841b89d614 634 if(_read(csd, 16) != 0) {
AjK 0:0a841b89d614 635 //fprintf(stderr, "Couldn't read csd response from disk\n");
AjK 0:0a841b89d614 636 return 0;
AjK 0:0a841b89d614 637 }
AjK 0:0a841b89d614 638
AjK 0:0a841b89d614 639 // csd_structure : csd[127:126]
AjK 0:0a841b89d614 640 // c_size : csd[73:62]
AjK 0:0a841b89d614 641 // c_size_mult : csd[49:47]
AjK 0:0a841b89d614 642 // read_bl_len : csd[83:80]
AjK 0:0a841b89d614 643
AjK 0:0a841b89d614 644 int csd_structure = ext_bits(csd, 127, 126);
AjK 0:0a841b89d614 645 int c_size = ext_bits(csd, 73, 62);
AjK 0:0a841b89d614 646 int c_size_mult = ext_bits(csd, 49, 47);
AjK 0:0a841b89d614 647 int read_bl_len = ext_bits(csd, 83, 80);
AjK 0:0a841b89d614 648
AjK 0:0a841b89d614 649 if(csd_structure != 0) {
AjK 0:0a841b89d614 650 //fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures");
AjK 0:0a841b89d614 651 return 0;
AjK 0:0a841b89d614 652 }
AjK 0:0a841b89d614 653
AjK 0:0a841b89d614 654 int blocks = (c_size + 1) * (1 << (c_size_mult + 2));
AjK 0:0a841b89d614 655 int block_size = 1 << read_bl_len;
AjK 0:0a841b89d614 656
AjK 0:0a841b89d614 657 if(block_size != 512) {
AjK 0:0a841b89d614 658 //fprintf(stderr, "This disk tastes funny! I only like 512 byte blocks (%d)\r\n",block_size);
AjK 0:0a841b89d614 659 return 0;
AjK 0:0a841b89d614 660 }
AjK 0:0a841b89d614 661
AjK 0:0a841b89d614 662 return blocks;
AjK 0:0a841b89d614 663 }
AjK 0:0a841b89d614 664