This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1310: FatFS ff.h undefined symbol f_open

Part Number: CC1310

Hello,

I am trying to open a TXT file on my SD card using the FatFS libraries.

I have included all of the needed files in my code for a simple f_open operation where i create a TXT file on my SD card. However, it says it can not find f_open (see image below).

This makes no sense to me. I have included the files in my code and when i ctr+click on the #include line it opens the ff.h library perfectly fine, which is where it defines the f_open function.

I have included my code below. The lines relevant for this issue are line 30-32 and line 205.

Why am I getting this error?

Kind regards,

Mirte H

/***** Includes *****/
/* Standard C Libraries */
#include <stdlib.h>
#include<stdio.h>
#include<string.h>
#include <math.h>
/* TI Drivers */
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <ti/display/Display.h>


/* Driverlib Header files */
#include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)

/* Board Header files */
#include "Board.h"

/* Application Header files */
#include "RFQueue.h"
#include "smartrf_settings/smartrf_settings.h"

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/drivers/UART.h>

#include <third_party/fatfs/ff.h>
#include <third_party/fatfs/diskio.h>
#include <file.h>
/* Custom header files */

#include <CRC8.h>
#include <Manchester.h>

/***** Defines *****/

/* Packet RX Configuration */
#define DATA_ENTRY_HEADER_SIZE 9  /* Constant header size of a Generic Data Entry */
#define MAX_LENGTH             19 /* Max length byte the radio will accept */
#define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
#define NUM_APPENDED_BYTES     2  /* The Data Entries data field will contain:
                                   * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
                                   * Max 30 payload bytes
                                   * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */



/***** Prototypes *****/
static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);

/***** Variable declarations *****/
static RF_Object rfObject;
static RF_Handle rfHandle;

/* Pin driver handle */
static PIN_Handle ledPinHandle;
static PIN_State ledPinState;

/* Buffer which contains all Data Entries for receiving data.
 * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (rxDataEntryBuffer, 4);
static uint8_t
rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                  MAX_LENGTH,
                                                  NUM_APPENDED_BYTES)];
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
static uint8_t
rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                  MAX_LENGTH,
                                                  NUM_APPENDED_BYTES)];
#elif defined(__GNUC__)
static uint8_t
rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                  MAX_LENGTH,
                                                  NUM_APPENDED_BYTES)]
                                                  __attribute__((aligned(4)));
#else
#error This compiler is not supported.
#endif

/* Receive dataQueue for RF Core to fill in data */
static dataQueue_t dataQueue;
static rfc_dataEntryGeneral_t* currentDataEntry;
static uint8_t packetLength;
static uint8_t* packetDataPointer;







