CCS FAT Driver Bugfix!

54
 FAQ Forum Help Official CCS Support  Search Register Profile  Log in to check your private messages  Log in CCS doe s not mo nitor thi s forum o n a regul ar basis. Please do not post bug Reports on this forum. Send them to [email protected] CCS FAT driver bugfix!  CCS Forum Index -> Code Library View previous topic :: View next topic Author Message andrewg Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia  CCS FAT driver bugfix! Posted: Sun Aug 29, 2010 10:46 am (See also CCS SD/MMC driver MBR support) The CCS "fat.c" functions "get_next_addr" and "get_prev_addr" do not correctly handle cluster transitions. The following  are corrected functions: Code: si gne d i nt8 ge t _ne xt_ ad dr( i nt32* m y_ad dr) {  i nt 32 t em p; # i f de f FA T32  i nt32 c; # el se  i nt16 c; # end i f  // check to m ak e sur e t hat t he nex t i t erati on w i l l gi ve us a cont i guous ad dr ess  temp = * m y_add r + 1;  if(( tem p > Data_Start ) && ((temp - Data_Start) %Bytes_Per_Cluster == 0))  {  // conve rt the curr ent addr ess  i nto the address of where i nf ormati on about  // the addr ess i s st ored i n the FA T, a nd put this va lue int o t he curr en t addr ess  c = ad dr_ to_cluster(temp - 1);  if ( get_next_cl uster(&c) == EO F)  r et urn EOF;  if (c >= #i fdef FA T32  0x0FFFFFF8 #el se  0xFFF8 #endi f  )  r et urn EO F;  t em p = cl ust er_t o_addr ( c) ;  }  *m y_addr = t em p;  r et ur n G O O D EC; } and Code: si gne d i nt8 get _prev_add r ( i nt32* m y_ad dr) {  i nt 32 t em p; #i fdef FA T32  i nt 32 c; CCS :: V iew topic - CCS F A T driver bug fix! ht tp://www.ccsinf o.com/f orum /viewtopic.php?t=43417 1 of 54 3/17/2015 3:49 PM

description

CCS FAT Driver Bugfix!

Transcript of CCS FAT Driver Bugfix!

  • FAQ Forum Help Official CCS Support Search Register

    Profile Log in to check your private messages Login

    CCS does not monitor this forum on a regular basis.

    Please do not post bug Reports on this forum. Send them [email protected]

    CCS FAT driver bugfix!

    CCS Forum Index -> Code Library

    View previous topic :: View next topic

    Author Message

    andrewg

    Joined: 17 Aug 2005Posts: 316Location: Perth, WesternAustralia

    CCS FAT driver bugfix!Posted: Sun Aug 29, 2010 10:46 am

    (See also CCS SD/MMC driver MBR support)

    The CCS "fat.c" functions "get_next_addr" and "get_prev_addr" do not correctly handle clustertransitions. The following are corrected functions:

    Code:signed int8 get_next_addr(int32* my_addr){ int32 temp;#ifdef FAT32 int32 c;#else int16 c;#endif

    // check to make sure that the next iteration will give us a contiguous address temp = *my_addr + 1; if((temp > Data_Start ) && ((temp - Data_Start) % Bytes_Per_Cluster == 0)) { // convert the current address into the address of where information about // the address is stored in the FAT, and put this value into the currentaddress c = addr_to_cluster(temp - 1); if(get_next_cluster(&c) == EOF) return EOF; if (c >=#ifdef FAT32 0x0FFFFFF8#else 0xFFF8#endif ) return EOF; temp = cluster_to_addr(c); } *my_addr = temp; return GOODEC;}

    andCode:

    signed int8 get_prev_addr(int32* my_addr){ int32 temp;#ifdef FAT32 int32 c;

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    1 of 54 3/17/2015 3:49 PM

  • #else int16 c;#endif

    temp = *my_addr; // if we're trying to go backwards one entry from the beginning of the root, // we won't be able to... if(temp = Data_Start ) && ((temp - Data_Start) % Bytes_Per_Cluster == 0)) { c = addr_to_cluster(temp); if(get_prev_cluster(&c) == EOF) return EOF; temp = cluster_to_addr(c) + Bytes_Per_Cluster; } *my_addr = temp - 1; return GOODEC;}

    Edit, I've realized the above works because I've slightly altered the "fat_init" function too. Thefollowing in "fat_init":

    Code:#ifdef FAT32 Data_Start = Bytes_Per_Cluster + Root_Dir;#else // FAT16

    needs to have "Bytes_Per_Cluster +" deleted._________________Andrew

    Last edited by andrewg on Fri Nov 12, 2010 8:47 pm; edited 2 times in total

    andrewg

    Joined: 17 Aug 2005Posts: 316Location: Perth, WesternAustralia

    Posted: Sun Aug 29, 2010 10:54 am

    Another one, "get_short_file_name" is also buggy. Fix:Code:signed int8 get_short_file_name(int32 file_entry_addr, char sname[], int8 type){ int8 buf, i, j = 0;

    // one short file name has, at the most, 11 characters for(i = 0; i < 11; ++i) { // read in a character if(mmcsd_read_data(i + file_entry_addr, 1, &buf) != GOODEC) return EOF; // convert the character if(buf != ' ') { if (i == 8 && type != 0x10) sname[j++] = '.'; sname[j++] = tolower(buf); } } if (sname[j - 1] == '.') --j; sname[j] = '\0'; return GOODEC;}

    _________________Andrew

    BugVito

    Joined: 12 Nov 2010Posts: 3

    MMCSD FAT: Still hanging despite the few changesPosted: Fri Nov 12, 2010 6:55 pm

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    2 of 54 3/17/2015 3:49 PM

  • Good stuff andrewg. This got me going until I formatted the sd card. It has seen a fair amount of trialand error and procedures before it finally worked, and this was all before applying your changes.

    Could you explain exactly what is needed for the sd card to work on both a pc and on a board using ccsmmcsd and fat drivers, or simply what format type, etc...?

    I have tried formatting as FAT32 with default settings, no luck, FAT32 with 512 size blocks, still no luck,completely wiped the card using a hex editor, then format with both options above, still no luck.

    It is unfortunate that ccs would deploy a crippled/incomplete driver without maintaining it. I've had anethernet board from ccs for a while, with close to no luck at using the sd card.

    andrewg

    Joined: 17 Aug 2005Posts: 316Location: Perth, WesternAustralia

    Posted: Fri Nov 12, 2010 9:25 pm

    I've only ever used cards formatted on my PC or in a camera. All my standard SD (not SHDC) cardswork fine. After I made my changes (cluster fix and MBR enhancement) the cards have just worked.

    I have to admit, though, that so far I've only ever had the PIC read a card (I've only used it forfirmware updating, so far). Writing is coming soon. Once I've done some writing and made sure itactually works (I don't see why it won't, since reading works fine), then I'm going to write to CCS andgive them my new code.

    When using the CCS code, make sure you've compiled it for the correct FAT16/32 variant for the cardsyou're using (probably FAT32).

    Also, so far I've implemented SD cards on pure 3.3V logic, so no 5V 3.3V level translationscomplicate things. I've also made sure I have pullup resistors on both the CS and MISO (data from cardto PIC) lines._________________Andrew

    BugVito

    Joined: 12 Nov 2010Posts: 3

    Posted: Sat Nov 13, 2010 8:21 am

    Ahh read only. This is good to know, and may be sufficient for now actually.

    My test starts by writting a file, appending text to it, and then reading from it. I'll chop those first bitsoff for now, and test a few different formats.

    Everything was working, read and write, using the ex_fat.c example and your fixed code. That isbefore formatting the card. So a fix may not be that far off.

    I seem to be using the same setup, FAT32, 3.3V, and pullup resistors.

    Thanks for the info and initiative! Most appreciated!

    KONAMI

    Joined: 29 Aug 2010Posts: 8

    FAT32Posted: Sat Dec 17, 2011 6:58 am

    Did it(CCS C FAT.C bugfix) work in FAT32 file system.

    quangtk87

    Joined: 10 Jun 2012Posts: 3

    I try this code but nothing appearPosted: Tue Jun 12, 2012 2:42 am

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    3 of 54 3/17/2015 3:49 PM

  • When I repair fat.c and mmcsd.c on ccs follow Andrewg. Every command is good, but it just working onmy Hyperterminal. Plug SD card in my PC is nothing, empty. Anybody help me! plz_________________tinhquang

    opas

    Joined: 17 Jun 2012Posts: 2

    more bug foundPosted: Thu Jun 21, 2012 10:09 pm

    I tried to use CCS lib to make a data logger. I found a lot of bugs in the lib and need much time tomodify it. At last I can make file with text in the card and can read it in Windows. Only one thing I cannot fix it : when I put data in cluster 2, Notepad show errors. If someone know the solution, please letme know

    Next is the lib code

    mmcsd.cCode:

    ///////////////////////////////////////////////////////////////////////////// MMCSD.c //////// //////// This is a low-level driver for MMC and SD cards. //////// //////// --User Functions-- //////// //////// mmcsd_init(): Initializes the media. //////// //////// mmcsd_read_byte(a, p) //////// Reads a byte from the MMC/SD card at location a, saves to //////// pointer p. Returns 0 if OK, non-zero if error. //////// //////// mmcsd_read_data(a, n, p) //////// Reads n bytes of data from the MMC/SD card starting at address //////// a, saves result to pointer p. Returns 0 if OK, non-zero if //////// error. //////// //////// mmcsd_flush_buffer() //////// The two user write functions (mmcsd_write_byte() and //////// mmcsd_write_data()) maintain a buffer to speed up the writing //////// process. Whenever a read or write is performed, the write //////// buffer is loaded with the specified page and only the //////// contents of this buffer is changed. If any future writes //////// cross a page boundary then the buffer in RAM is written //////// to the MMC/SD and then the next page is loaded into the //////// buffer. mmcsd_flush_buffer() forces the contents in RAM //////// to the MMC/SD card. Returns 0 if OK, non-zero if errror. //////// //////// mmcsd_write_byte(a, d) //////// Writes data byte d to the MMC/SD address a. Intelligently //////// manages a write buffer, therefore you may need to call //////// mmcsd_flush_buffer() to flush the buffer. //////// //////// mmcsd_write_data(a, n, p) //////// Writes n bytes of data from pointer p to the MMC/SD card //////// starting at address a. This function intelligently manages //////// a write buffer, therefore if you may need to call //////// mmcsd_flush_buffer() to flush any buffered characters. //////// returns 0 if OK, non-zero if error. //////// //////// mmcsd_read_block(a, s, p) //////// Reads an entire page from the SD/MMC. Keep in mind that the //////// start of the read has to be aligned to a block //////// (Address % 512 = 0). Therefore s must be evenly divisible by //////// 512. At the application level it is much more effecient to //////// to use mmcsd_read_data() or mmcsd_read_byte(). Returns 0 //////// if successful, non-zero if error. //////// //////// mmcsd_write_block(a, s, p): //////// Writes an entire page to the SD/MMC. This will write an //////// entire page to the SD/MMC, so the address and size must be //////// evenly divisble by 512. At the application level it is much //////// more effecient to use mmcsd_write_data() or mmcsd_write_byte().//////// Returns 0 if successful, non-zero if error. //////// ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    4 of 54 3/17/2015 3:49 PM

  • //// mmcsd_print_cid(): Displays all data in the Card Identification //////// Register. Note this only works on SD cards. //////// //////// mmcsd_print_csd(): Displays all data in the Card Specific Data //////// Register. Note this only works on SD cards. //////// //////// //////// --Non-User Functions-- //////// //////// mmcsd_go_idle_state(): Sends the GO_IDLE_STATE command to the //////// SD/MMC. //////// mmcsd_send_op_cond(): Sends the SEND_OP_COND command to the //////// SD. Note this command only works on SD. //////// mmcsd_send_if_cond(): Sends the SEND_IF_COND command to the //////// SD. Note this command only works on SD. //////// mmcsd_sd_status(): Sends the SD_STATUS command to the SD. Note //////// This command only works on SD cards. //////// mmcsd_send_status(): Sends the SEND_STATUS command to the //////// SD/MMC. //////// mmcsd_set_blocklen(): Sends the SET_BLOCKLEN command along with //////// the desired block length. //////// mmcsd_app_cmd(): Sends the APP_CMD command to the SD. This only //////// works on SD cards and is used just before any //////// SD-only command (e.g. send_op_cond()). //////// mmcsd_read_ocr(): Sends the READ_OCR command to the SD/MMC. //////// mmcsd_crc_on_off(): Sends the CRC_ON_OFF command to the SD/MMC //////// along with a bit to turn the CRC on/off. //////// mmcsd_send_cmd(): Sends a command and argument to the SD/MMC. //////// mmcsd_get_r1(): Waits for an R1 response from the SD/MMC and //////// then saves the response to a buffer. //////// mmcsd_get_r2(): Waits for an R2 response from the SD/MMC and //////// then saves the response to a buffer. //////// mmcsd_get_r3(): Waits for an R3 response from the SD/MMC and //////// then saves the response to a buffer. //////// mmcsd_get_r7(): Waits for an R7 response from the SD/MMC and //////// then saves the response to a buffer. //////// mmcsd_wait_for_token(): Waits for a specified token from the //////// SD/MMC. //////// mmcsd_crc7(): Generates a CRC7 using a pointer to some data, //////// and how many bytes long the data is. //////// mmcsd_crc16(): Generates a CRC16 using a pointer to some data, //////// and how many bytes long the data is. //////// ///////////////////////////////////////////////////////////////////////////////// (C) Copyright 2007 Custom Computer Services //////// This source code may only be used by licensed users of the CCS //////// C compiler. This source code may only be distributed to other //////// licensed users of the CCS C compiler. No other use, //////// reproduction or distribution is permitted without written //////// permission. Derivative programs created using this software //////// in object code form are not restricted in any way. /////////////////////////////////////////////////////////////////////////////

    #ifndef MMCSD_C#define MMCSD_C

    ///////////////////////// //////// User Config //////// /////////////////////////

    #include "stdint.h"

    #ifndef MMCSD_PIN_SCL #define MMCSD_PIN_SCL PIN_C3 //o #define MMCSD_PIN_SDI PIN_C4 //i #define MMCSD_PIN_SDO PIN_C5 //o #define MMCSD_PIN_SELECT PIN_B4 //o#endif

    #use spi(MASTER, DI=MMCSD_PIN_SDI, DO=MMCSD_PIN_SDO, CLK=MMCSD_PIN_SCL, BITS=8,MSB_FIRST, MODE=3, stream=mmcsd_spi,BAUD=4800)

    //////////////////////////// //////// Useful Defines //////// ////////////////////////////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    5 of 54 3/17/2015 3:49 PM

  • enum MMCSD_err {MMCSD_GOODEC = 0, MMCSD_IDLE = 0x01, MMCSD_ERASE_RESET = 0x02, MMCSD_ILLEGAL_CMD = 0x04, MMCSD_CRC_ERR = 0x08, MMCSD_ERASE_SEQ_ERR = 0x10, MMCSD_ADDR_ERR = 0x20, MMCSD_PARAM_ERR = 0x40, RESP_TIMEOUT = 0x80};

    #define GO_IDLE_STATE 0#define SEND_OP_COND 1#define SEND_IF_COND 8#define SEND_CSD 9#define SEND_CID 10#define SD_STATUS 13#define SEND_STATUS 13#define SET_BLOCKLEN 16#define READ_SINGLE_BLOCK 17#define WRITE_BLOCK 24#define SD_SEND_OP_COND 41#define APP_CMD 55#define READ_OCR 58#define CRC_ON_OFF 59

    #define IDLE_TOKEN 0x01#define DATA_START_TOKEN 0xFE

    #define MMCSD_MAX_BLOCK_SIZE 512

    /////////////////////////// ////// Global Variables ////// ///////////////////////////

    uint8_t g_mmcsd_buffer[MMCSD_MAX_BLOCK_SIZE];

    int1 g_CRC_enabled;int1 g_MMCSDBufferChanged;

    uint32_t g_mmcsdBufferAddress;

    enum _card_type{SD, MMC} g_card_type;uint32_t g_mmcsdPartitionOffset;///////////////////////////////// //////// Function Prototypes //////// /////////////////////////////////

    MMCSD_err mmcsd_init(int32 offset);MMCSD_err mmcsd_read_data(uint32_t address, uint16_t size, uint8_t* ptr);MMCSD_err mmcsd_read_block(uint32_t address, uint16_t size, uint8_t* ptr);MMCSD_err mmcsd_write_data(uint32_t address, uint16_t size, uint8_t* ptr);MMCSD_err mmcsd_write_block(uint32_t address, uint16_t size, uint8_t* ptr);MMCSD_err mmcsd_go_idle_state(void);MMCSD_err mmcsd_send_op_cond(void);MMCSD_err mmcsd_send_if_cond(uint8_t r7[]);MMCSD_err mmcsd_print_csd();MMCSD_err mmcsd_print_cid();MMCSD_err mmcsd_sd_status(uint8_t r2[]);MMCSD_err mmcsd_send_status(uint8_t r2[]);MMCSD_err mmcsd_set_blocklen(uint32_t blocklen);MMCSD_err mmcsd_read_single_block(uint32_t address);MMCSD_err mmcsd_write_single_block(uint32_t address);MMCSD_err mmcsd_sd_send_op_cond(void);MMCSD_err mmcsd_app_cmd(void);MMCSD_err mmcsd_read_ocr(uint8_t* r1);MMCSD_err mmcsd_crc_on_off(int1 crc_enabled);MMCSD_err mmcsd_send_cmd(uint8_t cmd, uint32_t arg);MMCSD_err mmcsd_get_r1(void);MMCSD_err mmcsd_get_r2(uint8_t r2[]);MMCSD_err mmcsd_get_r3(uint8_t r3[]);MMCSD_err mmcsd_get_r7(uint8_t r7[]);MMCSD_err mmcsd_wait_for_token(uint8_t token);uint8_t mmcsd_crc7(char *data, uint8_t length);

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    6 of 54 3/17/2015 3:49 PM

  • uint16_t mmcsd_crc16(char *data, uint8_t length);void mmcsd_select();void mmcsd_deselect();

    /// Fast Functions ! ///

    MMCSD_err mmcsd_load_buffer(void);MMCSD_err mmcsd_flush_buffer(void);MMCSD_err mmcsd_move_buffer(uint32_t new_addr);MMCSD_err mmcsd_read_byte(uint32_t addr, char* data);MMCSD_err mmcsd_write_byte(uint32_t addr, char data);

    void mmcsd_check_part(uint16_t off){ printf("find offset from physical to logical %X\r\n",g_mmcsd_buffer[off] ) ;

    if (g_mmcsd_buffer[off + 1] == 0x00) { printf("check part OK \r\n"); g_mmcsdPartitionOffset = g_mmcsd_buffer[off]; // active partition /* uint8_t t; t = g_mmcsd_buffer[off + 4]; if (t == 0x04 || t == 0x06 || t == 0x0B) { // FAT16 or FAT32 partition = make32( g_mmcsd_buffer[off + 11], g_mmcsd_buffer[off + 10], g_mmcsd_buffer[off + 9], g_mmcsd_buffer[off + 8]) * MMCSD_MAX_BLOCK_SIZE; }*/ }}

    ////////////////////////////////////// //////// Function Implementations //////// //////////////////////////////////////

    MMCSD_err mmcsd_init(){ uint8_t i, r1; printf("begin initialization \r\n"); g_CRC_enabled = TRUE; g_mmcsdBufferAddress = 0;

    output_drive(MMCSD_PIN_SCL); output_drive(MMCSD_PIN_SDO); output_drive(MMCSD_PIN_SELECT); output_float(MMCSD_PIN_SDI);

    mmcsd_deselect(); delay_ms(15); /* begin initialization */ i = 0; do { delay_ms(1); mmcsd_select(); r1=mmcsd_go_idle_state(); mmcsd_deselect(); i++; if(i == 0xFF) { mmcsd_deselect(); return r1; } } while(!bit_test(r1, 0));

    i = 0; do {

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    7 of 54 3/17/2015 3:49 PM

  • delay_ms(1); mmcsd_select(); r1=mmcsd_send_op_cond(); mmcsd_deselect(); i++; if(i == 0xFF) { mmcsd_deselect(); return r1; } } while(r1 & MMCSD_IDLE);

    /* figure out if we have an SD or MMC */ mmcsd_select(); r1=mmcsd_app_cmd(); r1=mmcsd_sd_send_op_cond(); mmcsd_deselect(); printf("The card is : 0x%x\r\n",r1); /* an mmc will return an 0x04 here */ if(r1 == 0x04) { g_card_type = MMC; printf("MMC\r\n");} else { g_card_type = SD; printf("SD\r\n"); // mmcsd_print_cid(); // mmcsd_print_csd(); }delay_ms(1000); /* set block length to 512 bytes */ mmcsd_select(); r1 = mmcsd_set_blocklen(MMCSD_MAX_BLOCK_SIZE); // printf("Set block length --> %X, \n\r", r1) ;

    if(r1 != MMCSD_GOODEC) { mmcsd_deselect(); return r1; } mmcsd_deselect();

    //if (r1 == 0) printf("Set block length failed !!!!!!!\r\n");

    // turn CRCs off to speed up reading/writing mmcsd_select(); r1 = mmcsd_crc_on_off(0); if(r1 != MMCSD_GOODEC) { mmcsd_deselect(); return r1; } mmcsd_deselect();

    r1 = mmcsd_load_buffer(); g_mmcsdPartitionOffset = 0;//mmcsd_check_part(0x1EE);//mmcsd_check_part(0x1DE);//mmcsd_check_part(0x1CE);//mmcsd_check_part(0x1BE);//we need to calculate the offset adresss between phy. and logic. address from theoffset sector at the address 0x1C6

    // printf("find offset from physical to logical %X\r\n",g_mmcsd_buffer[0x1C6] ) ;//more detail at http://www.secure-digital-card-source-code-driver.com/layout-of-a-mmc-or-sd-card-with-fat/the-boot-record

    if (g_mmcsd_buffer[0x1C6] < 80 )g_mmcsdBufferAddress = g_mmcsd_buffer[0x1C6]*0x200;// for card => 1GByte need to add more offsetelseg_mmcsdBufferAddress = g_mmcsd_buffer[0x1C6]*0x200+0x10000;

    printf("offset Adr : %lX\r\n",g_mmcsdBufferAddress ) ;

    g_mmcsdPartitionOffset=g_mmcsdBufferAddress; ;

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    8 of 54 3/17/2015 3:49 PM

  • r1 = mmcsd_load_buffer();

    if (g_mmcsd_buffer[0] == 0xEB){ printf("Boot sector found " ) ;} return r1;}

    MMCSD_err mmcsd_read_data(uint32_t address, uint16_t size, uint8_t* ptr){ MMCSD_err r1; uint16_t i; // counter for loops

    for(i = 0; i < size; i++) { r1 = mmcsd_read_byte(address++, ptr++); if(r1 != MMCSD_GOODEC) return r1; } return MMCSD_GOODEC;}

    MMCSD_err mmcsd_read_block(uint32_t address, uint16_t size, uint8_t* ptr){ MMCSD_err ec; uint16_t i; // counter for loops

    // send command mmcsd_select(); ec = mmcsd_read_single_block(address); if(ec != MMCSD_GOODEC) { mmcsd_deselect(); return ec; } // wait for the data start token ec = mmcsd_wait_for_token(DATA_START_TOKEN); if(ec != MMCSD_GOODEC) { mmcsd_deselect(); return ec; } // read in the data for(i = 0; i < size; i += 1) ptr[i] = spi_xfer(mmcsd_spi, 0xFF);

    if(g_CRC_enabled) { /* check the crc */ if(make16(spi_xfer(mmcsd_spi, 0xFF), spi_xfer(mmcsd_spi, 0xFF)) !=mmcsd_crc16(g_mmcsd_buffer, MMCSD_MAX_BLOCK_SIZE)) { mmcsd_deselect(); return MMCSD_CRC_ERR; } } else { /* have the card transmit the CRC, but ignore it */ spi_xfer(mmcsd_spi, 0xFF); spi_xfer(mmcsd_spi, 0xFF); } mmcsd_deselect();//printf("print block \r\n") ;//for(i = 0; i < 32; i += 1)

    // printf("adr :%x -> %X \r\n", i, ptr[i] ) ;// printf(" %c ", ptr[i] ) ;

    return MMCSD_GOODEC;}

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    9 of 54 3/17/2015 3:49 PM

  • MMCSD_err mmcsd_write_data(uint32_t address, uint16_t size, uint8_t* ptr){ MMCSD_err ec; uint16_t i; // counter for loops for(i = 0; i < size; i++) { ec = mmcsd_write_byte(address++, *ptr++); // if (*ptr++ != 0x00) // printf(" writ data at adr : -> %lX data -> %X : i = %X, size = %X\r\n",address, ptr[i],i,size ) ; if(ec != MMCSD_GOODEC) return ec; } return MMCSD_GOODEC;}

    MMCSD_err mmcsd_write_block(uint32_t address, uint16_t size, uint8_t* ptr){ MMCSD_err ec; uint16_t i;

    // send command mmcsd_select(); ec = mmcsd_write_single_block(address); if(ec != MMCSD_GOODEC) { mmcsd_deselect(); return ec; } // send a data start token spi_xfer(mmcsd_spi, DATA_START_TOKEN); // send all the data for(i = 0; i < size; i += 1) spi_xfer(mmcsd_spi, ptr[i]);

    // if the CRC is enabled we have to calculate it, otherwise just send an 0xFFFF if(g_CRC_enabled) spi_xfer(mmcsd_spi, mmcsd_crc16(ptr, size)); else { spi_xfer(mmcsd_spi, 0xFF); spi_xfer(mmcsd_spi, 0xFF); } // get the error code back from the card; "data accepted" is 0bXXX00101 ec = mmcsd_get_r1(); if(ec & 0x0A) { mmcsd_deselect(); return ec; } // wait for the line to go back high, this indicates that the write is complete while(spi_xfer(mmcsd_spi, 0xFF) == 0); mmcsd_deselect();

    return MMCSD_GOODEC;}

    MMCSD_err mmcsd_go_idle_state(void){ mmcsd_send_cmd(GO_IDLE_STATE, 0); return mmcsd_get_r1();}

    MMCSD_err mmcsd_send_op_cond(void){ mmcsd_send_cmd(SEND_OP_COND, 0); return mmcsd_get_r1();}

    MMCSD_err mmcsd_send_if_cond(uint8_t r7[])

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    10 of 54 3/17/2015 3:49 PM

  • { mmcsd_send_cmd(SEND_IF_COND, 0x45A);

    return mmcsd_get_r7(r7);}

    MMCSD_err mmcsd_print_csd(){ uint8_t buf[16], i, r1;

    // MMCs don't support this command if(g_card_type == MMC) return MMCSD_PARAM_ERR;

    mmcsd_select(); mmcsd_send_cmd(SEND_CSD, 0); r1 = mmcsd_get_r1(); if(r1 != MMCSD_GOODEC) { mmcsd_deselect(); return r1; } r1 = mmcsd_wait_for_token(DATA_START_TOKEN); if(r1 != MMCSD_GOODEC) { mmcsd_deselect(); return r1; }

    for(i = 0; i < 16; i++) buf[i] = spi_xfer(mmcsd_spi, 0xFF); mmcsd_deselect();

    printf("\r\nCSD_STRUCTURE: %X", (buf[0] & 0x0C) >> 2); printf("\r\nTAAC: %X", buf[1]); printf("\r\nNSAC: %X", buf[2]); printf("\r\nTRAN_SPEED: %X", buf[3]); printf("\r\nCCC: %lX", (make16(buf[4], buf[5]) & 0xFFF0) >> 4); printf("\r\nREAD_BL_LEN: %X", buf[5] & 0x0F); printf("\r\nREAD_BL_PARTIAL: %X", (buf[6] & 0x80) >> 7); printf("\r\nWRITE_BLK_MISALIGN: %X", (buf[6] & 0x40) >> 6); printf("\r\nREAD_BLK_MISALIGN: %X", (buf[6] & 0x20) >> 5); printf("\r\nDSR_IMP: %X", (buf[6] & 0x10) >> 4); printf("\r\nC_SIZE: %lX", (((buf[6] & 0x03) 6))); printf("\r\nVDD_R_CURR_MIN: %X", (buf[8] & 0x38) >> 3); printf("\r\nVDD_R_CURR_MAX: %X", buf[8] & 0x07); printf("\r\nVDD_W_CURR_MIN: %X", (buf[9] & 0xE0) >> 5); printf("\r\nVDD_W_CURR_MAX: %X", (buf[9] & 0x1C) >> 2); printf("\r\nC_SIZE_MULT: %X", ((buf[9] & 0x03) > 7)); printf("\r\nERASE_BLK_EN: %X", (buf[10] & 0x40) >> 6); printf("\r\nSECTOR_SIZE: %X", ((buf[10] & 0x3F) >7)); printf("\r\nWP_GRP_SIZE: %X", buf[11] & 0x7F); printf("\r\nWP_GRP_ENABLE: %X", (buf[12] & 0x80) >> 7); printf("\r\nR2W_FACTOR: %X", (buf[12] & 0x1C) >> 2); printf("\r\nWRITE_BL_LEN: %X", ((buf[12] & 0x03) >6)); printf("\r\nWRITE_BL_PARTIAL: %X", (buf[13] & 0x20) >> 5); printf("\r\nFILE_FORMAT_GRP: %X", (buf[14] & 0x80) >> 7); printf("\r\nCOPY: %X", (buf[14] & 0x40) >> 6); printf("\r\nPERM_WRITE_PROTECT: %X", (buf[14] & 0x20) >> 5); printf("\r\nTMP_WRITE_PROTECT: %X", (buf[14] & 0x10) >> 4); printf("\r\nFILE_FORMAT: %X", (buf[14] & 0x0C) >> 2); printf("\r\nCRC: %X", buf[15]);

    return r1;}

    MMCSD_err mmcsd_print_cid(){ uint8_t buf[16], i, r1;

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    11 of 54 3/17/2015 3:49 PM

  • // MMCs don't support this command if(g_card_type == MMC) return MMCSD_PARAM_ERR; mmcsd_select(); mmcsd_send_cmd(SEND_CID, 0); r1 = mmcsd_get_r1(); if(r1 != MMCSD_GOODEC) { mmcsd_deselect(); return r1; } r1 = mmcsd_wait_for_token(DATA_START_TOKEN); if(r1 != MMCSD_GOODEC) { mmcsd_deselect(); return r1; } for(i = 0; i < 16; i++) buf[i] = spi_xfer(mmcsd_spi, 0xFF); mmcsd_deselect(); printf("\r\nManufacturer ID: %X", buf[0]); printf("\r\nOEM/Application ID: %c%c", buf[1], buf[2]); printf("\r\nOEM/Application ID: %c%c%c%c%c", buf[3], buf[4], buf[5], buf[6],buf[7]); printf("\r\nProduct Revision: %X", buf[8]); printf("\r\nSerial Number: %X%X%X%X", buf[9], buf[10], buf[11], buf[12]); printf("\r\nManufacturer Date Code: %X%X", buf[13] & 0x0F, buf[14]); printf("\r\nCRC-7 Checksum: %X", buf[15]);

    return r1;}

    MMCSD_err mmcsd_sd_status(uint8_t r2[]){ uint8_t i;

    mmcsd_select(); mmcsd_send_cmd(APP_CMD, 0); r2[0]=mmcsd_get_r1(); mmcsd_deselect();

    mmcsd_select(); mmcsd_send_cmd(SD_STATUS, 0);

    for(i = 0; i < 64; i++) spi_xfer(mmcsd_spi, 0xFF);

    mmcsd_deselect();

    return mmcsd_get_r2(r2);}

    MMCSD_err mmcsd_send_status(uint8_t r2[]){ mmcsd_send_cmd(SEND_STATUS, 0); return mmcsd_get_r2(r2);}

    MMCSD_err mmcsd_set_blocklen(uint32_t blocklen){ mmcsd_send_cmd(SET_BLOCKLEN, blocklen); return mmcsd_get_r1();}

    MMCSD_err mmcsd_read_single_block(uint32_t address){ mmcsd_send_cmd(READ_SINGLE_BLOCK, address); return mmcsd_get_r1();}

    MMCSD_err mmcsd_write_single_block(uint32_t address){

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    12 of 54 3/17/2015 3:49 PM

  • mmcsd_send_cmd(WRITE_BLOCK, address); return mmcsd_get_r1();}

    MMCSD_err mmcsd_sd_send_op_cond(void){ mmcsd_send_cmd(SD_SEND_OP_COND, 0); return mmcsd_get_r1();}

    MMCSD_err mmcsd_app_cmd(void){ mmcsd_send_cmd(APP_CMD, 0); return mmcsd_get_r1();}

    MMCSD_err mmcsd_read_ocr(int r3[]){ mmcsd_send_cmd(READ_OCR, 0); return mmcsd_get_r3(r3);}

    MMCSD_err mmcsd_crc_on_off(int1 crc_enabled){ mmcsd_send_cmd(CRC_ON_OFF, crc_enabled); g_CRC_enabled = crc_enabled; return mmcsd_get_r1();}

    MMCSD_err mmcsd_send_cmd(uint8_t cmd, uint32_t arg){ uint8_t packet[6]; // the entire command, argument, and crc in one variable // construct the packet // every command on an SD card is or'ed with 0x40 packet[0] = cmd | 0x40; packet[1] = make8(arg, 3); packet[2] = make8(arg, 2); packet[3] = make8(arg, 1); packet[4] = make8(arg, 0);

    // calculate the crc if needed if(g_CRC_enabled) packet[5] = mmcsd_crc7(packet, 5); else packet[5] = 0xFF;

    // transfer the command and argument, with an extra 0xFF hacked in there spi_xfer(mmcsd_spi, packet[0]); spi_xfer(mmcsd_spi, packet[1]); spi_xfer(mmcsd_spi, packet[2]); spi_xfer(mmcsd_spi, packet[3]); spi_xfer(mmcsd_spi, packet[4]); spi_xfer(mmcsd_spi, packet[5]);//! spi_write2(packet[0]);//! spi_write2(packet[1]);//! spi_write2(packet[2]);//! spi_write2(packet[3]);//! spi_write2(packet[4]);//! spi_write2(packet[5]);

    return MMCSD_GOODEC;}

    MMCSD_err mmcsd_get_r1(void){ uint8_t response = 0, // place to hold the response coming back from the SPI line timeout = 0xFF; // maximum amount loops to wait for idle before gettingimpatient and leaving the function with an error code // loop until timeout == 0

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    13 of 54 3/17/2015 3:49 PM

  • while(timeout) { // read what's on the SPI line // the SD/MMC requires that you leave the line high when you're waiting fordata from it response = spi_xfer(mmcsd_spi, 0xFF); //response = spi_xfer(mmcsd_spi, 0x00);//leave the line idle // check to see if we got a response if(response != 0xFF) { // fill in the response that we got and leave the function return response; }

    // wait for a little bit longer timeout--; } // for some reason, we didn't get a response back from the card // return the proper error codes return RESP_TIMEOUT;}

    MMCSD_err mmcsd_get_r2(uint8_t r2[]){ r2[1] = mmcsd_get_r1(); r2[0] = spi_xfer(mmcsd_spi, 0xFF); return 0;}

    MMCSD_err mmcsd_get_r3(uint8_t r3[]){ return mmcsd_get_r7(r3);}

    MMCSD_err mmcsd_get_r7(uint8_t r7[]){ uint8_t i; // counter for loop // the top byte of r7 is r1 r7[4]=mmcsd_get_r1(); // fill in the other 4 bytes for(i = 0; i < 4; i++) r7[3 - i] = spi_xfer(mmcsd_spi, 0xFF);

    return r7[4];}

    MMCSD_err mmcsd_wait_for_token(uint8_t token){ MMCSD_err r1; // get a token r1 = mmcsd_get_r1(); // check to see if the token we recieved was the one that we were looking for if(r1 == token) return MMCSD_GOODEC; // if that wasn't right, return the error return r1; }

    unsigned int8 mmcsd_crc7(char *data,uint8_t length){ uint8_t i, ibit, c, crc; crc = 0x00; //Set initial value

    for (i = 0; i < length; i++, data++) { c = *data;

    for (ibit = 0; ibit < 8; ibit++)

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    14 of 54 3/17/2015 3:49 PM

  • { crc = crc
  • MMCSD_err ec = MMCSD_GOODEC; uint32_t //cur_block, new_block,address; int value; // make sure we're still on the same block //cur_block = g_mmcsdBufferAddress - (g_mmcsdBufferAddress %MMCSD_MAX_BLOCK_SIZE); // new_block = (new_addr) % MMCSD_MAX_BLOCK_SIZE; // printf(" move buffer: new ad = %lX, new_addr mod max_block --> %lX \n\r",new_addr, new_block) ; address = new_addr-g_mmcsdPartitionOffset; // new_block = new_addr - (new_addr % MMCSD_MAX_BLOCK_SIZE); new_block = address - (address % MMCSD_MAX_BLOCK_SIZE); // printf(" move buffer: new block befor offset = %lX \n\r", new_block) ; new_block += g_mmcsdPartitionOffset; // printf(" move buffer: g_mmcsdBufferAddress = %lX \n\r", g_mmcsdBufferAddress);// printf(" move buffer: new block = %lX \n\r", new_block) ; //if(cur_block != new_block) if(g_mmcsdBufferAddress != new_block) { // printf(" move buffer: g_mmcsdBufferAddress = %lX :new block = %lX\n\r", g_mmcsdBufferAddress, new_block ) ; // dump the old buffer if (g_MMCSDBufferChanged) { printf(" update data\n\r") ; ec = mmcsd_flush_buffer(); if(ec != MMCSD_GOODEC) return ec; g_MMCSDBufferChanged = FALSE; } // figure out the best place for a block g_mmcsdBufferAddress = new_block; // printf(" move buffer: new_block = %lX \n\r", g_mmcsdBufferAddress) ; // load up a new buffer ec = mmcsd_load_buffer(); //printf("move_buffer: load new buffer: \r\n"); // for(address= 0 ; address
  • ec = mmcsd_move_buffer(addr); if(ec != MMCSD_GOODEC) return ec; g_mmcsd_buffer[addr % MMCSD_MAX_BLOCK_SIZE] = data; // value = addr % MMCSD_MAX_BLOCK_SIZE;// printf("value=%lX:x%c ",value,g_mmcsd_buffer[value]) ; g_MMCSDBufferChanged = TRUE;

    return MMCSD_GOODEC;}

    #endif

    the nex lib fat.c[code:1:f803a1d0cb]///////////////////////////////////////////////////////////////////////////// FAT_PIC.C //////// //////// Driver/Library for a FAT filesystem with a PIC //////// //////// This Library was designed to resemble standard ANSI C I/O as //////// much as possible. There are, however, some caveats to this. //////// Please read the comments to make sure the inputs and outputs //////// to each function are understood before using anything in //////// this library. //////// //////// This library supports FAT16 and FAT32, but not both at the same //////// time (this is a compile option, see options below). It is //////// recommended to use FAT32, FAT32 also has been tested more. //////// //////// Any function with an argument taking in a file name must be in //////// the form of... //////// "/filename.fil" for a file in the root directory //////// "/Directory/filename.fil" for a file in a subdirectory of root //////// "/Directory/Subdirectory/filename.fil" and so on... //////// //////// Any function with an argument taking in a directory name must //////// be in the form of... //////// "/Dirname/" for a directory in the root directory //////// "/Dirname/Subdirname/" for a directory in a subdirectory of //////// root and so on... //////// //////// A compatable media library must be provided. This is //////// documented after the User Functions. //////// //////// -- User Functions -- //////// //////// fat_init() //////// Initializes the FAT library, also initializes the media. //////// //////// fatopen(char *name, char *mode, FILE *fstream) //////// Opens up a FILE stream to a specified file with the specified //////// permission mode: //////// Permissions: "r" = read //////// "w" = write //////// "a" = append //////// "rb" = read binarily ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    17 of 54 3/17/2015 3:49 PM

  • //// "w" will erase all of the data in the file upon //////// the opening of the file. //////// "a" will tack on all of the data to the end of the //////// file. //////// "r" will keep on reading until the stream //////// hits an '\0' //////// "rb" will keep on reading until the amount of //////// bytes read equals the size of the file. //////// //////// Unlike standard C fopen(), this does not malloc a FILE - //////// instead the caller will have to have allready allocated a //////// a FILE and pass a pointer to it. //////// //////// fatreopen(char *name, char *mode, FILE *fstream) //////// Closes a FILE stream, then reopens the stream with a new file //////// and new permissions. //////// //////// fatclose(FILE *fstream) //////// Closes a FILE stream. It is very important to call this //////// function when you're done reading or writing to a file. //// //////// //////// fatgetc(FILE *fstream) //////// Gets a character from a stream. An EOF will be returned at //////// different times depending on whether or not the stream is //////// reading binarily. If not reading binarily: EOF when the //////// stream reads a '\0'. If reading binarily: EOF when the amount //////// of bytes read equals the size of the file (end of file). //////// //////// fatputc(char c, FILE *fstream) //////// Puts a character into a stream (write to the file). //////// Writes are buffered, so the media may not be written to until //////// a fatclose(). //////// //////// char* fatgets(char* str, int num, FILE *fstream) //////// Gets characters from a stream until either a '\r', EOF, or //////// num - 1 is hit. //////// //////// fatputs(char* str, FILE *fstream) //////// Puts a string into a stream (write a string to the file). //////// //////// fatprintf(FILE *stream): Printfs the entire stream. //////// printf()'s the entire stream (printf()'s the contents of the//// file).//// //////// fatgetpos(FILE *fstream, fatpos_t *pos) //////// Gets the current position of the stream/file, saves to pos. //////// //////// fatsetpos(FILE *fstream, fatpos_t *pos) //////// Sets the current position of the stream/file. //////// //////// fatseek(FILE *fstream, int32 offset, int origin) //////// Sets the current position of the stream according to the //////// origin parameter: //////// SEEK_CUR: Set position relative to the //////// current stream position. //////// SEEK_END: Set position relative to the //////// end of the stream. //////// SEEK_SET: Set position relative to the //////// beginning of the stream. ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    18 of 54 3/17/2015 3:49 PM

  • //// //////// fateof(FILE *fstream) //////// Returns non-zero if the stream/file position is at EOF, //////// non-zero if there are still data left in the stream. //////// //////// faterror(FILE *fstream): //////// Returns non-zero if there have been errors with the stream, //////// zero if the stream has been operating correctly since it has //////// been opened. //////// //////// fatread(void* buffer, int size, int32 num, FILE* fstream) //////// Reads size*num chars from the stream, saves to buffer. //////// //////// fatwrite(void* buffer, int size, int32 num, FILE* fstream) //////// Writes size*num chars from buffer to the stream. //////// //////// fatflush(FILE *fstream) //////// Flushes the buffer in a stream. //////// //////// clearerr(FILE *fstream) //////// Clears any error flags in the stream. //////// //////// rewind(FILE *fstream) //////// Send the stream back to the beginning of the file. //////// //////// fatpos_t fattell(FILE *fstream) //////// Returns the current position of the stream. //////// //////// rm_file(char *fname) //////// Removes a file. //////// //////// rm_dir(char *dirname) //////// Removes a directory. //////// //////// mk_file(char *fname) //////// Makes a file, file will be blank. //////// //////// mk_dir(char *dirname) //////// Makes a directory. //////// //////// format(int32 mediaSize) //////// Formats the media into a FAT32 or FAT16 file system. //////// If you specify a mediaSize larger than the actual media bad //////// things will happen. If you specify a mediaSize smaller than //////// the actual media size will simply limit the filesystem from //////// using 0 to mediaSize-1. Anything after mediaSize can be used //////// by the application (perhaps as a general purpose EEPROM?) //////// NOTE: Windows thinks the filesystem is RAW. //////// NOTE: This may be a little buggy. //////// ///////////////////////////////////////////////////////////////////////////////// //////// This library was written to use CCS's MMC/SD library as the //////// media source. If you want to use a different media source, //////// you must provide the following 4 functions: //////// //////// int8 mmcsd_init(void); //////// Initializes the media. This will be called by fat_init(). //////// ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    19 of 54 3/17/2015 3:49 PM

  • //// int8 mmcsd_read_bytes(int32 a, int16 s, char *p); //////// Read s bytes from p to the media starting at address a. //////// //////// int8 mmcsd_write_data(int32 a, int16 s, char *p); //////// Write s bytes from p to the media starting at address a. //////// To maximize throughput on some medias, it's a good idea to //////// buffer writes in this function. //////// //////// int8 mmcsd_flush_buffer(void); //////// If your write function is buffering writes, this will flush //////// the buffer and write it to the media. //////// //////// All four functions should return 0 if OK, non-zero if error. //////// ///////////////////////////////////////////////////////////////////////////////// (C) Copyright 2007 Custom Computer Services //////// This source code may only be used by licensed users of the CCS //////// C compiler. This source code may only be distributed to other //////// licensed users of the CCS C compiler. No other use, //////// reproduction or distribution is permitted without written //////// permission. Derivative programs created using this software //////// in object code form are not restricted in any way. /////////////////////////////////////////////////////////////////////////////

    // NOTE This library has no concept of what time and date it currently is.// All files and folders created or modified using this library// will have invalid/inaccurate timestamps and datestamps.

    // NOTE To save on ROM and RAM space, the user of this library will have to// define what type of FAT they will be working with. The defines are// in the Useful Defines section below.

    // NOTE For faster writing or appending for an application such as a logger,// uncomment #FAST_FAT below. This will make the FAT library assume// there is one file on the card to write or append to, thereby// making writing and appending much faster. Reading is impossible in// this mode.// THIS IS NOT TESTED VERY WELL YET!

    // NOTE The current maximum file name length (full path) is 32 characters// long. If longer file names are desired, change the// MAX_FILE_NAME_LENGTH define below. Creating a file whose full path// is longer than MAX_FILE_NAME_LENGTH may lead to weird operation. Keep// in mind that making this define larger will make your RAM usage go// up.

    #ifndef FAT_PIC_C#define FAT_PIC_C

    #include #include #case

    ///////////////////////// ////// Useful Defines ////// /////////////////////////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    20 of 54 3/17/2015 3:49 PM

  • /// Define your FAT type here ///#define FAT16//#define FAT32

    /// For faster single-file writing, uncomment this line below /////#define FAST_FAT

    /// Everything else ///#define MAX_FILE_NAME_LENGTH 0x20 // the maximum length of a file name for our FAT, including /0terminator#define STREAM_BUF_SIZE 0x20 // how big the FILE buffer is. 0x20 is optimal

    //////////////////////////////////////////////////////////////////

    #define EOF -1#define GOODEC 0#define fatpos_t int32#define SEEK_CUR 0#define SEEK_END 1#define SEEK_SET 2

    /////////////////////////// ////// Global Variables ////// ///////////////////////////

    unsigned int16Bytes_Per_Cluster, // number of addressable bytes per clusterFAT_Start; // when the first FAT begins

    unsigned int32Data_Start, // when data startsFAT_Length, // the length of one FATNext_Free_Clust, // where the next free cluster isRoot_Dir; // when the root directory starts

    enum filetype{Data_File, // the stream is pointing to a binary, data fileDirectory, // the stream is pointing to a directoryNone // the stream isn't currently pointing to anything};

    enum ioflags{Closed = 0x00,Read = 0x01,Write = 0x02,Append = 0x04,Binary = 0x08,EOF_Reached = 0x10,Read_Error = 0x20,Write_Error = 0x40,File_Not_Found = 0x80};

    struct iobuf{

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    21 of 54 3/17/2015 3:49 PM

  • fatpos_tBytes_Until_EOF, // how many bytes until the stream's end of fileCur_Char, // the current byte that the stream is pointing atEntry_Addr, // the entry address of the file that is associated with the streamParent_Start_Addr, // the parent's start adddress of the file that is associated with the streamSize, // the size of the file that is associated with the streamStart_Addr; // the beginning of the data in the file that is associated with the stream

    enum filetype File_Type; // the type of file that is associated with the stream

    enum ioflags Flags; // any associated input/output flag

    int Buf[STREAM_BUF_SIZE]; // this is a buffer so that during fatputc() or fatgetc()// the media won't have to be read at every character};typedef struct iobuf FILE;

    ////////////////////////////// ////// Function Prototypes ////// //////////////////////////////

    /// Standard C Functions ///signed int fatopen(char fname[], char mode[], FILE* stream);signed int fatreopen(char fname[], char mode[], FILE* stream);signed int fatclose(FILE* stream);signed int fatgetc(FILE* stream);signed int fatputc(int ch, FILE* stream);char* fatgets(char* str, int num, FILE* stream);signed int fatputs(char* str, FILE* stream);signed int fatprintf(FILE* stream);signed int fatgetpos(FILE* stream, fatpos_t* position);signed int fatsetpos(FILE* stream, fatpos_t* position);signed int fatseek(FILE* stream, int32 offset, int origin);signed int fateof(FILE* stream);signed int faterror(FILE* stream);signed int fatread(void* buffer, int size, int32 num, FILE* stream);signed int fatwrite(void* buffer, int size, int32 count, FILE* stream );signed int fatflush(FILE* stream);signed int remove(char* fname);void clearerr(FILE* stream);void rewind(FILE* stream);fatpos_t fattell(FILE* stream);

    /// Non-Standard C Functions ///signed int rm_file(char fname[]);signed int rm_dir(char dname[]);signed int mk_file(char fname[]);signed int mk_dir(char dname[]);

    /// Functions' Utility Functions ///signed int set_file(char fname[], int attrib, FILE* stream);signed int get_file_name(int32 file_entry_addr, char name[]);signed int set_file_name(int32 parent_dir_addr, int32* entry_addr, char name[]);signed int get_short_file_name(int32 file_entry_addr, char sname[], int type);signed int make_short_file_name(int32 parent_dir_addr, char fname[], char sname[]);int long_name_chksum (int* pFcbName);signed int check_invalid_char(char fname[]);

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    22 of 54 3/17/2015 3:49 PM

  • #ifdef FAT32signed int get_next_free_cluster(int32* my_cluster);signed int dealloc_clusters(int32 start_cluster);signed int alloc_clusters(int32 start_cluster, int32* new_cluster_addr);signed int clear_cluster(int32 cluster);signed int write_fat(int32 cluster, int32 data);#else // FAT16signed int get_next_free_cluster(int16* my_cluster);signed int dealloc_clusters(int16 start_cluster);signed int alloc_clusters(int16 start_cluster, int32* new_cluster_addr);signed int clear_cluster(int16 cluster);signed int write_fat(int16 cluster, int16 data);#endif // #ifdef FAT32signed int get_next_file(FILE* stream);signed int get_prev_file(FILE* stream);signed int get_next_free_addr(int32* my_addr);signed int get_next_free_entry(int32* start_addr);signed int get_next_entry(int32* start_addr);signed int get_prev_entry(int32* start_addr);signed int read_buffer(FILE* stream, int* val);signed int write_buffer(FILE* stream, int val);void fill_entry(char the_entry[], char val, int8 start_ind);void disp_timestamp(int16 timestamp);void disp_datestamp(int16 datestamp);

    /// Data Utility Functions ///signed int fat_init();#ifdef FAT32signed int get_next_cluster(int32* my_cluster);signed int get_prev_cluster(int32* my_cluster);int32 cluster_to_addr(int32 cluster);int32 addr_to_cluster(int32 addr);#else // FAT16signed int get_next_cluster(int16* my_cluster);signed int get_prev_cluster(int16* my_cluster);int32 cluster_to_addr(int16 cluster);int16 addr_to_cluster(int32 addr);#endif // #ifdef FAT32signed int get_next_addr(int32* my_addr);signed int get_prev_addr(int32* my_addr);signed int format(int32 DskSize);

    /// Debugging Utility Functions ///signed int disp_folder_contents(char foldername[]);signed int dump_addr(int32 from, int32 to);signed int dump_clusters(int32 from, int32 to);void disp_fat_stats();signed int fatprintfinfo(FILE* stream);

    /////////////////////////////////// ////// Function Implementations ////// ///////////////////////////////////

    /// Standard C Functions ///

    /*signed int fatopen(char fname[], char mode[], FILE* stream)

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    23 of 54 3/17/2015 3:49 PM

  • Summary: This will open up a file stream for reading, writing, or appending.Param fname: The full path of the file to open.Param mode: The mode to open up the stream into."r" = Read"w" = Write"a" = Append"rb", "wb", "ab" = Read, Write, or Append in Binary modeParam stream: The stream to open up.Returns: EOF if there was a problem, GOODEC if everything went okay.Note: fname must be in the form of /filename.fil for a file in the root directory/Directory/filename.fil for a file in a subdirectory of root/Directory/Subdirectory/filename.fil and so on...Note: Standard C will make a file in case a file isn't found,however due to recursion this is not possible in CCSC.*/signed int fatopen(char fname[], char mode[], FILE* stream){int fname_parse_pos = 1; // the current index of the fname character

    char target_file[MAX_FILE_NAME_LENGTH]; // temporary buffer to hold names of files

    FILE cur_stream; // this will be the stream that will be returned if all goes well

    #ifndef FAST_FATintdepth = 0, // how many subdirectories deep the file istarget_file_parse_pos; // the current index of the target_file character#endif // #ifndef FAST_FAT

    // set flags#ifdef FAST_FATswitch(mode[0]){case 'w':cur_stream.Flags = Write;break;case 'a':cur_stream.Flags = Append;break;default:return EOF;}

    // start looking for the file, start at rootcur_stream.Start_Addr = cur_stream.Parent_Start_Addr = Root_Dir;

    while(fname[fname_parse_pos] != '\0'){target_file[fname_parse_pos - 1] = fname[fname_parse_pos];fname_parse_pos += 1;}

    target_file[fname_parse_pos] = '\0';

    // find the file inside of its subdirectoryif(set_file(target_file, 0x20, &cur_stream) != GOODEC){cur_stream.Flags |= File_Not_Found;*stream = cur_stream;

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    24 of 54 3/17/2015 3:49 PM

  • return EOF;}

    // at this point, we've found the file*stream = cur_stream;return GOODEC;#else // NO FAST_FATswitch(mode[0]){case 'r':cur_stream.Flags = Read;break;case 'w':cur_stream.Flags = Write;break;case 'a':cur_stream.Flags = Append;break;default:return EOF;}

    if(mode[1] == 'b')cur_stream.Flags |= Binary;

    // start looking for the file, start at rootcur_stream.Start_Addr = cur_stream.Parent_Start_Addr = Root_Dir;//printf("fatopen:cur_stream.Start_Addr--> %lX \n\r", cur_stream.Start_Addr);// figure out how deep we have to go, count how many '/' we have in the stringwhile(fname[fname_parse_pos] != '\0'){if(fname[fname_parse_pos] == '/')depth++;fname_parse_pos += 1;}

    // start the fname index at 1 to skip over the '/'fname_parse_pos = 1;

    // open up to the subdirectory, if possiblewhile(depth > 0){// find the name of our next target directorytarget_file_parse_pos = 0;while(fname[fname_parse_pos] != '/'){// check to make sure that we're not at the end of a poorly formatted stringif(fname[fname_parse_pos] == '\0')return EOF;

    // fill up the buffer and increment the indexestarget_file[target_file_parse_pos] = fname[fname_parse_pos];fname_parse_pos += 1;target_file_parse_pos += 1;}

    // increment the fname index one more because it's currently pointing at the '/'fname_parse_pos += 1;

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    25 of 54 3/17/2015 3:49 PM

  • // tack on a \0 to the end of the target file to terminate the stringtarget_file[target_file_parse_pos] = '\0';// printf("SET FILE\n\r") ;

    // check to see if the directory exists and open it if possible, otherwise exit because the directorydoesn't existif(set_file(target_file, 0x10, &cur_stream) != GOODEC){cur_stream.Flags |= File_Not_Found;*stream = cur_stream;return EOF;}depth -= 1;}

    // check to see if we're trying to open just a directoryif(fname[fname_parse_pos] == '\0'){*stream = cur_stream;return GOODEC;}

    // now that we have the locat

    opas

    Joined: 17 Jun 2012Posts: 2

    more bug found [2]Posted: Thu Jun 21, 2012 10:16 pm

    I do errors, now my code again

    Fact.c

    [code:1:9ea10b2720]///////////////////////////////////////////////////////////////////////////// FAT_PIC.C //////// //////// Driver/Library for a FAT filesystem with a PIC //////// //////// This Library was designed to resemble standard ANSI C I/O as //////// much as possible. There are, however, some caveats to this. //////// Please read the comments to make sure the inputs and outputs //////// to each function are understood before using anything in //////// this library. //////// //////// This library supports FAT16 and FAT32, but not both at the same //////// time (this is a compile option, see options below). It is //////// recommended to use FAT32, FAT32 also has been tested more. //////// //////// Any function with an argument taking in a file name must be in //////// the form of... //////// "/filename.fil" for a file in the root directory //////// "/Directory/filename.fil" for a file in a subdirectory of root //////// "/Directory/Subdirectory/filename.fil" and so on... //////// //////// Any function with an argument taking in a directory name must //////// be in the form of... //////// "/Dirname/" for a directory in the root directory //////// "/Dirname/Subdirname/" for a directory in a subdirectory of //////// root and so on... //////// //////// A compatable media library must be provided. This is //////// documented after the User Functions. ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    26 of 54 3/17/2015 3:49 PM

  • //// //////// -- User Functions -- //////// //////// fat_init() //////// Initializes the FAT library, also initializes the media. //////// //////// fatopen(char *name, char *mode, FILE *fstream) //////// Opens up a FILE stream to a specified file with the specified //////// permission mode: //////// Permissions: "r" = read //////// "w" = write //////// "a" = append //////// "rb" = read binarily //////// "w" will erase all of the data in the file upon //////// the opening of the file. //////// "a" will tack on all of the data to the end of the //////// file. //////// "r" will keep on reading until the stream //////// hits an '\0' //////// "rb" will keep on reading until the amount of //////// bytes read equals the size of the file. //////// //////// Unlike standard C fopen(), this does not malloc a FILE - //////// instead the caller will have to have allready allocated a //////// a FILE and pass a pointer to it. //////// //////// fatreopen(char *name, char *mode, FILE *fstream) //////// Closes a FILE stream, then reopens the stream with a new file //////// and new permissions. //////// //////// fatclose(FILE *fstream) //////// Closes a FILE stream. It is very important to call this //////// function when you're done reading or writing to a file. //// //////// //////// fatgetc(FILE *fstream) //////// Gets a character from a stream. An EOF will be returned at //////// different times depending on whether or not the stream is //////// reading binarily. If not reading binarily: EOF when the //////// stream reads a '\0'. If reading binarily: EOF when the amount //////// of bytes read equals the size of the file (end of file). //////// //////// fatputc(char c, FILE *fstream) //////// Puts a character into a stream (write to the file). //////// Writes are buffered, so the media may not be written to until //////// a fatclose(). //////// //////// char* fatgets(char* str, int num, FILE *fstream) //////// Gets characters from a stream until either a '\r', EOF, or //////// num - 1 is hit. //////// //////// fatputs(char* str, FILE *fstream) //////// Puts a string into a stream (write a string to the file). //////// //////// fatprintf(FILE *stream): Printfs the entire stream. //////// printf()'s the entire stream (printf()'s the contents of the//// file).//// //////// fatgetpos(FILE *fstream, fatpos_t *pos) //////// Gets the current position of the stream/file, saves to pos. ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    27 of 54 3/17/2015 3:49 PM

  • //// //////// fatsetpos(FILE *fstream, fatpos_t *pos) //////// Sets the current position of the stream/file. //////// //////// fatseek(FILE *fstream, int32 offset, int origin) //////// Sets the current position of the stream according to the //////// origin parameter: //////// SEEK_CUR: Set position relative to the //////// current stream position. //////// SEEK_END: Set position relative to the //////// end of the stream. //////// SEEK_SET: Set position relative to the //////// beginning of the stream. //////// //////// fateof(FILE *fstream) //////// Returns non-zero if the stream/file position is at EOF, //////// non-zero if there are still data left in the stream. //////// //////// faterror(FILE *fstream): //////// Returns non-zero if there have been errors with the stream, //////// zero if the stream has been operating correctly since it has //////// been opened. //////// //////// fatread(void* buffer, int size, int32 num, FILE* fstream) //////// Reads size*num chars from the stream, saves to buffer. //////// //////// fatwrite(void* buffer, int size, int32 num, FILE* fstream) //////// Writes size*num chars from buffer to the stream. //////// //////// fatflush(FILE *fstream) //////// Flushes the buffer in a stream. //////// //////// clearerr(FILE *fstream) //////// Clears any error flags in the stream. //////// //////// rewind(FILE *fstream) //////// Send the stream back to the beginning of the file. //////// //////// fatpos_t fattell(FILE *fstream) //////// Returns the current position of the stream. //////// //////// rm_file(char *fname) //////// Removes a file. //////// //////// rm_dir(char *dirname) //////// Removes a directory. //////// //////// mk_file(char *fname) //////// Makes a file, file will be blank. //////// //////// mk_dir(char *dirname) //////// Makes a directory. //////// //////// format(int32 mediaSize) //////// Formats the media into a FAT32 or FAT16 file system. //////// If you specify a mediaSize larger than the actual media bad //////// things will happen. If you specify a mediaSize smaller than //////// the actual media size will simply limit the filesystem from //////// using 0 to mediaSize-1. Anything after mediaSize can be used ////

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    28 of 54 3/17/2015 3:49 PM

  • //// by the application (perhaps as a general purpose EEPROM?) //////// NOTE: Windows thinks the filesystem is RAW. //////// NOTE: This may be a little buggy. //////// ///////////////////////////////////////////////////////////////////////////////// //////// This library was written to use CCS's MMC/SD library as the //////// media source. If you want to use a different media source, //////// you must provide the following 4 functions: //////// //////// int8 mmcsd_init(void); //////// Initializes the media. This will be called by fat_init(). //////// //////// int8 mmcsd_read_bytes(int32 a, int16 s, char *p); //////// Read s bytes from p to the media starting at address a. //////// //////// int8 mmcsd_write_data(int32 a, int16 s, char *p); //////// Write s bytes from p to the media starting at address a. //////// To maximize throughput on some medias, it's a good idea to //////// buffer writes in this function. //////// //////// int8 mmcsd_flush_buffer(void); //////// If your write function is buffering writes, this will flush //////// the buffer and write it to the media. //////// //////// All four functions should return 0 if OK, non-zero if error. //////// ///////////////////////////////////////////////////////////////////////////////// (C) Copyright 2007 Custom Computer Services //////// This source code may only be used by licensed users of the CCS //////// C compiler. This source code may only be distributed to other //////// licensed users of the CCS C compiler. No other use, //////// reproduction or distribution is permitted without written //////// permission. Derivative programs created using this software //////// in object code form are not restricted in any way. /////////////////////////////////////////////////////////////////////////////

    // NOTE This library has no concept of what time and date it currently is.// All files and folders created or modified using this library// will have invalid/inaccurate timestamps and datestamps.

    // NOTE To save on ROM and RAM space, the user of this library will have to// define what type of FAT they will be working with. The defines are// in the Useful Defines section below.

    // NOTE For faster writing or appending for an application such as a logger,// uncomment #FAST_FAT below. This will make the FAT library assume// there is one file on the card to write or append to, thereby// making writing and appending much faster. Reading is impossible in// this mode.// THIS IS NOT TESTED VERY WELL YET!

    // NOTE The current maximum file name length (full path) is 32 characters// long. If longer file names are desired, change the// MAX_FILE_NAME_LENGTH define below. Creating a file whose full path// is longer than MAX_FILE_NAME_LENGTH may lead to weird operation. Keep// in mind that making this define larger will make your RAM usage go// up.

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    29 of 54 3/17/2015 3:49 PM

  • #ifndef FAT_PIC_C#define FAT_PIC_C

    #include #include #case

    ///////////////////////// ////// Useful Defines ////// /////////////////////////

    /// Define your FAT type here ///#define FAT16//#define FAT32

    /// For faster single-file writing, uncomment this line below /////#define FAST_FAT

    /// Everything else ///#define MAX_FILE_NAME_LENGTH 0x20 // the maximum length of a file name for our FAT, including /0terminator#define STREAM_BUF_SIZE 0x20 // how big the FILE buffer is. 0x20 is optimal

    //////////////////////////////////////////////////////////////////

    #define EOF -1#define GOODEC 0#define fatpos_t int32#define SEEK_CUR 0#define SEEK_END 1#define SEEK_SET 2

    /////////////////////////// ////// Global Variables ////// ///////////////////////////

    unsigned int16Bytes_Per_Cluster, // number of addressable bytes per clusterFAT_Start; // when the first FAT begins

    unsigned int32Data_Start, // when data startsFAT_Length, // the length of one FATNext_Free_Clust, // where the next free cluster isRoot_Dir; // when the root directory starts

    enum filetype{Data_File, // the stream is pointing to a binary, data fileDirectory, // the stream is pointing to a directoryNone // the stream isn't currently pointing to anything};

    enum ioflags{

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    30 of 54 3/17/2015 3:49 PM

  • Closed = 0x00,Read = 0x01,Write = 0x02,Append = 0x04,Binary = 0x08,EOF_Reached = 0x10,Read_Error = 0x20,Write_Error = 0x40,File_Not_Found = 0x80};

    struct iobuf{fatpos_tBytes_Until_EOF, // how many bytes until the stream's end of fileCur_Char, // the current byte that the stream is pointing atEntry_Addr, // the entry address of the file that is associated with the streamParent_Start_Addr, // the parent's start adddress of the file that is associated with the streamSize, // the size of the file that is associated with the streamStart_Addr; // the beginning of the data in the file that is associated with the stream

    enum filetype File_Type; // the type of file that is associated with the stream

    enum ioflags Flags; // any associated input/output flag

    int Buf[STREAM_BUF_SIZE]; // this is a buffer so that during fatputc() or fatgetc()// the media won't have to be read at every character};typedef struct iobuf FILE;

    ////////////////////////////// ////// Function Prototypes ////// //////////////////////////////

    /// Standard C Functions ///signed int fatopen(char fname[], char mode[], FILE* stream);signed int fatreopen(char fname[], char mode[], FILE* stream);signed int fatclose(FILE* stream);signed int fatgetc(FILE* stream);signed int fatputc(int ch, FILE* stream);char* fatgets(char* str, int num, FILE* stream);signed int fatputs(char* str, FILE* stream);signed int fatprintf(FILE* stream);signed int fatgetpos(FILE* stream, fatpos_t* position);signed int fatsetpos(FILE* stream, fatpos_t* position);signed int fatseek(FILE* stream, int32 offset, int origin);signed int fateof(FILE* stream);signed int faterror(FILE* stream);signed int fatread(void* buffer, int size, int32 num, FILE* stream);signed int fatwrite(void* buffer, int size, int32 count, FILE* stream );signed int fatflush(FILE* stream);signed int remove(char* fname);void clearerr(FILE* stream);void rewind(FILE* stream);fatpos_t fattell(FILE* stream);

    /// Non-Standard C Functions ///

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    31 of 54 3/17/2015 3:49 PM

  • signed int rm_file(char fname[]);signed int rm_dir(char dname[]);signed int mk_file(char fname[]);signed int mk_dir(char dname[]);

    /// Functions' Utility Functions ///signed int set_file(char fname[], int attrib, FILE* stream);signed int get_file_name(int32 file_entry_addr, char name[]);signed int set_file_name(int32 parent_dir_addr, int32* entry_addr, char name[]);signed int get_short_file_name(int32 file_entry_addr, char sname[], int type);signed int make_short_file_name(int32 parent_dir_addr, char fname[], char sname[]);int long_name_chksum (int* pFcbName);signed int check_invalid_char(char fname[]);#ifdef FAT32signed int get_next_free_cluster(int32* my_cluster);signed int dealloc_clusters(int32 start_cluster);signed int alloc_clusters(int32 start_cluster, int32* new_cluster_addr);signed int clear_cluster(int32 cluster);signed int write_fat(int32 cluster, int32 data);#else // FAT16signed int get_next_free_cluster(int16* my_cluster);signed int dealloc_clusters(int16 start_cluster);signed int alloc_clusters(int16 start_cluster, int32* new_cluster_addr);signed int clear_cluster(int16 cluster);signed int write_fat(int16 cluster, int16 data);#endif // #ifdef FAT32signed int get_next_file(FILE* stream);signed int get_prev_file(FILE* stream);signed int get_next_free_addr(int32* my_addr);signed int get_next_free_entry(int32* start_addr);signed int get_next_entry(int32* start_addr);signed int get_prev_entry(int32* start_addr);signed int read_buffer(FILE* stream, int* val);signed int write_buffer(FILE* stream, int val);void fill_entry(char the_entry[], char val, int8 start_ind);void disp_timestamp(int16 timestamp);void disp_datestamp(int16 datestamp);

    /// Data Utility Functions ///signed int fat_init();#ifdef FAT32signed int get_next_cluster(int32* my_cluster);signed int get_prev_cluster(int32* my_cluster);int32 cluster_to_addr(int32 cluster);int32 addr_to_cluster(int32 addr);#else // FAT16signed int get_next_cluster(int16* my_cluster);signed int get_prev_cluster(int16* my_cluster);int32 cluster_to_addr(int16 cluster);int16 addr_to_cluster(int32 addr);#endif // #ifdef FAT32signed int get_next_addr(int32* my_addr);signed int get_prev_addr(int32* my_addr);signed int format(int32 DskSize);

    /// Debugging Utility Functions ///signed int disp_folder_contents(char foldername[]);signed int dump_addr(int32 from, int32 to);signed int dump_clusters(int32 from, int32 to);

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    32 of 54 3/17/2015 3:49 PM

  • void disp_fat_stats();signed int fatprintfinfo(FILE* stream);

    /////////////////////////////////// ////// Function Implementations ////// ///////////////////////////////////

    /// Standard C Functions ///

    /*signed int fatopen(char fname[], char mode[], FILE* stream)Summary: This will open up a file stream for reading, writing, or appending.Param fname: The full path of the file to open.Param mode: The mode to open up the stream into."r" = Read"w" = Write"a" = Append"rb", "wb", "ab" = Read, Write, or Append in Binary modeParam stream: The stream to open up.Returns: EOF if there was a problem, GOODEC if everything went okay.Note: fname must be in the form of /filename.fil for a file in the root directory/Directory/filename.fil for a file in a subdirectory of root/Directory/Subdirectory/filename.fil and so on...Note: Standard C will make a file in case a file isn't found,however due to recursion this is not possible in CCSC.*/signed int fatopen(char fname[], char mode[], FILE* stream){int fname_parse_pos = 1; // the current index of the fname character

    char target_file[MAX_FILE_NAME_LENGTH]; // temporary buffer to hold names of files

    FILE cur_stream; // this will be the stream that will be returned if all goes well

    #ifndef FAST_FATintdepth = 0, // how many subdirectories deep the file istarget_file_parse_pos; // the current index of the target_file character#endif // #ifndef FAST_FAT

    // set flags#ifdef FAST_FATswitch(mode[0]){case 'w':cur_stream.Flags = Write;break;case 'a':cur_stream.Flags = Append;break;default:return EOF;}

    // start looking for the file, start at rootcur_stream.Start_Addr = cur_stream.Parent_Start_Addr = Root_Dir;

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    33 of 54 3/17/2015 3:49 PM

  • while(fname[fname_parse_pos] != '\0'){target_file[fname_parse_pos - 1] = fname[fname_parse_pos];fname_parse_pos += 1;}

    target_file[fname_parse_pos] = '\0';

    // find the file inside of its subdirectoryif(set_file(target_file, 0x20, &cur_stream) != GOODEC){cur_stream.Flags |= File_Not_Found;*stream = cur_stream;return EOF;}

    // at this point, we've found the file*stream = cur_stream;return GOODEC;#else // NO FAST_FATswitch(mode[0]){case 'r':cur_stream.Flags = Read;break;case 'w':cur_stream.Flags = Write;break;case 'a':cur_stream.Flags = Append;break;default:return EOF;}

    if(mode[1] == 'b')cur_stream.Flags |= Binary;

    // start looking for the file, start at rootcur_stream.Start_Addr = cur_stream.Parent_Start_Addr = Root_Dir;//printf("fatopen:cur_stream.Start_Addr--> %lX \n\r", cur_stream.Start_Addr);// figure out how deep we have to go, count how many '/' we have in the stringwhile(fname[fname_parse_pos] != '\0'){if(fname[fname_parse_pos] == '/')depth++;fname_parse_pos += 1;}

    // start the fname index at 1 to skip over the '/'fname_parse_pos = 1;

    // open up to the subdirectory, if possiblewhile(depth > 0){// find the name of our next target directorytarget_file_parse_pos = 0;while(fname[fname_parse_pos] != '/'){

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    34 of 54 3/17/2015 3:49 PM

  • // check to make sure that we're not at the end of a poorly formatted stringif(fname[fname_parse_pos] == '\0')return EOF;

    // fill up the buffer and increment the indexestarget_file[target_file_parse_pos] = fname[fname_parse_pos];fname_parse_pos += 1;target_file_parse_pos += 1;}

    // increment the fname index one more because it's currently pointing at the '/'fname_parse_pos += 1;

    // tack on a \0 to the end of the target file to terminate the stringtarget_file[target_file_parse_pos] = '\0';// printf("SET FILE\n\r") ;

    // check to see if the directory exists and open it if possible, otherwise exit because the directorydoesn't existif(set_file(target_file, 0x10, &cur_stream) != GOODEC){cur_stream.Flags |= File_Not_Found;*stream = cur_stream;return EOF;}depth -= 1;}

    // check to see if we're trying to open just a directoryif(fname[fname_parse_pos] == '\0'){*stream = cur_stream;return GOODEC;}

    // now that we have the location of the subdirectory that the file is in, attempt to open the filetarget_file_parse_pos = 0;while(fname[fname_parse_pos] != '\0'){// fill up the buffer and increment the indexestarget_file[target_file_parse_pos] = fname[fname_parse_pos];fname_parse_pos += 1;target_file_parse_pos += 1;}

    // tack on a \0 to the end of the target file to terminate the stringtarget_file[target_file_parse_pos] = '\0';

    //printf("target file : %s \n\r",target_file) ;

    // find the file inside of its subdirectoryif(set_file(target_file, 0x20, &cur_stream) != GOODEC){cur_stream.Flags |= File_Not_Found;*stream = cur_stream;return EOF;}

    // at this point, we've found the file

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    35 of 54 3/17/2015 3:49 PM

  • *stream = cur_stream;return GOODEC;#endif // #ifdef FAST_FAT}

    /*signed int fatreopen(char fname[], char mode[], FILE* old_stream, FILE* new_stream)Summary: This will close a stream and then reopen it using new parameters.Param fname: The full path of the file to open.Param mode: The mode to open up the stream into."r" = Read"w" = Write"a" = Append"rb", "wb", "ab" = Read, Write, or Append in Binary modeParam stream: The stream to close and reopen.Returns: EOF if there was a problem, GOODEC if everything went okay.Note: fname must be in the form of /filename.fil for a file in the root directory/Directory/filename.fil for a file in a subdirectory of root/Directory/Subdirectory/filename.fil and so on...Note: Standard C will make a file in case a file isn't found,however due to recursion this is not possible in CCSC.*/signed int fatreopen(char fname[], char mode[], FILE* stream){// close the old streamif(fatclose(stream) == EOF)return EOF;

    // open the new streamif(fatopen(fname, mode, stream) == EOF)return EOF;

    return GOODEC;}

    /*signed int fatclose(FILE* stream)Summary: Closes a stream and commits any changes done to the file.Param: The stream to close.Returns: EOF if there was a problem, 0 if everything went okay.*/signed int fatclose(FILE* stream){int ec = 0;int value,address;int32 first_cluster;

    //for(address= 0 ; address Entry_Addr + address, 1, &value);

    // printf(" fatclose: stream->Entry_Addr --> %lX , HexVal --> %X, AsciiVal--> %c\n\r",stream->Entry_Addr+address, value, value) ;

    // }

    // commit data back to the stream's entry, if neededif((stream->Flags & Write) || (stream->Flags & Append)){

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    36 of 54 3/17/2015 3:49 PM

  • // write the new size of the fileif(mmcsd_write_data(stream->Entry_Addr + 0x1C, 4, &(stream->Size)) != GOODEC){// printf(" fatclose: stream->Entry_Addr --> %lX , stream->Size --> %lX\n\r",stream->Entry_Addr+0x1c, stream->Size) ;

    stream->Flags |= Write_Error;return EOF;}

    // check to see if the first cluster is already linked in the fileec += mmcsd_read_data(stream->Entry_Addr + 0x14, 2, (int16*)&first_cluster + 1);ec += mmcsd_read_data(stream->Entry_Addr + 0x1A, 2, &first_cluster);

    //printf(" fatclose: stream->Entry_Addr+0x14 --> %lX , first_cluster + 1 --> %lX\n\r",stream->Entry_Addr+0x14, first_cluster + 1) ;//printf(" fatclose: stream->Entry_Addr+0x1A --> %lX , first_cluster --> %lX\n\r",stream->Entry_Addr+0x1A, first_cluster) ;

    if(ec != GOODEC){stream->Flags |= Read_Error;return EOF;}

    // write the first cluster to the entry if neededif(first_cluster == 0){// convert the start address to a cluster numberfirst_cluster = addr_to_cluster(stream->Start_Addr);

    ec += mmcsd_write_data(stream->Entry_Addr + 0x14, 2, (int16*)&first_cluster + 1);ec += mmcsd_write_data(stream->Entry_Addr + 0x1A, 2, &first_cluster);

    if(ec != GOODEC){stream->Flags |= Write_Error;return EOF;}}

    // dump the remaining buffer to the cardif(fatflush(stream) == EOF)return EOF;}// nullify the datastream->Cur_Char = 0;stream->Entry_Addr = 0;stream->Size = 0;stream->Start_Addr = 0;stream->Flags = 0;return 0;}

    /*signed int fatgetc(FILE* stream)Summary: Gets a character from a stream.Param: The stream to get a character from.Returns: The character that was gotten from the stream,

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    37 of 54 3/17/2015 3:49 PM

  • EOF if the stream has reached the end of the file or doesn't have permissions to read,*/signed int fatgetc(FILE* stream){char ch; // character read in

    // check to see if the stream has proper permissions to readif(stream->Flags & Read){// when the number of bytes until eof hit zero, we know we are at the end of any fileif(stream->Bytes_Until_EOF == 0){stream->Flags |= EOF_Reached;return EOF;}

    // read in the next byte in the bufferif(read_buffer(stream, &ch) == EOF)return EOF;

    // a 0x00 will signify the end of a non-binary fileif((ch == '\0') && !(stream->Flags & Binary)){stream->Flags |= EOF_Reached;return EOF;}

    // get the next contiguous address of the streamif(get_next_addr(&(stream->Cur_Char)) != GOODEC)return EOF;

    // we just got 1 byte closer to the end of the filestream->Bytes_Until_EOF -= 1;return ch;}

    // if the stream doesn't have proper permissions to read, return an EOFelsereturn EOF;}

    /*signed int fatputc(int ch, FILE* stream)Summary: Puts a character into a stream.Param ch: The character to put into the stream.Param stream: The stream to put a character into.Returns: The character that was put into the stream,EOF if the stream doesn't have permissions to write, or if a problem happened.*/signed int fatputc(int ch, FILE* stream){// check to see if the stream has proper permissions to writeif(((stream->Flags & Write) || (stream->Flags & Append)) && (stream->File_Type == Data_File)){ //printf("\r\n Cur_Char = %lX ; Data_Start : %lX",stream->Cur_Char, Data_Start);// if there isn't any space allocated yet, allocate someif(stream->Cur_Char < Data_Start){ // printf("\r\n Get new cluster : ");// printf("\r\n next free cluster = %X\r\n",Next_Free_Clust);

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    38 of 54 3/17/2015 3:49 PM

  • if(get_next_free_cluster(&Next_Free_Clust) == EOF)return EOF;// printf("Next_Free_Clust %X",Next_Free_Clust);

    #ifdef FAT32if(write_fat(Next_Free_Clust, 0x0FFFFFFF) == EOF)return EOF;#else // FAT16if(write_fat(Next_Free_Clust, 0xFFFF) == EOF)return EOF;#endif // #ifdef FAT32if(clear_cluster(Next_Free_Clust) == EOF)return EOF;stream->Cur_Char = stream->Start_Addr = cluster_to_addr(Next_Free_Clust);}

    // write the next character to the bufferif(write_buffer(stream, ch) == EOF)return EOF;

    // get the next address, increment Cur_Charif(get_next_addr(&(stream->Cur_Char)) == EOF){// write the current buffer to the end of the current clusterif(mmcsd_write_data(stream->Cur_Char - STREAM_BUF_SIZE + 1, STREAM_BUF_SIZE, stream->Buf)!= GOODEC){stream->Flags |= Write_Error;return EOF;}// start looking for a new cluster to allocateif(alloc_clusters(addr_to_cluster(stream->Cur_Char), &(stream->Cur_Char)) == EOF)return EOF;}

    // our file just got bigger by 1 bytestream->Size += 1;

    return ch;}

    // if the stream doesn't have proper permissions to write, return an EOFelsereturn EOF;}

    /*char* fatgets(char* str, int num, FILE* stream)Summary: Reads characters from a stream into a string.Param str: A pointer to the beginning of the string to put characters into.Param num: The number of characters to put into the string - 1.Param stream: The stream to read from.Returns: A pointer to the most recently added character, or NULL if there was an error.Note: If a newline is read from the stream, then str will be terminated with a newline.If num - 1 or EOF is reached, then str will be null terminated.*/char* fatgets(char* str, int num, FILE* stream){int i; // counter for loops

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    39 of 54 3/17/2015 3:49 PM

  • // loop until num - 1for(i = 0; i < num - 1; i += 1){str[i] = fatgetc(stream);if(str[i] == '\n')return str;if(str[i] == EOF)break;}

    // close off str with a null terminatorstr[i] = '\0';

    return str;}

    /*signed int fatputs(char* str, FILE* stream)Summary: Writes characters from a string into a stream.Param str: A pointer to the beginning of the string to write into the stream.Param stream: The stream to write into.Returns: EOF if there was a problem, GOODEC if everything went okay.*/signed int fatputs(char* str, FILE* stream){int i = 0; // counter for loops

    // fatputc every character in the streamwhile(str[i] != '\0'){if(fatputc(str[i], stream) == EOF)return EOF;i += 1;// printf("fatputs : %c : %X \r\n", str[i],str[i]);}

    return GOODEC;}

    /*signed int fatprintf(FILE* stream)Summary: This will print off the entire contents of the stream to the console.Param: The stream to print off.Returns: The last character printed off to the console.*/signed int fatprintf(FILE* stream){signed int ch; // character read in

    // keep on printf any characters read in as long as we don't run into an end of file or a media errordo{ch = fatgetc(stream);printf("%c", ch);} while(ch != EOF);

    return ch;}

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    40 of 54 3/17/2015 3:49 PM

  • /*signed int fatgetpos(FILE* stream, fatpos_t* position)Summary: Returns the current position of where the stream is pointing to relative to the beginning ofthe stream.Param stream: The stream to get the position of.Param position: A pointer to a variable put the current position of the pointer into.Returns: 0 on success.*/signed int fatgetpos(FILE* stream, fatpos_t* position){*position = stream->Size - stream->Bytes_Until_EOF;return 0;}

    /*signed int fatsetpos(FILE* stream, fatpos_t* position)Summary: Sets the current position of where the stream is pointing to in memory relative to thebeginning of the stream.Param stream: The stream to set the position of.Param position: A pointer the a variable that has the value of the new position.Returns: 0 on success, or EOF if there was error.*/signed int fatsetpos(FILE* stream, fatpos_t* position){#ifndef FAST_FAT#ifdef FAT32int32 cur_cluster; // the current cluster we're pointing to#else // FAT16int16 cur_cluster; // the current cluster we're pointing to#endif // #ifdef FAT32int32 i; // pointer to memory#endif // #ifndef FAST_FAT

    // check to see if we want to just rewind the fileif(*position == 0){rewind(stream);return GOODEC;}

    // this whole process is much different and easier if we're writing or appending at a spot after EOF// this will essentially write null characters to the file from EOF to the desired positionif(((stream->Flags & Write) || (stream->Flags & Append)) && (stream->Size < *position)){while(stream->Size < *position)if(fatputc('\0', stream) == EOF)return EOF;

    return 0;}

    #ifdef FAST_FATstream->Cur_Char = stream->Start_Addr + *position;#else // NO FAST_FAT// figure out how many clusters into the file the position is to be set toi = *position / Bytes_Per_Cluster;cur_cluster = addr_to_cluster(stream->Start_Addr);

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    41 of 54 3/17/2015 3:49 PM

  • // head to that clusterwhile(i > 0){if(get_next_cluster(&cur_cluster) != GOODEC)return EOF;i -= 1;}

    // head to the correct clusterstream->Cur_Char = cluster_to_addr(cur_cluster);

    // now that we're in the correct cluster, tack on the remaining positionstream->Cur_Char += (*position % Bytes_Per_Cluster);

    if(stream->Flags & Read){// we now need to change how far it is until EOFstream->Bytes_Until_EOF = stream->Size - *position;

    // fill up the bufferif(mmcsd_read_data(stream->Cur_Char, STREAM_BUF_SIZE, stream->Buf) != GOODEC){stream->Flags |= Read_Error;return EOF;}}

    elsestream->Size = *position;#endif // #ifdef FAST_FATreturn 0;}

    /*signed int fatseek(FILE* stream, int32 offset, int origin)Summary: This will set the position of the file stream according to the input. The EOF flag will also becleared.Param stream: The stream to set the position of.Param offset: How many bytes relative of origin the file stream position will be set.Param origin: This will be one of 3 values...SEEK_CUR: Set position relative to the current stream position.SEEK_END: Set position relative to the end of the stream.SEEK_SET: Set position relative to the beginning of the stream.Returns: 0 on success, or EOF if there was error.*/signed int fatseek(FILE* stream, int32 offset, int origin){int32 myoffset; // since fatsetpos requires a pointer to a variable, we need this here

    switch(origin){case SEEK_CUR:myoffset = stream->Cur_Char + offset;if(fatsetpos(stream, &myoffset) != 0)return EOF;break;case SEEK_END:myoffset = stream->Size - offset;if(fatsetpos(stream, &myoffset) != 0)

    CCS :: View topic - CCS FAT driver bugfix! http://www.ccsinfo.com/forum/viewtopic.php?t=43417

    42 of 54 3/17/2015 3:49 PM

  • return EOF;break;case SEEK_SET:myoffset = offset;if(fatsetpos(stream, &myoffset) != 0)return EOF;break;default:return EOF;}

    // clear the EOF flagstream->Flags &= 0xEF;

    return GOODEC;}

    /*signed int fateof(FILE* stream)Summary: Determines whether or not the stream is at