void File::close(void) { fat_close_file(_fd); #if SD_RAW_WRITE_SUPPORT sd_raw_sync(); #endif }
void SDCardFile::close() { if (fd != NULL) { fat_close_file(fd); sd_raw_sync(); fd = NULL; } }
void FAT::write(const char * data) { //Always write to the end of the file. fat_seek_file(_file_handle, 0, FAT_SEEK_END); fat_write_file(_file_handle, (uint8_t *)data, strlen(data)); sd_raw_sync(); }
uint8_t closeFile(struct fat_file_struct* fd){ fat_close_file(fd); if (!sd_raw_sync()){ printf_P(PSTR("failed to sync file\r\n")); return 0; } return 1; }
bool FatFsClass::createFile(const char * file_name) { struct fat_dir_entry_struct directory; if(fat_create_file(_dd, file_name, &directory)){ sd_raw_sync(); return true; } return false; }
bool FatFsClass::deleteFile(const char * file_name) { struct fat_dir_entry_struct directory; if(find_file_in_dir(file_name, &directory)){ if(fat_delete_file(_fs, &directory)){ sd_raw_sync(); return true; } } return false; }
bool SDCardEntry::createSubDirectory(const char *path, struct fat_dir_entry_struct *new_entry) { if (path[0] == '/') path++; fat_dir_struct *dd = fat_open_dir(SDCard.fs, &dir_entry); if (dd == NULL) return false; char subDir[64]; while (1) { const char *pos = strchr(path, '/'); if (pos == NULL) { m_strncpy(subDir, path, sizeof(subDir) - 1); } else { int len = pos - path; memcpy(subDir, path, len); subDir[len] = '\0'; path = pos + 1; } struct fat_dir_entry_struct new_dir_entry; int result = fat_create_dir(dd, subDir, &new_dir_entry); if (result == 0 && strcmp(subDir, new_dir_entry.long_name)) { fat_close_dir(dd); return false; } else { memcpy(new_entry, &new_dir_entry, sizeof(new_dir_entry)); fat_close_dir(dd); dd = fat_open_dir(SDCard.fs, &new_dir_entry); if (dd == NULL) { return false; } else { if (pos == NULL) { sd_raw_sync(); fat_close_dir(dd); return true; } } } } }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length) { offset_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* determine byte count to read at once */ block_offset = offset & 0x01ff; block_address = offset - block_offset; read_length = 512 - block_offset; /* read up to block border */ if(read_length > length) read_length = length; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } /* wait for data block (start byte 0xfe) */ while(sd_raw_rec_byte() != 0xfe); #if SD_RAW_SAVE_RAM /* read byte block */ uint16_t read_to = block_offset + read_length; for(uint16_t i = 0; i < 512; ++i) { uint8_t b = sd_raw_rec_byte(); if(i >= block_offset && i < read_to) *buffer++ = b; } #else /* read byte block */ uint8_t* cache = raw_block; for(uint16_t i = 0; i < 512; ++i) *cache++ = sd_raw_rec_byte(); raw_block_address = block_address; memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; #endif /* read crc16 */ sd_raw_rec_byte(); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }
int main() { /* we will just use ordinary idle mode */ set_sleep_mode(SLEEP_MODE_IDLE); /* setup uart */ uart_init(); while(1) { /* setup sd card slot */ if(!sd_raw_init()) { #if DEBUG uart_puts_p(PSTR("MMC/SD initialization failed\n")); #endif continue; } /* open first partition */ struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, #if SD_RAW_WRITE_SUPPORT sd_raw_write, sd_raw_write_interval, #else 0, 0, #endif 0 ); if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, #if SD_RAW_WRITE_SUPPORT sd_raw_write, sd_raw_write_interval, #else 0, 0, #endif -1 ); if(!partition) { #if DEBUG uart_puts_p(PSTR("opening partition failed\n")); #endif continue; } } /* open file system */ struct fat_fs_struct* fs = fat_open(partition); if(!fs) { #if DEBUG uart_puts_p(PSTR("opening filesystem failed\n")); #endif continue; } /* open root directory */ struct fat_dir_entry_struct directory; fat_get_dir_entry_of_path(fs, "/", &directory); struct fat_dir_struct* dd = fat_open_dir(fs, &directory); if(!dd) { #if DEBUG uart_puts_p(PSTR("opening root directory failed\n")); #endif continue; } /* print some card information as a boot message */ print_disk_info(fs); /* provide a simple shell */ char buffer[24]; while(1) { /* print prompt */ uart_putc('>'); uart_putc(' '); /* read command */ char* command = buffer; if(read_line(command, sizeof(buffer)) < 1) continue; /* execute command */ if(strcmp_P(command, PSTR("init")) == 0) { break; } else if(strncmp_P(command, PSTR("cd "), 3) == 0) { command += 3; if(command[0] == '\0') continue; /* change directory */ struct fat_dir_entry_struct subdir_entry; if(find_file_in_dir(fs, dd, command, &subdir_entry)) { struct fat_dir_struct* dd_new = fat_open_dir(fs, &subdir_entry); if(dd_new) { fat_close_dir(dd); dd = dd_new; continue; } } uart_puts_p(PSTR("directory not found: ")); uart_puts(command); uart_putc('\n'); } else if(strcmp_P(command, PSTR("ls")) == 0) { /* print directory listing */ struct fat_dir_entry_struct dir_entry; while(fat_read_dir(dd, &dir_entry)) { uint8_t spaces = sizeof(dir_entry.long_name) - strlen(dir_entry.long_name) + 4; uart_puts(dir_entry.long_name); uart_putc(dir_entry.attributes & FAT_ATTRIB_DIR ? '/' : ' '); while(spaces--) uart_putc(' '); uart_putdw_dec(dir_entry.file_size); uart_putc('\n'); } } else if(strncmp_P(command, PSTR("cat "), 4) == 0) { command += 4; if(command[0] == '\0') continue; /* search file in current directory and open it */ struct fat_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { uart_puts_p(PSTR("error opening ")); uart_puts(command); uart_putc('\n'); continue; } /* print file contents */ uint8_t buffer[8]; uint32_t offset = 0; while(fat_read_file(fd, buffer, sizeof(buffer)) > 0) { uart_putdw_hex(offset); uart_putc(':'); for(uint8_t i = 0; i < 8; ++i) { uart_putc(' '); uart_putc_hex(buffer[i]); } uart_putc('\n'); offset += 8; } fat_close_file(fd); } else if(strcmp_P(command, PSTR("disk")) == 0) { if(!print_disk_info(fs)) uart_puts_p(PSTR("error reading disk info\n")); } #if FAT_WRITE_SUPPORT else if(strncmp_P(command, PSTR("rm "), 3) == 0) { command += 3; if(command[0] == '\0') continue; struct fat_dir_entry_struct file_entry; if(find_file_in_dir(fs, dd, command, &file_entry)) { if(fat_delete_file(fs, &file_entry)) continue; } uart_puts_p(PSTR("error deleting file: ")); uart_puts(command); uart_putc('\n'); } else if(strncmp_P(command, PSTR("touch "), 6) == 0) { command += 6; if(command[0] == '\0') continue; struct fat_dir_entry_struct file_entry; if(!fat_create_file(dd, command, &file_entry)) { uart_puts_p(PSTR("error creating file: ")); uart_puts(command); uart_putc('\n'); } } else if(strncmp_P(command, PSTR("write "), 6) == 0) { command += 6; if(command[0] == '\0') continue; char* offset_value = command; while(*offset_value != ' ' && *offset_value != '\0') ++offset_value; if(*offset_value == ' ') *offset_value++ = '\0'; else continue; /* search file in current directory and open it */ struct fat_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { uart_puts_p(PSTR("error opening ")); uart_puts(command); uart_putc('\n'); continue; } int32_t offset = strtolong(offset_value); if(!fat_seek_file(fd, &offset, FAT_SEEK_SET)) { uart_puts_p(PSTR("error seeking on ")); uart_puts(command); uart_putc('\n'); fat_close_file(fd); continue; } /* read text from the shell and write it to the file */ uint8_t data_len; while(1) { /* give a different prompt */ uart_putc('<'); uart_putc(' '); /* read one line of text */ data_len = read_line(buffer, sizeof(buffer)); if(!data_len) break; /* write text to file */ if(fat_write_file(fd, (uint8_t*) buffer, data_len) != data_len) { uart_puts_p(PSTR("error writing to file\n")); break; } } fat_close_file(fd); } else if(strncmp_P(command, PSTR("mkdir "), 6) == 0) { command += 6; if(command[0] == '\0') continue; struct fat_dir_entry_struct dir_entry; if(!fat_create_dir(dd, command, &dir_entry)) { uart_puts_p(PSTR("error creating directory: ")); uart_puts(command); uart_putc('\n'); } } #endif #if SD_RAW_WRITE_BUFFERING else if(strcmp_P(command, PSTR("sync")) == 0) { if(!sd_raw_sync()) uart_puts_p(PSTR("error syncing disk\n")); } #endif else if(strcmp_P(command, PSTR("sync")) == 0) { // vytvor adresar mereni_teploty // nekonecna smycka - pomoci RTCka kazdou minutu odmer teplotu } else { uart_puts_p(PSTR("unknown command: ")); uart_puts(command); uart_putc('\n'); } } /* close directory */ fat_close_dir(dd); /* close file system */ fat_close(fs); /* close partition */ partition_close(partition); } return 0; }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length) { #if !SD_RAW_SAVE_RAM uint8_t attempts = 0; #endif offset_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* determine byte count to read at once */ block_offset = offset & 0x01ff; block_address = offset - block_offset; read_length = 512 - block_offset; /* read up to block border */ if(read_length > length) read_length = length; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif read_block: /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); sd_errno = SDR_ERR_BADRESPONSE; return 0; } /* wait for data block (start byte 0xfe) */ uint16_t tries = 0; while(sd_raw_rec_byte() != 0xfe) { if(tries++ >= 0x7FFF) { unselect_card(); sd_errno = SDR_ERR_COMMS; return 0; } } #if SD_RAW_SAVE_RAM /* read byte block */ uint16_t read_to = block_offset + read_length; for(uint16_t i = 0; i < 512; ++i) { uint8_t b = sd_raw_rec_byte(); if(i >= block_offset && i < read_to) *buffer++ = b; } /* ignore crc bytes */ sd_raw_rec_byte(); sd_raw_rec_byte(); #else /* read byte block */ uint8_t* cache = raw_block; for(uint16_t i = 0; i < 512; ++i) *cache++ = sd_raw_rec_byte(); raw_block_address = block_address; /* read crc16 */ if ( sd_use_crc ) { uint16_t crc = sd_raw_rec_byte() << 8; crc |= sd_raw_rec_byte(); if ( crc != sd_crc16(raw_block, (uint16_t)512) ) { unselect_card(); if ( ++attempts < 5 ) { sd_raw_rec_byte(); // pause a little goto read_block; } sd_errno = SDR_ERR_CRC; return 0; } } else { /* ignore crc bytes */ sd_raw_rec_byte(); sd_raw_rec_byte(); } memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; #endif /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }
/** * \ingroup sd_raw * Writes raw data to the card. * * \note If write buffering is enabled, you might have to * call sd_raw_sync() before disconnecting the card * to ensure all remaining data has been written. * * \param[in] offset The offset where to start writing. * \param[in] buffer The buffer containing the data to be written. * \param[in] length The number of bytes to write. * \returns 0 on failure, 1 on success. * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval */ uint8_t sd_raw_write(uint32_t offset, const uint8_t* buffer, uint16_t length) { #if SD_RAW_WRITE_SUPPORT if(get_pin_locked()) return 0; uint32_t block_address; uint16_t block_offset; uint16_t write_length; while(length > 0) { /* determine byte count to write at once */ block_address = offset & 0xfffffe00; block_offset = offset & 0x01ff; write_length = 512 - block_offset; /* write up to block border */ if(write_length > length) write_length = length; /* Merge the data to write with the content of the block. * Use the cached block if available. */ if(block_address != raw_block_address) { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif if(block_offset || write_length < 512) { if(!sd_raw_read(block_address, raw_block, sizeof(raw_block))) return 0; } raw_block_address = block_address; } if(buffer != raw_block) { memcpy(raw_block + block_offset, buffer, write_length); #if SD_RAW_WRITE_BUFFERING raw_block_written = 0; if(length == write_length) return 1; #endif } /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_WRITE_SINGLE_BLOCK, block_address)) { unselect_card(); spi_rec_byte(); return 0; } /* send start byte */ spi_send_byte(0xfe); /* write byte block */ spi_send_data(raw_block, 512); /* write dummy crc16 */ spi_send_byte(0xff); spi_send_byte(0xff); /* wait while card is busy */ /* uint16_t i; for(i = 0; i < 0x7fff; ++i) { if(spi_rec_byte() == 0xff) break; } if(i >= 0x7fff) { unselect_card(); spi_rec_byte(); return 0; } */ // obiger code reicht bei langsamen Karten nicht aus! // daher nachfolgende alte Version mit endlos Warteschleife // Wil. while(spi_rec_byte() != 0xff); spi_rec_byte(); /* deaddress card */ unselect_card(); buffer += write_length; offset += write_length; length -= write_length; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif } return 1; #else return 0; #endif }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(uint32_t offset, uint8_t* buffer, uint16_t length) { uint32_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* determine byte count to read at once */ block_address = offset & 0xfffffe00; block_offset = offset & 0x01ff; read_length = 512 - block_offset; /* read up to block border */ if(read_length > length) read_length = length; #if !SD_RAW_SAVE_RAM /* check if the requested data is cached */ if(block_address != raw_block_address) #endif { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* address card */ select_card(); /* send single block request */ if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, block_address)) { unselect_card(); spi_rec_byte(); return 0; } /* wait for data block (start byte 0xfe) */ uint16_t i; for(i = 0; i < 0x1fff; ++i) { if(spi_rec_byte() == 0xfe) break; } if(i >= 0x1fff) { unselect_card(); spi_rec_byte(); return 0; } #if SD_RAW_SAVE_RAM /* read byte block */ uint16_t read_to = block_offset + read_length; for(uint16_t i = 0; i < 512; ++i) { uint8_t b = spi_rec_byte(); if(i >= block_offset && i < read_to) *buffer++ = b; } #else /* read byte block */ spi_rec_data(raw_block, 512); raw_block_address = block_address; memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; #endif /* read crc16 */ spi_rec_byte(); spi_rec_byte(); /* deaddress card */ unselect_card(); spi_rec_byte(); } #if !SD_RAW_SAVE_RAM else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } #endif length -= read_length; offset += read_length; } return 1; }
//0 for success, negative for failure int readLogCon(void) { char keyword[64]; char value[64]; char stringBuf[512]; struct fat16_file_struct fd; int len; int s=0; int t=0; keyword[0]=0; value[0]=0; int result; if(root_file_exists(LOGCON_NAME)) { //There already is a logcon file, open it and suck int in result = root_open(&fd,LOGCON_NAME); if(result<0) return result; len = fat16_read_file(&fd, (unsigned char *)stringBuf, 512); if(len<0) return -1; fat16_close_file(&fd); } else { //No existing logcon file, write a fresh one result=root_open_new(&fd,LOGCON_NAME); if(result<0) return result; stringBuf[0]=0; //Write out each default line for(int i=0;strlen(fTable[i].tag)>0;i++) { strcat(stringBuf,fTable[i].tag); strcat(stringBuf,"="); strcat(stringBuf,fTable[i].def); strcat(stringBuf,"\r\n"); } //write it out to the file len=strlen(stringBuf); fat16_write_file(&fd, (unsigned char*)stringBuf, len); fat16_close_file(&fd); sd_raw_sync(); } //Either way, the logcon file is now in stringBuf and //its length is in len s=0; t=0; char inValue=0; for(s = 0; s < len; s++) { if(stringBuf[s] == '=') { keyword[t]=0; inValue=1; t=0; } else if(stringBuf[s]=='\n') { value[t]=0; inValue=0; t=0; result=processLine(keyword,value); if(result<0) return result; } else { if(inValue) { value[t]=stringBuf[s]; } else { keyword[t]=stringBuf[s]; } t++; } } return 0; }
int main() { /* setup uart */ uart_init(); /* setup stdio */ uart_connect_stdio(); /* setup sd card slot */ if(!sd_raw_init()) { #if DEBUG printf_P(PSTR("MMC/SD initialization failed\n")); #endif return 1; } /* open first partition */ struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, 0); if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, -1 ); if(!partition) { #if DEBUG printf_P(PSTR("opening partition failed\n")); #endif return 1; } } /* open file system */ struct fat16_fs_struct* fs = fat16_open(partition); if(!fs) { #if DEBUG printf_P(PSTR("opening filesystem failed\n")); #endif return 1; } /* open root directory */ struct fat16_dir_entry_struct directory; fat16_get_dir_entry_of_path(fs, "/", &directory); struct fat16_dir_struct* dd = fat16_open_dir(fs, &directory); if(!dd) { #if DEBUG printf_P(PSTR("opening root directory failed\n")); #endif return 1; } /* provide a simple shell */ char buffer[24]; while(1) { /* print prompt */ uart_putc('>'); uart_putc(' '); /* read command */ char* command = buffer; if(read_line(command, sizeof(buffer)) < 1) continue; /* execute command */ if(strncmp_P(command, PSTR("cd "), 3) == 0) { command += 3; if(command[0] == '\0') continue; /* change directory */ struct fat16_dir_entry_struct subdir_entry; if(find_file_in_dir(fs, dd, command, &subdir_entry)) { struct fat16_dir_struct* dd_new = fat16_open_dir(fs, &subdir_entry); if(dd_new) { fat16_close_dir(dd); dd = dd_new; continue; } } printf_P(PSTR("directory not found: %s\n"), command); } else if(strcmp_P(command, PSTR("ls")) == 0) { /* print directory listing */ struct fat16_dir_entry_struct dir_entry; while(fat16_read_dir(dd, &dir_entry)) { printf_P(PSTR("%10lu %s%c\n"), dir_entry.file_size, dir_entry.long_name, (dir_entry.attributes & FAT16_ATTRIB_DIR) ? '/' : ' ' ); } } else if(strncmp_P(command, PSTR("cat "), 4) == 0) { command += 4; if(command[0] == '\0') continue; /* search file in current directory and open it */ struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { printf_P(PSTR("error opening %s\n"), command); continue; } /* print file contents */ uint8_t buffer[8]; uint32_t offset = 0; while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0) { printf_P(PSTR("%08lx: %02x %02x %02x %02x %02x %02x %02x %02x\n"), offset, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7] ); offset += 8; } fat16_close_file(fd); } #if FAT16_WRITE_SUPPORT else if(strncmp_P(command, PSTR("rm "), 3) == 0) { command += 3; if(command[0] == '\0') continue; struct fat16_dir_entry_struct file_entry; if(find_file_in_dir(fs, dd, command, &file_entry)) { if(fat16_delete_file(fs, &file_entry)) continue; } printf_P(PSTR("error deleting file: %s\n"), command); } else if(strncmp_P(command, PSTR("touch "), 6) == 0) { command += 6; if(command[0] == '\0') continue; struct fat16_dir_entry_struct file_entry; if(!fat16_create_file(dd, command, &file_entry)) printf_P(PSTR("error creating file: %s\n"), command); } else if(strncmp_P(command, PSTR("write "), 6) == 0) { command += 6; if(command[0] == '\0') continue; char* offset_value = command; while(*offset_value != ' ' && *offset_value != '\0') ++offset_value; if(*offset_value == ' ') *offset_value++ = '\0'; else continue; /* search file in current directory and open it */ struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command); if(!fd) { printf_P(PSTR("error opening %s\n"), command); continue; } int32_t offset = strtol(offset_value, 0, 0); if(!fat16_seek_file(fd, &offset, FAT16_SEEK_SET)) { printf_P(PSTR("error seeking on %s\n"), command); fat16_close_file(fd); continue; } /* read text from the shell and write it to the file */ uint8_t data_len; while(1) { /* give a different prompt */ uart_putc('<'); uart_putc(' '); /* read one line of text */ data_len = read_line(buffer, sizeof(buffer)); if(!data_len) break; /* write text to file */ if(fat16_write_file(fd, (uint8_t*) buffer, data_len) != data_len) { printf_P(PSTR("error writing to file\n")); break; } } fat16_close_file(fd); } #endif #if SD_RAW_WRITE_BUFFERING else if(strcmp_P(command, PSTR("sync")) == 0) { if(!sd_raw_sync()) printf_P(PSTR("error syncing disk\n")); } #endif else { printf_P(PSTR("unknown command: %s\n"), command); } } /* close file system */ fat16_close(fs); /* close partition */ partition_close(partition); return 0; }
/** * \ingroup sd_raw * Writes raw data to the card. * * \note If write buffering is enabled, you might have to * call sd_raw_sync() before disconnecting the card * to ensure all remaining data has been written. * * \param[in] offset The offset where to start writing. * \param[in] buffer The buffer containing the data to be written. * \param[in] length The number of bytes to write. * \returns 0 on failure, 1 on success. * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval */ uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length) { if(sd_raw_locked()) return 0; offset_t block_address; uint16_t block_offset; uint16_t write_length; while(length > 0) { /* determine byte count to write at once */ block_offset = offset & 0x01ff; block_address = offset - block_offset; write_length = 512 - block_offset; /* write up to block border */ if(write_length > length) write_length = length; /* Merge the data to write with the content of the block. * Use the cached block if available. */ if(block_address != raw_block_address) { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif if(block_offset || write_length < 512) { if(!sd_raw_read(block_address, raw_block, sizeof(raw_block))) return 0; } raw_block_address = block_address; } if(buffer != raw_block) { memcpy(raw_block + block_offset, buffer, write_length); #if SD_RAW_WRITE_BUFFERING raw_block_written = 0; if(length == write_length) return 1; #endif } /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } /* send start byte */ sd_raw_send_byte(0xfe); /* write byte block */ uint8_t* cache = raw_block; for(uint16_t i = 0; i < 512; ++i) sd_raw_send_byte(*cache++); /* write dummy crc16 */ sd_raw_send_byte(0xff); sd_raw_send_byte(0xff); /* wait while card is busy */ while(sd_raw_rec_byte() != 0xff); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); buffer += write_length; offset += write_length; length -= write_length; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif } return 1; }
/** * \ingroup sd_raw * Reads raw data from the card. * * \param[in] offset The offset from which to read. * \param[out] buffer The buffer into which to write the data. * \param[in] length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length) { offset_t block_address; uint16_t block_offset; uint16_t read_length; while(length > 0) { /* determine byte count to read at once */ block_offset = offset & 0x01ff; block_address = offset - block_offset; read_length = 512 - block_offset; /* read up to block border */ if(read_length > length) read_length = length; /* check if the requested data is cached */ if(block_address != raw_block_address) { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { return 0; } /* wait for data block (start byte 0xfe) */ //while(sd_raw_rec_byte() != 0xfe); sd_raw_send_byte(0xef); /* read byte block */ uint8_t* cache = raw_block; for(uint16_t i = 0; i < 512; ++i) { while(!(SPSR & (1<<SPIF))); *cache++ = SPDR; } raw_block_address = block_address; /* read crc16 */ sd_raw_send_byte(0xab); sd_raw_send_byte(0xcd); memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } else { /* use cached data */ memcpy(buffer, raw_block + block_offset, read_length); buffer += read_length; } length -= read_length; offset += read_length; } return 1; }
/** * \ingroup sd_raw_read_block * Reads block of raw data from the card. * * \param[in] block_address the address of the block to read * \param[in] block_offset The offset from which to read. * \param[out] raw_buffer The buffer into which to write the data. * \param[in] read_length The number of bytes to read. * \returns 0 on failure, 1 on success. * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval */ uint8_t sd_raw_read_block(offset_t block_address, offset_t block_offset, uint8_t* raw_buffer, uintptr_t read_length) { #if SD_RAW_WRITE_BUFFERING if(!sd_raw_sync()) return 0; #endif /* address card */ select_card(); /* send single block request */ #if SD_RAW_SDHC if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) #else if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) #endif { unselect_card(); return 0; } uint16_t tries = 0; /* wait for data block (start byte 0xfe) */ while((sd_raw_rec_byte() != 0xfe)){ if(tries >= 0x7FFF){ unselect_card(); return 0; } tries++; } #if SD_RAW_SAVE_RAM /* read byte block */ uint16_t read_to = block_offset + read_length; for(uint16_t i = 0; i < 512; ++i) { uint8_t b = sd_raw_rec_byte(); if(i >= block_offset && i < read_to) *buffer++ = b; } #else /* read byte block */ // uint8_t* cache = raw_block; uint8_t* cache = raw_buffer; for(uint16_t i = 0; i < 512; ++i) *cache++ = sd_raw_rec_byte(); #endif /* read crc16 */ sd_raw_rec_byte(); sd_raw_rec_byte(); /* deaddress card */ unselect_card(); /* let card some time to finish */ sd_raw_rec_byte(); return 1; }
int load_fw(char* filename) { struct fat16_file_struct * fd; int read; int i; char* addy; addy = (char*)STARTADDR; /* Erase all sectors we could use */ prep_command[1]=ERASE_SECT_START; prep_command[2]=ERASE_SECT_STOP; iap_fn(prep_command,result); iap_fn(erase_command,result); /* Open the file */ fd = root_open(filename); /* Clear the buffer */ for(i=0;i<READBUFSIZE;i++) { readbuf[i]=0; } /* Read the file contents, and print them out */ while( (read=fat16_read_file(fd,(unsigned char*)readbuf,READBUFSIZE)) > 0 ) { // Print Data to UART (DEBUG) /*for(i=0; i<read; i++) { rprintf("%c",readbuf[i]); }*/ /* Write Data to Flash */ /* Prepare Current Sector */ /* This assumes that we are always only writing to one sector! * This is only true if our write size necessarily aligns * on proper boundaries. Be careful */ prep_command[1] = SECTOR_NUMBER(((int)addy)); prep_command[2] = prep_command[1]; iap_fn(prep_command,result); /* *** Should check result here... but I'm not */ /* If all went according to plan, the sector is primed for write * (or erase) */ /* Now write data */ write_command[1]=(unsigned int)addy; write_command[2]=(unsigned int)readbuf; write_command[3]=READBUFSIZE; iap_fn(write_command,result); /* *** Should check result here... but I'm not */ /* If all went according to plan, data is in flash, * and the sector is locked again */ /* Done with current data, so clear buffer * this is because we ALWAYS write out the * entire buffer, and we don't want to write * garbage data on reads smaller than READBUFSIZE */ for(i=0;i<READBUFSIZE;i++) { readbuf[i]=0; } /* Now update the address-- */ addy = addy + READBUFSIZE; /* And we should probably bounds-check... *SIGH*/ if((unsigned int)addy > (unsigned int) 0x0007CFFF) { break; } } /* All data copied to FLASH */ /* Debug: Report the flash contents */ /* addy = (char*)STARTADDR;*/ /* PRINTF0("Dirty Screech\n\r");*/ /* delay_ms(10000);*/ /* while(addy<(char*)0x00050000)*/ /* {*/ /* __putchar(*addy++);*/ /* }*/ /* PRINTF0("Dirty Screech completed\n\r");*/ /* Close the file! */ sd_raw_sync(); fat16_close_file(fd); root_delete(filename); return 0; }
void RepRapSDCard::close_file(File f) { //fat_resize_file(f,f->pos); fat_close_file(f); sd_raw_sync(); }