static uint8_t packet[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */




/* Custom raw and decoded payloads */
uint8_t payload[19];
uint8_t decoded[MAX_LENGTH];
/* RX Semaphore */
static Semaphore_Struct rxSemaphore;
static Semaphore_Handle rxSemaphoreHandle;

float twodecround(float var);
float twodecround(float var){
    var = (var*100);
    int value = round(var);
    var = value;
    var /= 100;

//TODO: ROUND TO TWO DECIMALS
    return var;


}



/*
 * Application LED pin configuration table:
 *   - All LEDs board LEDs are off.
 */
PIN_Config pinTable[] =
{
 Board_PIN_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

/***** Function definitions *****/

void *mainThread(void *arg0)
{
    RF_Params rfParams;
    RF_Params_init(&rfParams);

    /* Initialize RX semaphore */
    Semaphore_construct(&rxSemaphore, 0, NULL);
    rxSemaphoreHandle = Semaphore_handle(&rxSemaphore);



    Display_Params params;
      Display_Params_init(&params);
      params.lineClearMode = DISPLAY_CLEAR_BOTH;
      Display_Handle uartDisplayHandle = Display_open(Display_Type_UART, &params);


    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, pinTable);
    if (ledPinHandle == NULL)
    {
        while(1);
    }

    if( RFQueue_defineQueue(&dataQueue,
                            rxDataEntryBuffer,
                            sizeof(rxDataEntryBuffer),
                            NUM_DATA_ENTRIES,
                            MAX_LENGTH + NUM_APPENDED_BYTES))
    {
        /* Failed to allocate space for all data entries */
        while(1);
    }

    /* Modify CMD_PROP_RX command for application needs */

    /* Set the Data Entity queue for received data */
    RF_cmdPropRx.pQueue = &dataQueue;
    /* Discard ignored packets from Rx queue */
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
    /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
    RF_cmdPropRx.maxPktLen = MAX_LENGTH;
    RF_cmdPropRx.pktConf.bRepeatOk = 1;
    RF_cmdPropRx.pktConf.bRepeatNok = 1;

    /* Request access to the radio */
#if defined(DeviceFamily_CC26X0R2)
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioSetup, &rfParams);
#else
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
#endif// DeviceFamily_CC26X0R2

    /* Set the frequency */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);

    /* Enter RX mode and stay forever in RX */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);





    while(1)
    {
        FIL fil;        /* File object */
        char line[100]; /* Line buffer */
        FRESULT fr;     /* FatFs return code */

        fr = f_open(&fil, "message.txt", FA_CREATE_NEW | FA_WRITE);

        Semaphore_pend(rxSemaphoreHandle, BIOS_WAIT_FOREVER);

        uint8_t CRC_OK_NOK = 0;
        float DataCalc = 0;
        float degC = 0;
        float hum = 0;
        float vbat = 0;

        uint8_t LENGTH =0;
        uint8_t ID0=0;
        uint8_t ID1=0;
        uint8_t ID2=0;
        uint32_t ID_FULL = 0;
        uint8_t TYPE=0;
        uint8_t DATA0=0;
        uint8_t DATA1=0;
        uint16_t DATA_FULL = 0;
        uint8_t CRC=0;
        uint8_t nCRC=0;
        uint32_t temp_id = 0;
        uint16_t temp_id5 = 0;



        int c = 0;

        for (c = 0; c < 19; c++)
        {
              payload[c] = manDecode(packet[c]);

        }

        LENGTH |= payload[0];
        LENGTH <<= 4;
        LENGTH |= payload[1];




       if(LENGTH == 5){

                    ID0 |= payload[4];
                    ID0 <<= 4;
                    ID0 |= payload[5];

                    ID1 |= payload[2];
                    ID1 <<= 4;
                    ID1 |= payload[3];

                    DATA0 |= payload[6];
                    DATA0 <<= 4;
                    DATA0 |= payload[7];

                    DATA1 |= payload[8];
                    DATA1 <<= 4;
                    DATA1 |= payload[9];


                    CRC |= payload[10];
                    CRC <<= 4;
                    CRC |= payload[11];

                    CRC_OK_NOK = doCrc(LENGTH, ID0, ID1, 0, 0, DATA0, DATA1, CRC, 0);

                    DATA_FULL |= DATA0;
                    DATA_FULL <<=8;
                    DATA_FULL |= DATA1;
                    DataCalc = DATA_FULL;

                    ID_FULL |= ID0;
                    ID_FULL <<=8;
                    ID_FULL |= ID1;

                    if(CRC_OK_NOK == 1)
                    {
                    DataCalc /= 100;
                    DataCalc *=0.78125;

                    // IF LAATSTE BIT ID 1 IS DAN IS HET TEMP
                    temp_id5 = ID_FULL;
                    temp_id5 <<= 15;
                    temp_id5 >>= 15;
                    if(temp_id5 == 1)
                    {
                    degC = twodecround(DataCalc);
                    }
                    else
                    {
                        hum = twodecround(DataCalc);
                    }

               }

       }
           if(LENGTH == 7)
           {

                    ID0 |= payload[6];
                    ID0 <<= 4;
                    ID0 |= payload[7];

                    ID1 |= payload[4];
                    ID1 <<= 4;
                    ID1 |= payload[5];

                    ID2 |= payload[2];
                    ID2 <<= 4;
                    ID2 |= payload[3];

                    TYPE |= payload[8];
                    TYPE <<= 4;
                    TYPE |= payload[9];

                    DATA0 |= payload[10];
                    DATA0 <<= 4;
                    DATA0 |= payload[11];

                    DATA1 |= payload[12];
                    DATA1 <<= 4;
                    DATA1 |= payload[13];

                    CRC |= payload[14];
                    CRC <<= 4;
                    CRC |= payload[15];

                    nCRC |= payload[16];
                    nCRC <<= 4;
                    nCRC |= payload[17];

                   CRC_OK_NOK = doCrc(LENGTH, ID0, ID1, ID2, TYPE, DATA0, DATA1, CRC, nCRC);

                    DATA_FULL |= DATA0;
                    DATA_FULL <<=8;
                    DATA_FULL |= DATA1;

                    ID_FULL |= ID0;
                    ID_FULL <<=8;
                    ID_FULL |= ID1;
                    ID_FULL <<=8;
                    ID_FULL |= ID2;


                    if(CRC_OK_NOK == 1)
                    {
                    switch (TYPE)
                    {
                          case 32: //20, CHECKED: TC77 OR MCP9808
                                DATA_FULL <<= 3;
                                degC = DATA_FULL;
                                degC /= 100;
                                degC *= 0.09765625;
                                degC = twodecround(degC);
                                break;

                          case 0x48: //30, NOT CHECKED: T6613
                                // not used
                                break;
                          case 64: //40, CHECKED: SHT10



                              temp_id = 0;
                              temp_id = ID_FULL;
                              temp_id <<= 31;
                              temp_id >>= 31;

                              // IF LAATSTE BIT ID 1 IS DAN IS HET HUM
                              if(temp_id == 1)
                              {
                                  //IF HUM:
                                  float tempHum = DATA_FULL * DATA_FULL;
                                  tempHum *=1.5955E-6;
                                  hum = DATA_FULL;
                                  hum *= 0.0367;
                                  hum -= 2.0468;
                                  hum -= tempHum;
                                  hum = twodecround(hum);
                              }
                              else{
                                degC = DATA_FULL;
                                degC *= 0.01;
                                degC -= 39.6;
                                degC = twodecround(degC);
                              }

                                break;

                          case 80: //50, NOT CHECKED
                                //HDS1080

//                                //IF HUM:
//                                hum = DATA;
//                                hum *= 0.152587890625;
//
//                                // IF TEMP:
//                                degC = DATA;
//                                degC *= 0.25177001953125;
//                                degC -= 4000;

                                break;

                          case 224:  //E0 CHECKED: temp pt100

                                degC = DATA_FULL;
                                degC /= 100;
                                degC *= 0.390625;
                                degC = twodecround(degC);

                                break;

                          case 240: //F0, CHECKED bat volt

                                vbat = 2097.152;
                                vbat /= DATA_FULL;
                                vbat = twodecround(vbat);
                                break;

                          default:
                                // UNKNOWN
                                DataCalc = 69420;

                                break;

                    }
               }



        }






 }
}









