/* * This function synchronously waits any pending block transfers * are finished. If your program needs to ensure a block has finished * transferring, call this function. * * Note that sd_read_block() and sd_write_block() already call this * function internally before attempting a new transfer, so there are * only two times when a user would need to use this function. * * 1) When the processor will be shutting down. All pending * writes should be finished first. * 2) When the user needs the result of an sd_read_block() call * right away. */ void sd_wait_notbusy(sd_context_t *sdc) { /* Just twiddle our thumbs until the transfer's done */ while ((DMA0CTL & DMAEN) != 0); /* Reset the DMA controller */ DMACTL0 = 0; /* Ignore the checksum */ sd_delay(4); /* Check for the busy flag (set on write block) */ if (sdc->busyflag == 1) { while (spi_recv_byte() != 0xFF); sdc->busyflag = 0; } /* Deassert CS */ spi_cs_deassert(); /* * Send some extra clocks so the card can resynchronize * on next transfer */ sd_delay(2); }
u8 sd_open( void ) { u8 i; u8 resp[ R1 + 16 + 2 ]; u24 deleteme; // Check for card if( !sd_card_present() ) return( SD_ERR_NOCARD ); // SPI to 400kHz SPI_BRG_H = 0x00; SPI_BRG_L = 0x7D; // Required delays before initialization sd_assert(); sd_delay( 100 ); sd_deassert(); sd_delay( 2 ); // Enter idle state if( sd_send_command( CMD0_GO_IDLE_STATE, NULL, NULL ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); // Read OCR (for operating conditions) and verify 3.3V capability if( sd_send_command( CMD58_READ_OCR, NULL, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); if( !( resp[ 2 ] & MSK_OCR_33 ) ) return( SD_ERR_OCR ); // Initialize card i = 0; do { if( sd_send_command( ACMD41_APP_SEND_OP_COND, NULL, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); } while( ( resp[ 0 ] & SD_ERR_R1_IDLE ) && ++i != SD_IDLE_TIMEOUT ); // Set block length to 512 (compatible with SDHC) if( sd_set_blocklen( 512 ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); // Read CSD //if( sd_send_command( CMD9_SEND_CSD, NULL, resp ) != SD_ERR_OK ) return( SD_ERR_GENERIC ); /* for( i = 0; i < 255; i++ ) { sd_readblock( i, block ); for( deleteme = 0; deleteme < 512; deleteme++ ) { if( block[ deleteme ] != 0 ) { asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); asm( "NOP" ); break; } } } */ // All hail the initialized SD card! return( SD_ERR_OK ); }
void sd_wait_notbusy (sd_context_t *sdc){ while ((DMA0CTL & DMAEN) != 0){;} //Just twiddle our thumbs until the transfer’s done. DMACTL0 = 0; //Reset the DMA controller. sd_delay(4); // Ignore the checksum. if (sdc->busyflag == 1){ //Check for the busy flag (set on a write block). while (spi_rcv_byte() != 0xFF); sdc->busyflag = 0; } spi_cs_deassert(); //Deassert CS. //-------------------------Send some extra clocks so the card can resynchronize on the next transfer------------------------- sd_delay(2); }
int sd_initialize() { char i, j; sdc->busyflag = 0; for (i=0; i<4; i++) argument[i] = 0; /* Delay for at least 74 clock cycles. This means to actually * *clock* out at least 74 clock cycles with no data present on * the clock. In SPI mode, send at least 10 idle bytes (0xFF). */ spi_cs_assert(); sd_delay(100); spi_cs_deassert(); sd_delay(2); /* Put the card in the idle state */ if (sd_send_command(sdc, CMD0, CMD0_R, response, argument) == 0) return 0; /* Now wait until the card goes idle. Retry at most SD_IDLE_WAIT_MAX times */ j = 0; do { j++; /* Flag the next command as an application-specific command */ if (sd_send_command(sdc, CMD55, CMD55_R, response, argument) == 1) { /* Tell the card to send its OCR */ sd_send_command(sdc, ACMD41, ACMD41_R, response, argument); } else { /* No response, bail early */ j = SD_IDLE_WAIT_MAX; } } while ((response[0] & MSK_IDLE) == MSK_IDLE && j < SD_IDLE_WAIT_MAX); /* As long as we didn't hit the timeout, assume we're OK. */ if (j >= SD_IDLE_WAIT_MAX) return 0; if (sd_send_command(sdc, CMD58, CMD58_R, response, argument) == 0) return 0; /* At a very minimum, we must allow 3.3V. */ if ((response[2] & MSK_OCR_33) != MSK_OCR_33) return 0; /* Set the block length */ if (sd_set_blocklen (sdc, SD_BLOCKSIZE) != 1) return 0; /* If we got this far, initialization was OK. */ return 1; }
int sd_ocr(void) { int i; /* Negotiate operating condition for SD, it makes card ready state */ for(i=0;i<50;i++) { sd_cmd55(); SDICARG=0xff8000; SDICCON=(0x1<<9)|(0x1<<8)|0x69; /* if using real board, should replace code here. need to modify qemu in near future*/ /* Check end of ACMD41 */ if( (sd_cmd_end(41, 1)==RT_EOK) & SDIRSP0==0x80ff8000 ) { SDICSTA=0xa00; return RT_EOK; } sd_delay(200); } SDICSTA=0xa00; return RT_ERROR; }
uint8_t write_file(uint32_t file_number,file *f)// writes the whole file { file temp; message data,*d; uint8_t i; if(CHECK_FILE_FLAG(file_number)) // check file delete flag was der before { i=0; while(i < messages_per_file) { temp=*f; data=temp.sms[i]; d=&data; if (!write_message(file_number,d,i)) break; sd_delay(15); } if(i==messages_per_file) return 0x00;//write ok; else return 0x11; //partial write } else { return 0x01;//file write problem } }
uint8_t read_file(uint32_t file_number) //read the file and returns the pointer to file { message m; uint8_t i; if(CHECK_FILE_FLAG(file_number)) // { for(i=0;i<messages_per_file;i++) { if(read_message(file_number,i)); { m=*ptr; tempf.sms[i]=m; //storing the message } sd_delay(15); } tempf.flag=0x11; //file exists ptrf=&tempf; return 0x00; // read file correctly } else { return 0x11;// file doesnot exists } }
rt_uint8_t sd_init(void) { //-- SD controller & card initialize int i; /* Important notice for MMC test condition */ /* Cmd & Data lines must be enabled by pull up resister */ SDIPRE = PCLK/(INICLK)-1; SDICON = (0<<4) | 1; // Type A, clk enable SDIFSTA = SDIFSTA | (1<<16); SDIBSIZE = 0x200; /* 512byte per one block */ SDIDTIMER=0x7fffff; /* timeout count */ /* Wait 74SDCLK for MMC card */ for(i=0; i<0x1000; i++); sd_cmd0(); /* Check SD card OCR */ if(sd_ocr() == RT_EOK) { rt_kprintf("In SD ready\n"); } else { rt_kprintf("Initialize fail\nNo Card assertion\n"); return RT_ERROR; } RECMD2: SDICARG = 0x0; SDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x42; /* lng_resp, wait_resp, start, CMD2 */ if(sd_cmd_end(2, 1) == RT_ERROR) goto RECMD2; SDICSTA = 0xa00; /* Clear cmd_end(with rsp) */ RECMD3: SDICARG = 0<<16; /* CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ) */ SDICCON = (0x1<<9)|(0x1<<8)|0x43; /* sht_resp, wait_resp, start, CMD3 */ if(sd_cmd_end(3, 1) == RT_ERROR) goto RECMD3; SDICSTA=0xa00; /* Clear cmd_end(with rsp) */ RCA = (SDIRSP0 & 0xffff0000 )>>16; SDIPRE=PCLK/(SDCLK)-1; /* Normal clock=25MHz */ if( SDIRSP0 & 0x1e00 != 0x600 ) goto RECMD3; sd_sel_desel(1); sd_delay(200); sd_setbus(); return RT_EOK; }
//initialization was successful, 0 otherwise. //sd_context_t *sdc -- pointer to a data structure containing //information about the card. For now, the //timeouts MUST be specified in advance. This //function does not yet calculate them from the //card data. int sd_initialize(sd_context_t *sdc){ char i, j; //SPI SD initialization sequence: CMD0->CMD55->ACMD41->CMD58. j = 0; //Note there is no CMD2 or CMD3 in SPI mode. These instructions are devoted to addressing on the SD bus. sdc->busyflag = 0; //SD memory card SD initialization sequence: CMD0->CMD55->ACMD41->CMD2->CMD3. for (i=0; i<4; i++){ argument[i] = 0; } //Delay for at least 74 clock cycles. This means to actually spi_cs_assert(); //*clock* out at least 74 clock cycles with no data present on sd_delay(100); //the clock. In SPI mode, send at least 10 idle bytes (0xFF). spi_cs_deassert(); sd_delay(2); if (sd_send_command(sdc, CMD0, CMD0_R, response, argument) == 0){ //Put the card in the idle state return 0; } //-------------------------------------Now wait until the card goes idle. Retry at most SD_IDLE_WAIT_MAX times.-------------------------------------- do{ j++; //Flag the next command as an application-specific command. if (sd_send_command(sdc, CMD55, CMD55_R, response, argument) == 1){ sd_send_command(sdc, ACMD41, ACMD41_R, response, argument); //Tell the card to send its OCR } else{ // No response, bail early. j = SD_IDLE_WAIT_MAX; } } while ((response[0] & MSK_IDLE) == MSK_IDLE && j < SD_IDLE_WAIT_MAX); //As long as we didn’t hit the timeout, assume we’re OK. if (j >= SD_IDLE_WAIT_MAX){ return 0; } if (sd_send_command(sdc, CMD58, CMD58_R, response, argument) == 0){ return 0; } if ((response[2] & MSK_OCR_33) != MSK_OCR_33){ //At a very minimum, we must allow 3.3V. return 0; } if (sd_set_blocklen (sdc, SD_BLOCKSIZE) != 1){ //Set the block length return 0; } return 1; //If we got this far, initialization was OK. }
/* * This function initializes the SD card. It returns 1 if * initialization was successful, 0 otherwise. * * sd_context_t *sdc -- Pointer to a data structure containing * information about the card. For now, the * timeouts must be specified in advance. It * is not yet calculated from the card data. */ int sd_initialize(sd_context_t *sdc) { u16 i; /* * SPI SDv2 initialization sequence: * CMD0 * CMD8 * CMD55+ACMD41 * CMD58 * (There is no CMD2 or CMD3 in SPI mode. These * instructions are devoted to addressing on the SD bus) */ sdc->busyflag = 0; /* * Delay for at least 74 clock cycles. This means to actually * *clock* out at least 74 clock cycles with no data present on * the clock. In SPI mode, send at least 10 idle bytes (0xFF) */ spi_cs_deassert(); sd_delay(100); spi_cs_assert(); sd_delay(2); /* Put the card in thee idle state */ if (sd_send_command(sdc, CMD0, CMD0_R, response, NULL) == 0) return 0; sd_packarg(argument, 0x000001AA); if (sd_send_command(sdc, CMD8, CMD8_R, response, argument) == 0) { return 0; } if (response[0] & MSK_ILL_CMD) { /* Illegal command, try SDv1 init */ sd_packarg(argument, 0x00000000); } else { /* Check if the voltage range is appropiate */ if (response[3] == 0x01 && response[4] == 0xAA) { sd_packarg(argument, 0x40000000); } else { return 0; } } /* Now wait until the card goes idle. Retry at most SD_IDLE_WAIT_MAX */ i = 0; do { i++; /* Flag the next command as an application-specific command */ if (sd_send_command(sdc, CMD55, CMD55_R, response, NULL) == 1) { /* Tell the card to send its OCR */ sd_send_command(sdc, ACMD41, ACMD41_R, response, argument); } else { /* No response, bail early */ i = SD_IDLE_WAIT_MAX; } } while ((response[0] & MSK_IDLE) == MSK_IDLE && i < SD_IDLE_WAIT_MAX); /* As long as we didn't hit the timeout, assume we're OK */ if (i >= SD_IDLE_WAIT_MAX) return 0; if (sd_send_command(sdc, CMD58, CMD58_R, response, NULL) == 0) return 0; /* At the very minimum, we must allow 3.3V */ if ((response[2] & MSK_OCR_33) != MSK_OCR_33) return 0; /* Set the block length */ if (sd_set_blocklen(sdc, SD_BLOCKSIZE) != 1) return 0; /* If we got this far, initialization was OK */ return 1; }
uint8_t load_fat_mat_from_SD()// Loads the Fat and mat from SD in case of reset { uint32_t address,temp; uint8_t data[message_size]; uint16_t i,j,shift=0,x; uint16_t next=0; uint32_t MAT_START=SP_ADD_MAT_START; /* Read FAT From any special address */ address=(SP_ADD_FAT1 << 9); sd_read_block(&sd,address,data); // read FAT from SD sd_delay(15); // needs to be withdrawn /* Take FAT into <main> memory */ address=0; for(i=0;i<files;i++) /* loads Addresses of file into FAT */ { for(j=0;j<4;j++) { temp= data[next++] << shift; address= address | temp; shift += 8; } root->address[i]= address; shift= 0; } address=0; shift=0; for(i=0;i<files;i++) /* loads no of files into FAT */ { for(j=0;j<4;j++) { temp= data[next++] << shift; address= address | temp; shift += 8; } root->file_number[i]= address; shift= 0; } address=0; shift=0; for(i=0;i<4;i++) /* loads flag_tables of file into FAT */ { for(j=0;j<4;j++) { temp= data[next++] << shift; address= address | temp; shift += 8; } root->flag_table[i]= address; shift= 0; } /* Fat is loaded into memory but not MAT let us do it */ shift=next=0; // (optimized); for(x=0;x<files;x++) { address=MAT_START << 9; sd_read_block(&sd,address,data); // For each file read mat address=0; shift=0; for(i=0;i<4;i++) // loads file number { temp= data[next++] << shift; address= address | temp; shift += 8; } mat[x]->file_number=address; // loads file number mat[x]->next= data[next++]; // loads next ptr; for(i=0;i<messages_per_file;i++) // loads message number mat[x]->message_number[i]= data[next++]; shift=0; address=0; for(i=0;i<8;i++) /* loads exists flag */ { for(j=0;j<4;j++) { temp= data[next++] << shift; address= address | temp; shift += 8; } mat[x]->exists_flag_table[i]= address; shift= 0; } shift=0; address=0; for(i=0;i<8;i++) /* loads delete flag */ { for(j=0;j<4;j++) { temp= data[next++] << shift; address= address | temp; shift += 8; } mat[x]->delete_flag_table[i]= address; shift= 0; } shift=0; address=0; for(i=0;i<messages_per_file;i++) /* loads Addresses messages*/ { for(j=0;j<4;j++) { temp= data[next++] << shift; address= address | temp; shift += 8; } mat[x]->address[i]= address; shift= 0; } next=0; } return 0; }
uint8_t store_fat_mat_to_SD()// stores the Fat and mat in SD at higher address. Need to be called from idle task. { /* Size of FAT to be written into SD sector is 40 bytes only.*/ uint32_t address,temp; uint8_t data[message_size]; uint16_t i,j,shift=0,x; uint16_t next=0; uint32_t MAT_START; MAT_START=SP_ADD_MAT_START; //Starting address sector where mats will be stored contigiously /* Following 3 loops stores the FAT into array */ for(i=0;i<files;i++) // Stores the address of the files of FAT in array to be written { for(j=0;j<4;j++) { address=(root->address[i]) >> shift; temp=address & 0xff; data[next++]=(uint8_t)temp; shift +=8; } shift=0; } shift=0; for(i=0;i<files;i++) // Stores the numbers of the files of FAT in array to be written { for(j=0;j<4;j++) { address=(root->file_number[i]) >> shift; temp=address & 0xff; data[next++]=(uint8_t)temp; shift +=8; } shift=0; } shift=0; for(i=0;i<4;i++) // Stores the flag_table of the files of FAT in array to be written { for(j=0;j<4;j++) { address=(root->flag_table[i]) >> shift; temp=address & 0xff; data[next++]=(uint8_t)temp; shift +=8; } shift=0; } for(i=next;i<message_size;i++) // zero paddding data[i]=0; /* Sector is ready to be written into SD Card At Special address*/ address = (SP_ADD_FAT1 << 9 ); sd_write_block(&sd,address,data); // FAT1 is written sd_delay(15); // SD card is taking rest wait address = (SP_ADD_FAT2 << 9 ); sd_write_block(&sd,address,data); // FAT2 is written sd_delay(15); // SD card is taking rest wait address = (SP_ADD_FAT3 << 9 ); sd_write_block(&sd,address,data); // FAT3 is written sd_delay(15); // SD card is taking rest wait /* Its time to write MATS into SD Card */ shift=0; next=0; for(x=0;x<files;x++) { for(i=0;i<4;i++) { address= (mat[x]->file_number) >> shift; temp= address & 0xff; data[next++]= (uint8_t)temp; shift += 8; } // File Number is written shift=0; data[next++]=(mat[x]->next); // next ptr is done for(i=0;i<messages_per_file;i++) // message number is written { data[next++]= mat[x]->message_number[i]; } for(i=0;i<8;i++) // Stores exists flad table { for(j=0;j<4;j++) { address=(mat[x]->exists_flag_table[i]) >> shift; temp=address & 0xff; data[next++]=(uint8_t)temp; shift +=8; } shift=0; } shift=0; for(i=0;i<8;i++) // Stores delete flag table { for(j=0;j<4;j++) { address=(mat[x]->delete_flag_table[i]) >> shift; temp=address & 0xff; data[next++]=(uint8_t)temp; shift +=8; } shift=0; } shift=0; for(i=0;i<messages_per_file;i++) // Stores address of messages { for(j=0;j<4;j++) { address=(mat[x]->address[i]) >> shift; temp=address & 0xff; data[next++]=(uint8_t)temp; shift +=8; } shift=0; } for(i=next;i<message_size;i++) data[i]=0x0; /* MAT for this itration's file is ready to written into SD */ address= MAT_START << 9; sd_write_block(&sd,address,data); sd_delay(15);// Sd is taking rest MAT_START++; shift=0; next=0; } return 0; }