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.

Writing to an external SD card in BLE stack w/ CC2540

Other Parts Discussed in Thread: CC2540, CC2541, CC2640, CC2650

Hi, all

I am new to this style of programming within a given protocol, and am unsure how to do things that are unrelated to the protocol. By this, I mean, I need to do basic uC functions like taking information from sensors (will be a piezoelectric, an RF proximity sensor, and accelerometer), some being through an ADC, and then writing them to an external SD card. I have a library for writing to an SD card through Chan (http://www.8051projects.net/mmc-sd-interface-fat16/fat16-library.php) but am very much unsure how to do this with the BLE stack. 

If I understand it correctly, I need to have a profile for each of these sensors as well as the SD card, but I don't need to necessarily share this data through the GATT profile. I don't understand where exactly to start on this profile development if this is the case, but I do have a base level experience with uC's and basic I/O functionality.

To give an insight on the project, I will be taking in information from the sensors using a CC2540, and saving data to an SD card as well as sending it to the phone. Due to time constraint issues, I think the easiest way to do this will be by making the .txt log file and then sending this using an FTP profile that I have found online. 

Any insight or tutorials on this will be helpful, because I still haven't found exactly what I need in the BLE software developer's guide; because most of it is stated assuming I already have some experience with bluetooth.

Thank you very much for your help

Zach

  • Hi,

    First of all, given RF API does not mean (in theory) any restriction to your style of programming. What really matters is (I take it you are aiming at using CC2540 alone, not as RF-only device coupled to separate controller) adapting to OSAL environment and coexistence of user-defined code, IO and radio. 

    I believe that you most certainly don't need separate profiles for sole purpose of accessing your device via bittenfruit devices, as you can pack every piece of sensor data in a single profile description. Keep in mind that to BLE stack "profile" means a rather fat bunch of  variables and code (callbacks invoked when GATT read/write occur). Profile is nothing but an access interface coming with an overhead, and you don't need that overhead with those tiny weaklings of 8051.

    Two basic issues you'll face is:

    a) producing a routine that will read sensors without crippling the radio (a co-existence problem), and

    b) exposing data to smartphone - it seems that you've already found possible solution. I don't know if it is hard to develop iPhone app for a profile with custom set of attributes, so if there is SIG-defined file-access profile, might be good to stick with it. Your call, really/

    BR, 

    Oleg  

  • Thank you for your reply, Oleg

    I think I understand what you are saying. Basically I can use a single new profile with the included 8051 header files to read in my data through an ADC and other inputs and to isolate the relevant input data. In that same profile, I can take the data and put them into strings that come from sampling the sensors, then send this using the header files I have found for writing to an external SD card through the SPI interface. This file would then be sent as a .txt file (though admittedly I'm not sure how to actually set this to be a type of file, so maybe it will just be understood by the iOS app without any file extension) "

    The co-existence problem hopefully will not be an issue, because it will basically be recording data until something triggers it to stop, then when it stops it would close that .txt file and send it to the phone. That's how I see it working anyway. 

    Thank you very much for your help on this. 

  • Crippling the radio is definitely a problem, or better said, having reads/writes to SDCard in the same CPU cycles/memory pool than the BLE stack is pretty much impossible to the best of my experience.

    I have accomplished reads/writes to SDCard in CC2540, and separately had application code to relay serial port data to a BLE enabled iPhone, but when attempting both at the same time, the radio (BLE) always breaks at some point in execution.

    As of now, our project has used Chan's FatFS and PetitFS with SD-SPI through bit-banging (_hal_uart_spi.h/.c doesn't really work on cc2540, even on the supposedly working ALT2 configuration so bit-banging had to be implemented). Both to no success as BLE breaks at about 20-30 ticks (20-30 seconds, 1 open/write/close per second).

    Needless to say this is surely a memory issue. PetitFS supposedly restricts heap usage to under 100B since it writes only from sector start and only writes whole sectors, but in real scenarios where you want to efficiently append to a sector of data with PetitFS, you have to keep a 512B buffer in application memory which pretty much emulates the standard, non-petit FatFS, so it's back to square one on memory usage.

    Just to give a better overview of the issues arising on these kinds of implementations, we are considering adding another CC2540 to our design, and placing 2 of them in series dividing the workload of SDCard operations and BLE operation between them so as not to break BLE. It's overkill, but after 3 months of testing it's the only real solution we can think of.

  • Hi Tiago,

    I'm in the same situation as yours. I want to read a file from SD card and send it to phone using BLE. I have modified simpleBLEperipheral project and added SD card read and write functionality to minimize memory usage. But then I came to know that SD card doesnt really let you write and read as in flash memory. I mean its more of a sophisticated way of using FAT file system and creating a file or reading a file. I would really appreciate if you can give me heads up on using Chan's FatFS or any other along with CC2541. Is chan's file system too big for CC2541 memory ? Any other advice?

    Thanks
  • Hello,

    Could anyone give us some guidelines about how one can read/write a file on a sd card through cc2540 ? I am working with FATFS by Chan and the SimpleBLEPeripheral example. Could anyone help me? Unfortunately my code doesn't work.

    thank you in advance,

     

  • Hi,

    Do you have a problem with porting Chan's FatFS, or FatFS works fine, but breaks the radio?

    If I remember correct, making user code co-exist with TI's BLE stack could be tricky. The stack uses a basic cooperative planner to manage radio tasks. For radio to function properly, user code must not block. One cannot, for example, run blocking function that checks if file exists (those can take time).

    Frankly, I believe that if application needs MCU to do anything short of basic user code, it will be much better served by BLE-enabled chips like 2650 or others, where stack runs separately.
  • Hello,


    Thank you very very much for your message. The first problems is with Chan's FATFS, specifically with diskio.c. It gives as warnings the "MMC_disk_initialize", "ATA_disk_read", "MMC_disk_read" and "USB_disk_read". 

    My target is to send a file "message.txt" to the SD card. I am based on the SimpleBLEPeripheral Example and the spi_master_send.c example with a rate for the SPI = 115200 .

    The SD card is 2GB. And my code is the following:


    /* Initialize SPI interface and external memory */
    void memInit(void)
    {
        //*** Setup USART 0 SPI at alternate location 1 *** //
        // Configure USART0 for Alternative 1 => Port P0 (PERCFG.U0CFG = 0).
        PERCFG = (PERCFG & ~PERCFG_U0CFG) | PERCFG_U0CFG_ALT1;    
        // Give priority to USART 0 over Timer 1 for port 0 pins.
        P2DIR &= P2DIR_PRIP0_USART0;
       // Set pins 2, 3 and 5 as peripheral I/O and pin 4 as GPIO output.
        P0SEL = (P0SEL & ~BIT4) | BIT5 | BIT3 | BIT2;
        P0DIR |= BIT4;
        // Configure CS (P1_7/P1_2) as output

        // Configure P1_0 as GPIO output for LED1.
        P1SEL &= BIT0;      // GPIO.
        P1DIR |= BIT0;      // Output.
        P1_0 = 0;           // LED1 off.
        
        CS = CS_DISABLED;

    //*** Configuration - Setup the SPI interface ***
        // Fill array with bytes to send.
        uint8 value = 0x00;
        int i;
        for (i = 0; i < BUFFER_SIZE; i++)
        {
            txBufferMaster[i] = value++;
        }
        
        // Set USART to SPI mode and Master mode.
        U0CSR &= ~(U0CSR_MODE | U0CSR_SLAVE);
        
            
         // Set:
        // - mantissa value
        // - exponent value
        // - clock phase to be centered on first edge of SCK period
        // - negative clock polarity (SCK low when idle)
        // - bit order for transfers to LSB first
        U0BAUD = SPI_BAUD_M;
        U0GCR = (U0GCR & ~(U0GCR_BAUD_E | U0GCR_CPOL | U0GCR_CPHA | U0GCR_ORDER))
            | SPI_BAUD_E;
        
    /* Transfer data */
        // Clear SSN, the SPI slave is active when SSN is low.
         CS = CS_DISABLED;
        
         for (i = 0; i < BUFFER_SIZE; i++)
        {
            // Write byte to USART0 buffer (transmit data).
            U0DBUF = txBufferMaster[i];

            // Check if byte is transmitted.
            while(!(U0CSR & U0CSR_TX_BYTE));

            // Clear transmit byte status.
            U0CSR &= ~U0CSR_TX_BYTE;
        }
        
        CS = CS_ENABLED;
     
        FATFS FatFs;   /* Work area (file system object) for logical drive */
        /* Register work area to the default drive */
        if(f_mount(&FatFs, "", 1)==FR_OK) {
          FIL fil;       /* File object */
          UINT bw;
          CS = CS_ENABLED;
          WAIT_1_3US(2);
         
        /* Open a text file */
          f_open(&fil, "message.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE | FA_CREATE_ALWAYS);
          WAIT_1_3US(80);

        /* Read all lines and display it */
          f_write(&fil, "Hello world!\r\n", 14, &bw);
          WAIT_1_3US(80);
        
        /* Close the file */
          f_close(&fil);
          CS = CS_DISABLED;   
        }
     
        while(1);

    }

    Which is the problem ? It is the first time I am programming the cc2540 and I don't understand.

    Thank you in advance,

  • Hello,

    >> It gives as warnings the "MMC_disk_initialize", "ATA_disk_read", "MMC_disk_read" and "USB_disk_read".

    What do you mean by "as warnings"? Does some compiler warning pops ups?

    There was a thread (e2e.ti.com/.../280960) describing apparent stack/memory problem when cramming both FatFS and BLE example into CC2540.

    As a side note: do you use some FatFS port checked on other 8051-type MCU? Or did you begin from scratch?

    Regards,
  • Hello,


    Firstly, thank you very much for your message and help. I am using the IAR Embedded Workbench. The thread you sent me says that "Unfortunately, the page you've requested no longer exists. Please use the search form above to locate the information you're interested in."

    I have started from the scratch with cc2540. To notice that now I don't have any error or warning! I resolve these! I finally use only the diskio.h, the ff.h and the integer.h. Nothing else.

    Any advice about my code. Is something wrong? As I told I have based on the spi_master_send.c from the peripheral exampes of cc2540 and the SimpleBLEPeripheral project. The reason that the file is not created is possibly the baud rate or the definition of the clock? Should I possibly create another file for the sd card, based on the spi_slave_receive.c?  

    Could you please tell me which file of Chan's Library you use in order to recognize the existence of the SD card ?

    Thank you again,

  • Sorry about the link, it has got extra symbol somehow. Here it is: e2e.ti.com/.../280960

    Apparently, topicstarter (Tiago Borba) had run in some memory issues.
    Can you please describe the warnings? Are those IAR compiler warnings?

    // I have started from the scratch with cc2540. Any advice, please?
    First of all, does your project need to use SD card and BLE radio simultaneously? CC2540 is poorly suited for handling both BLE stack (implemented as non-blocking state machine) and user code that might incur long delays.
  • Thank you for the link! I have already read it. However, it doesn't help me. I will try to contact with Tiago Borba.

    My project need to use sd card to save files. And then , I would like to send the file to the central BLE (the mobile phone).
    Can the cc2540 support this function?
    So, I use the FATFs of Chan's library and I try to create a file "message.txt" in the SD card through SPI.

    Thank you again,

  • Dear Oleg Komlev,

    My answer is above! I don't understand why it is above! In addition to my previous message, when I will transfer files to the memory, I will disable the BLE radio.

    Thank you again for your help!

    Kind Regards,

  • Hello,

    >> which file of Chan's Library you use in order to recognize the existence of the SD card ?

    Check out elm-chan.org/.../00index_e.html. It is hardware-dependent function. Disk detect of SD card via SPI requires a few simple steps, but they do require changing SPI frequency (the SPI master should use SCLK of no more than 400 kHz during initial attempts to exchange data with SD card).

    I recommend finding some usable FatFS port and adapting it for this very reason. I cannot point exact working 8051 port, but I believe many examples at Chan's page (the link above) might be usable. An excellent PIC32 port was provided by some kind soul at Microchip's forums (www.microchip.com/.../m563218.aspx), I think it could be used as template.
  • Hello,

    Thank you very much for your help and your time. I am sorry for disturbing you again.

    For the SPI I use the examples, I have already mentioned in order to be more sure that this will work. Now I use the generic example of

    http://elm-chan.org/fsw/ff/ff12.zip

    and I cannot initialize SDCard  (diskio.c, sdcard,.h).

    Also, some here at the forum mention that the best speed of SPI is 400KHz. Has anyone achieved this experiment in order to give us some guidelines ?

    Thank you very much.

  • Hello,

    First of all, 400 kHz is not "best" SPI clock frequency, it is required after card was powered up, to write commands via SPI. Later, it can be changed to much higher numbers. Many cards permit 20 MHz clock, some even higher.

    The generic port (ff12.zip) will not be enough. disk_initialize(), disk_write(), disk_read() and several other functions are not implemented in generic port, because they are hardware-dependent. You will need to either write them from scrath, or (much better way imho) adapt them from some working project, possibly designated for other MCU. I suggest googling for some projects and tutorials: I believe something like www.8051projects.net/.../MMC-SD-Card-interfacing-and-FAT16-Filesystem.pdf could give you a good start.

    Best regards,
  • Thank you again for your message! I built the code as well as the disk_initialize(), disk_write(), disk_read() etc funtions.
    Everything works without errors and without warnings!

    [1] I don't know how I can understand that the "x" SPI clock frequency is the appropriate in order to achieve communication and successful transfer of data.

    [2] Also, there isn't official information about if I should de-activate the BLE advertisement in order for the data to be transfered to the SD card (a file in my case) or not.

    Many sincere thanks again for your time and help .

    Kind Regards,
  • [1] 400 kHz limit is imposed by SD card specification, if I am not mistaken. As of upper limit, better stick with several megahertz for start.

    [2] That's entirely up to you. Just remember that for CC2540 to serve BLE stack, software should not block: it may not, for example, poll card for half a seconds without returning control to stack.
  • Thank you very much!

    Do you know where I should call my function that initializes SPI and SD card?

    I call it in the  osalInitTasks() and it gives me a linking error! I don't understand why!

    void osalInitTasks()

    {

      ... ... ...

    memorySPIinit();

      ... ... ...

    }

    It gives "Linking Error[e27]: Entry "SD_Command::?relay" in module OSAL_SimpleBLEPeripheral ( C:\Texas  ..... ..... .... "

    Have a nice day,

  • Hello,

    I have built the code without errors and when I am trying to call the SD_SPI_initialization() function I get the error :

    What am I missing? I don't understand! I call my function from the "performPeriodicTask()" function of SimpleBLEPeripheral.c .

    Could anyone help me ? I am using cc2540 with 128K flash and INT_HEAP_LEN=3072.

    Thank you,

  • Dear Oleg Komlev,

    I am working with the SimpleBLEPeripheral sample and I have build my code accompanied with Chan'slibrary and everything works without errors.
    However when I am trying to call the SD_SPI_initialization() function everything stops. There is no BLE advertisement and nothing is created in the SD!!!
    Should I use aother example like the HostTestRelease or SimpleBLEBridge??
    PLEASE can anyone helps me who has already achieved this interface?

    THANK YOU,
  • Hello Oleg Komlev,

    Thank you for your help by now! I would like very much to understand if there is anyone who has achieved SD interface with CC2540, not simultaneously with the handling of BLE stack.
    I mean has anyone achieve to do something with the SD and CC2540, even with the BLE to be disconnected??

    If yes, in which sample of Stack he was based on?

    Thank you! ANY HELP PLEASE?
  • Hello,

    I do not get it - how did you manage to call any function despite linker error? I thought IAR simply should not download.

    128K device may be too small to house both stack and FatFS code. Try to crank compiler optimisation up, if possible, or maybe use 256K part. It's been years since I have worked with 8051s under IAR, maybe there are some banking tricks one could use to optimize code placement.

    We have tried to develop mesh-like network demo with 2540s using Master/Peripheral role switch, and it was a failure: stock TI demo leaves, if memory serves me, like 12-16KB of program flash free. Simply adding Master source code to project broke the hole thing - it will not fit, at least with compiler available to us.

    Best regards.
  • Hello Oleg Komlev,

    Many sincere thanks for your prompt message! I don't treat any problem with the stack when I am executing simpleBLEPeripheral sample and FATFS. I follow these instructions --> processors.wiki.ti.com/.../128kproject !

    So you have not achieved an interface betweeen a SD card (or any other non volatile external memory) and CC2540 by now? Even if we talk about the version of cc2540 with 256K?

    Have you ever achieved an interface like this with other board, like the cc2640 or something else?

    I wonder how Tiago Borba ( e2e.ti.com/.../280960 ) mentions that he has achieved to do everything (read/write/open a file, etc.), without BLE connection. I would like to do the same but I cannot! Everything is debugged in IAR without errors but nothing happens in the SD!

    Unfortunately, Tiago Borba don't answer in any message! :( And unfortunately, there is no help or guidelines from someone who knows by TI! :(

    Thank you very much for your valuable time .

    Kind Regards,
  • Hello!

    We are trying to write to an SD card using the sensor tag but we aren't able to find any start point. The sensor tag would be the cc2650 one. Is there any way to port your code to the new sensor tag?

    thank you
    alejandro
  • Hey Tiago!
    I see that you actually accomplished reads/writes to sd card on the cc2540. Could you give me a hand on how you accomplished this?
    I'm using the cc2650 and it might be very similar.

    Thank you
    Alejandro
  • Hello,

    I started again to work in this project! I managed to read/write in a SD card without the use of Bluetooth stack and functionality. But I would like to insert it in my application.

    I would like to read/write the SD card and to send the data to the mobile. Could you please help me with any hint?
    Thank you,