void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
    if (e & RF_EventRxEntryDone)
    {
        /* Toggle pin to indicate RX */
        PIN_setOutputValue(Board_PIN_RLED, CC1310_LAUNCHXL_PIN_RLED  ,
                           !PIN_getOutputValue(Board_PIN_RLED ));

        /* Get current unhandled data entry */
        currentDataEntry = RFQueue_getDataEntry();

        /* Handle the packet data, located at &currentDataEntry->data:
         * - Length is the first byte with the current configuration
         * - Data starts from the second byte */
        packetLength      = 19;
        packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);

        /* Copy the payload + the status byte to the packet variable */
        memcpy(packet, packetDataPointer, (packetLength + 1));

        RFQueue_nextEntry();

        Semaphore_post(rxSemaphoreHandle);
    }
}

  • Hi Mirte,

    Please can you right click on the project and go to project properties. 

    In the project properties window, under Build > Arm Linker, You can find the File search path.  You could add the path to the specific library you are using here. 

    Regards,

    Sid

  • Hi Sid,

    Thank you for your quick response. I did try that a few times before and it didn't work so I removed all of them. 

    I tried it again just now and it still doesnt work. Here is what I added:

    Kind regards,

    Mirte H

  • Hi Mirte, 

    Can you try including this header file.

    #include <third_party/fatfs/ffcio.h>

    Regards,

    Sid

  • HI Sid,

    I added it but i still get the same error. When i change f_open to fccio_open i also get the same error but with fccio_open.

    Kind regards,

    Mirte H

  • Hi Mirte, 

    Include the path, in the "Include library file or command file as input tab"

    C:\ti\simplelink_cc13x0_sdk_4_20_01_03\source\third_party\fatfs\lib\ccs\m3\fatfs.a

    After adding this file, it seems to still expect a user defined fatfs_getFatTime() function, 

    So I added a dummy implementation of this by adding the following lines of code in the application code. 

    int32_t fatfs_getFatTime(void)
    {
        return 0;
    }

    Unless you use fatfs_getFatTime() this should be okay. 

    Regards,

    Sid

  • Good morning Sid,

    This solved my issue! I have no more errors. I even added a few random functions (f_write, f_close) to be sure and it still works.

    It still feels weird that i have to do this much and even add a dummy to make this library usable. do you have any idea why it acts this way? (Just out of curiosity.)

    Thanks a lot! Grinning

    Kind regards,

    Mirte H

  • Hello Sid,

    I am in the middle of implementing FatFS but i've come across another issue. I don't know how familiar you are with FatFS but I figured there would be no harm in sharing. The link is below.

    ://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1100116/cc1310-fatfs-f_open-always-returning-fr_write_protected

    Thanks again!

    Mirte H

  • Hi Mirte, 

    I joined your threads because my earlier suggested fix, maybe an issue.  

    I see that in the simplelink_cc13xx_cc26xx_sdk, there is a fatsd example.

    In that there is an actual implementation for the fatfs_getFatTime() function. 

    #include <time.h>
    /*
     *  ======== fatfs_getFatTime ========
     */
    int32_t fatfs_getFatTime(void)
    {
        time_t seconds;
        uint32_t fatTime;
        struct tm *pTime;
    
        /*
         *  TI time() returns seconds elapsed since 1900, while other tools
         *  return seconds from 1970.  However, both TI and GNU localtime()
         *  sets tm tm_year to number of years since 1900.
         */
        seconds = time(NULL);
    
        pTime = localtime(&seconds);
    
        /*
         *  localtime() sets pTime->tm_year to number of years
         *  since 1900, so subtract 80 from tm_year to get FAT time
         *  offset from 1980.
         */
        fatTime = ((uint32_t)(pTime->tm_year - 80) << 25) |
            ((uint32_t)(pTime->tm_mon) << 21) |
            ((uint32_t)(pTime->tm_mday) << 16) |
            ((uint32_t)(pTime->tm_hour) << 11) |
            ((uint32_t)(pTime->tm_min) << 5) |
            ((uint32_t)(pTime->tm_sec) >> 1);
    
        return ((int32_t)fatTime);
    }

    This may fix the issue, even if it does not. It is worth adding. 

    Regards,

    Sid

  • Part Number: CC1310

    Hello,

    I am trying to open my SD card, create a TXT file on it and close it. However, f_open always returns FR_WRITE_PROTECTED.

    This is weird since FF_FS_READONLY is defined as 0, which means read/write is enabled. I am using a MicroSD card and it's freshly formatted and I'm 100% sure it is NOT write protected. 

    This is my first time using FatFS, i am using snippets of code provided by the FatFS documentation. I've been looking online for an hour but I can't find the answer anywhere.

    What am I doing wrong?

    My code is below. The relevent lines of code are lines 220-230

     // My values: 85 = (0)1010101   IS 0 = 00000000
            //106 = (0)1101010 IS 7 = (0)111
            // 102 = 01100110 IS 5 = 0101
            //01 = 0   10 = 1
    
    
    //5 Message sensor:
    //AA AA AA AA 55 05 DC 2F 00 00 0A
    //9999 9999 9999 9999 66  66 = NOT RECEIVED
    //55 66 A6 A5 59 AA 55 55 55 55 55 99
    //
    //
    
    //7 Message sensor:
    //AA AA AA AA 55 07 16 05 03 40 00 00 31 CE
    //9999 9999 9999 9999 66  66
    //55 6A 56 69 55 66 55 5A 65 55 55 55 55 55 5A 56 A5 A9
    
    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    #include<stdio.h>
    #include<string.h>
    #include <math.h>
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/display/Display.h>
    
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /* Board Header files */
    #include "Board.h"
    
    /* Application Header files */
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/drivers/UART.h>
    
    #include <third_party/fatfs/ff.h>
    #include <third_party/fatfs/diskio.h>
    #include <third_party/fatfs/ffcio.h>
    #include <third_party/fatfs/ffconf.h>
    #include <file.h>
    /* Custom header files */
    
    int32_t fatfs_getFatTime(void){
        return 0;
    }
    
    #include <CRC8.h>
    #include <Manchester.h>
    
    /***** Defines *****/
    
    /* Packet RX Configuration */
    #define DATA_ENTRY_HEADER_SIZE 9  /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH             19 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     2  /* The Data Entries data field will contain:
                                       * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
                                       * Max 30 payload bytes
                                       * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */
    
    
    
    /***** Prototypes *****/
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)]
                                                      __attribute__((aligned(4)));
    #else
    #error This compiler is not supported.
    #endif
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t packetLength;
    static uint8_t* packetDataPointer;
    
    
    
    
    
    
    
    static uint8_t packet[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
    
    
    
    
    /* Custom raw and decoded payloads */
    uint8_t payload[19];
    uint8_t decoded[MAX_LENGTH];
    /* RX Semaphore */
    static Semaphore_Struct rxSemaphore;
    static Semaphore_Handle rxSemaphoreHandle;
    
    float twodecround(float var);
    float twodecround(float var){
        var = (var*100);
        int value = round(var);
        var = value;
        var /= 100;
    
    //TODO: ROUND TO TWO DECIMALS
        return var;
    
    
    }
    
    
    
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config pinTable[] =
    {
     Board_PIN_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        /* Initialize RX semaphore */
        Semaphore_construct(&rxSemaphore, 0, NULL);
        rxSemaphoreHandle = Semaphore_handle(&rxSemaphore);
    
    
    
        Display_Params params;
          Display_Params_init(&params);
          params.lineClearMode = DISPLAY_CLEAR_BOTH;
          Display_Handle uartDisplayHandle = Display_open(Display_Type_UART, &params);
    
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, pinTable);
        if (ledPinHandle == NULL)
        {
            while(1);
        }
    
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
    
        /* Modify CMD_PROP_RX command for application needs */
    
        /* Set the Data Entity queue for received data */
        RF_cmdPropRx.pQueue = &dataQueue;
        /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;
        RF_cmdPropRx.pktConf.bRepeatOk = 1;
        RF_cmdPropRx.pktConf.bRepeatNok = 1;
    
        /* Request access to the radio */
    #if defined(DeviceFamily_CC26X0R2)
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioSetup, &rfParams);
    #else
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    #endif// DeviceFamily_CC26X0R2
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        /* Enter RX mode and stay forever in RX */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
    
        FATFS *fs;
        FIL fil;        /* File object */
        FRESULT fr;     /* FatFs return code */
    
            fs = malloc(sizeof (FATFS));
            fr = f_mount(fs, "", 0);
    
            fr = f_open(&fil, "message.txt", FA_WRITE | FA_CREATE_NEW );
    
           // fr = f_write(&fil, 0, 20, 0);
            fr = f_close(&fil);
    
    
        while(1)
        {
    
            Semaphore_pend(rxSemaphoreHandle, BIOS_WAIT_FOREVER);
    
    
    
    
    
    
            uint8_t CRC_OK_NOK = 0;
            float DataCalc = 0;
            float degC = 0;
            float hum = 0;
            float vbat = 0;
    
            uint8_t LENGTH =0;
            uint8_t ID0=0;
            uint8_t ID1=0;
            uint8_t ID2=0;
            uint32_t ID_FULL = 0;
            uint8_t TYPE=0;
            uint8_t DATA0=0;
            uint8_t DATA1=0;
            uint16_t DATA_FULL = 0;
            uint8_t CRC=0;
            uint8_t nCRC=0;
            uint32_t temp_id = 0;
            uint16_t temp_id5 = 0;
    
    
    
            int c = 0;
    
            for (c = 0; c < 19; c++)
            {
                  payload[c] = manDecode(packet[c]);
    
            }
    
            LENGTH |= payload[0];
            LENGTH <<= 4;
            LENGTH |= payload[1];
    
    
    
    
           if(LENGTH == 5){
    
                        ID0 |= payload[4];
                        ID0 <<= 4;
                        ID0 |= payload[5];
    
                        ID1 |= payload[2];
                        ID1 <<= 4;
                        ID1 |= payload[3];
    
                        DATA0 |= payload[6];
                        DATA0 <<= 4;
                        DATA0 |= payload[7];
    
                        DATA1 |= payload[8];
                        DATA1 <<= 4;
                        DATA1 |= payload[9];
    
    
                        CRC |= payload[10];
                        CRC <<= 4;
                        CRC |= payload[11];
    
                        CRC_OK_NOK = doCrc(LENGTH, ID0, ID1, 0, 0, DATA0, DATA1, CRC, 0);
    
                        DATA_FULL |= DATA0;
                        DATA_FULL <<=8;
                        DATA_FULL |= DATA1;
                        DataCalc = DATA_FULL;
    
                        ID_FULL |= ID0;
                        ID_FULL <<=8;
                        ID_FULL |= ID1;
    
                        if(CRC_OK_NOK == 1)
                        {
                        DataCalc /= 100;
                        DataCalc *=0.78125;
    
                        // IF LAATSTE BIT ID 1 IS DAN IS HET TEMP
                        temp_id5 = ID_FULL;
                        temp_id5 <<= 15;
                        temp_id5 >>= 15;
                        if(temp_id5 == 1)
                        {
                        degC = twodecround(DataCalc);
                        }
                        else
                        {
                            hum = twodecround(DataCalc);
                        }
    
                   }
    
           }
               if(LENGTH == 7)
               {
    
                        ID0 |= payload[6];
                        ID0 <<= 4;
                        ID0 |= payload[7];
    
                        ID1 |= payload[4];
                        ID1 <<= 4;
                        ID1 |= payload[5];
    
                        ID2 |= payload[2];
                        ID2 <<= 4;
                        ID2 |= payload[3];
    
                        TYPE |= payload[8];
                        TYPE <<= 4;
                        TYPE |= payload[9];
    
                        DATA0 |= payload[10];
                        DATA0 <<= 4;
                        DATA0 |= payload[11];
    
                        DATA1 |= payload[12];
                        DATA1 <<= 4;
                        DATA1 |= payload[13];
    
                        CRC |= payload[14];
                        CRC <<= 4;
                        CRC |= payload[15];
    
                        nCRC |= payload[16];
                        nCRC <<= 4;
                        nCRC |= payload[17];
    
                       CRC_OK_NOK = doCrc(LENGTH, ID0, ID1, ID2, TYPE, DATA0, DATA1, CRC, nCRC);
    
                        DATA_FULL |= DATA0;
                        DATA_FULL <<=8;
                        DATA_FULL |= DATA1;
    
                        ID_FULL |= ID0;
                        ID_FULL <<=8;
                        ID_FULL |= ID1;
                        ID_FULL <<=8;
                        ID_FULL |= ID2;
    
    
                        if(CRC_OK_NOK == 1)
                        {
                        switch (TYPE)
                        {
                              case 32: //20, CHECKED: TC77 OR MCP9808
                                    DATA_FULL <<= 3;
                                    degC = DATA_FULL;
                                    degC /= 100;
                                    degC *= 0.09765625;
                                    degC = twodecround(degC);
                                    break;
    
                              case 0x48: //30, NOT CHECKED: T6613
                                    // not used
                                    break;
                              case 64: //40, CHECKED: SHT10
    
    
    
                                  temp_id = 0;
                                  temp_id = ID_FULL;
                                  temp_id <<= 31;
                                  temp_id >>= 31;
    
                                  // IF LAATSTE BIT ID 1 IS DAN IS HET HUM
                                  if(temp_id == 1)
                                  {
                                      //IF HUM:
                                      float tempHum = DATA_FULL * DATA_FULL;
                                      tempHum *=1.5955E-6;
                                      hum = DATA_FULL;
                                      hum *= 0.0367;
                                      hum -= 2.0468;
                                      hum -= tempHum;
                                      hum = twodecround(hum);
                                  }
                                  else{
                                    degC = DATA_FULL;
                                    degC *= 0.01;
                                    degC -= 39.6;
                                    degC = twodecround(degC);
                                  }
    
                                    break;
    
                              case 80: //50, NOT CHECKED
                                    //HDS1080
    
    //                                //IF HUM:
    //                                hum = DATA;
    //                                hum *= 0.152587890625;
    //
    //                                // IF TEMP:
    //                                degC = DATA;
    //                                degC *= 0.25177001953125;
    //                                degC -= 4000;
    
                                    break;
    
                              case 224:  //E0 CHECKED: temp pt100
    
                                    degC = DATA_FULL;
                                    degC /= 100;
                                    degC *= 0.390625;
                                    degC = twodecround(degC);
    
                                    break;
    
                              case 240: //F0, CHECKED bat volt
    
                                    vbat = 2097.152;
                                    vbat /= DATA_FULL;
                                    vbat = twodecround(vbat);
                                    break;
    
                              default:
                                    // UNKNOWN
                                    DataCalc = 69420;
    
                                    break;
    
                        }
                   }
    
    
    
            }
    
    
    
    
    
    
     }
    }
    
    
    
    
    
    
    
    
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            /* Toggle pin to indicate RX */
            PIN_setOutputValue(Board_PIN_RLED, CC1310_LAUNCHXL_PIN_RLED  ,
                               !PIN_getOutputValue(Board_PIN_RLED ));
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &currentDataEntry->data:
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte */
            packetLength      = 19;
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet, packetDataPointer, (packetLength + 1));
    
            RFQueue_nextEntry();
    
            Semaphore_post(rxSemaphoreHandle);
        }
    }
    

    Kind regards,

    Mirte H

  • Hi Mirte, I am joining these threads because it is possible that they are related. 

    Please look into my previous reply about fatfs_getFatTime(). 

  • Hello Sid,

    I added your suggested fix but it didn't solve the problem, I am still getting FR_WRITE_PROTECTED from F_open, that's why I made it a seperate thread.

    Do you know what the issue could be or should I make a new thread? Because the issue from this thread has been solved.

    Kind regards,

    Mirte H

  • Part Number: CC1310

    Hello everybody,

    I have been struggling with the FatFS library for a few days now. All I want to do is use SPI to write a TXT file to my SD card.

    As you can see in the linked thread I have been struggling with the f_open function. It always returns FR_WRITE_PROTECTED, even when there is no SD card present. I think this means the communication using SPI is going wrong.

    I can use the sdraw example, it initializes the SD_card fine and can actually read the data size etc. so I know it is possible. (It does get stuck when It writes and tries to read what It wrote, but I figure that is because writing corrupts the SD card.)

    I tried combining the sdraw example with FatFS but i still get the FR_WRITE_PROTECTED error.

    Here is the code I tried where i combined rawsd and FatFS:

    /*
     * Copyright (c) 2016-2019, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== sdraw.c ========
     */
    #include <stddef.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/SD.h>
    #include <ti/display/Display.h>
    #include <third_party/fatfs/ff.h>
    #include <third_party/fatfs/diskio.h>
    #include <third_party/fatfs/ffcio.h>
    #include <third_party/fatfs/ffconf.h>
    /* Example/Board Header files */
    #include "Board.h"
    int32_t fatfs_getFatTime(void){
        time_t seconds;
            uint32_t fatTime;
            struct tm *pTime;
    
            /*
             *  TI time() returns seconds elapsed since 1900, while other tools
             *  return seconds from 1970.  However, both TI and GNU localtime()
             *  sets tm tm_year to number of years since 1900.
             */
            seconds = time(NULL);
    
            pTime = localtime(&seconds);
    
            /*
             *  localtime() sets pTime->tm_year to number of years
             *  since 1900, so subtract 80 from tm_year to get FAT time
             *  offset from 1980.
             */
            fatTime = ((uint32_t)(pTime->tm_year - 80) << 25) |
                ((uint32_t)(pTime->tm_mon) << 21) |
                ((uint32_t)(pTime->tm_mday) << 16) |
                ((uint32_t)(pTime->tm_hour) << 11) |
                ((uint32_t)(pTime->tm_min) << 5) |
                ((uint32_t)(pTime->tm_sec) >> 1);
    
            return ((int32_t)fatTime);
    }
    /* Buffer size used for the file copy process */
    #define BUFFSIZE 1024
    
     /* Starting sector to write/read to */
    #define STARTINGSECTOR 0
    
    #define BYTESPERKILOBYTE 1024
    
    /*
     * Set this constant to 1 in order to write to the SD card.
     * WARNING: Running this example with WRITEENABLE set to 1 will cause
     * any filesystem present on the SD card to be corrupted!
     */
    #define WRITEENABLE 1
    
    static Display_Handle display;
    
    unsigned char textarray[BUFFSIZE];
    
    unsigned char cpy_buff[BUFFSIZE];
    
    /*
     *  ======== mainThread ========
     *  Task to perform a raw write and read from the SD card.
     *  Note: Running this application will cause any filesystem on the
     *      SD card to become corrupted!
     */
    void *mainThread(void *arg0)
    {
        FRESULT fresult;
        int_fast8_t   result;
        FATFS *fs;
    
        SD_Handle     sdHandle;
        FIL fil;        /* File object */
    
        Display_init();
        GPIO_init();
        SD_init();
    
    
        /* Open the display for output */
        display = Display_open(Display_Type_UART, NULL);
        if (display == NULL) {
            /* Failed to open display driver */
            while (1);
        }
    
    
    
    
    
        /* Mount and register the SD Card */
        sdHandle = SD_open(Board_SD0, NULL);
        if (sdHandle == NULL) {
            Display_printf(display, 0, 0, "Error starting the SD card\n");
            while (1);
        }
    
        result = SD_initialize(sdHandle);
        if (result != SD_STATUS_SUCCESS) {
            Display_printf(display, 0, 0, "Error initializing the SD card\n");
            while (1);
        }
    
        fs = malloc(sizeof (FATFS));
        fresult = f_mount(fs, "", 0);
    
        fresult = f_open(&fil, "file.txt",  FA_CREATE_NEW | FA_WRITE );
        SD_close(sdHandle);
    
        return (NULL);
    }
    
       

    I'm getting kind of desperate and annoyed at myself for not being able to figure this out. I really hope someone on here can help me out.

    All I want to do is use the CC1310 defined SPI lines in CC1310_LAUNCHXL.H to write a TXT file to my SD card, how do I do that using either this code or a completely new code? 

    Thanks in advance.

    Kind regards,

    Mirte H 

  • Hi Mirte,

    Regarding your issue I'm afraid we can't look into your code. I would recommend the FATFs documentation which you can find here:

    http://elm-chan.org/fsw/ff/00index_e.html

    Cheers,

    Marie H

  • Hi Marie,

    That's okay, I understand, the issue probably wasn't very TI related but more FatFS Slight smile

    To close this thread on a positive note and maybe help others with the same struggle: I've managed to find a snippet of code that works in this post: https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/799403/rtos-cc2642r-high-current-consumption-following-f_open-call-fatfs/2958511#2958511

    I copied the mainthread and I can finally write a txt file on my SD card! 

    Thanks for your help and time.

    Kind regards,

    Mirte H