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.

TM4C; Flash or EEPROM how to read from?

Hello,

I am progressing on a project that contains a timer interrupt...which samples temperature from the ADC. I would like to store that temperature into memory(FLASH or EEPROM...it doesn't matter) so that I can retrieve it when desired.

There is a while(1) loop after the EEPROM code. I want to replace the while loop with some type of user input...press a button, etc to move on and transmit the data.


Before the loop/logic I'd like to store temperature F to memory. After the loop/logic I would like to READ from memory and store to msg.tempF for the rest of the program to use.


I tried to set pui32Read to msg.tempF and I simply got the address of pui32Read. How do I get the contents? That was with EEPROM of course...i wasn't sure how to even get started reading flash.

Thanks!

void Timer0IntHandler(void)
{
    int32_t intStatus;
    message_t msg;
    uint8_t * ptr,
              byte;

    uint32_t ui32ADC0Value[4];
    volatile uint32_t ui32TempAvg;
    volatile uint32_t ui32TempValueC;
    volatile uint32_t ui32TempValueF;

    uint32_t pui32Data[1];
    uint32_t pui32Read[1];

    //////////////////////////////////////////////////////////////////////////
    //Enable the gpio led pins
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //For Flash testing
    GPIOPinTypeGPIOOutput
    (GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x00);
    SysCtlDelay(20000000); //End of flash testing
    //////////////////////////////////////////////////////////////////////////


    //////////////////////////////////////////////////////////////////////////
    //Enable the analog to digital converter. ADC0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ///////////////////////////////////////////////////////////////////////////

    // Retrieve timer interrupt status.
    intStatus = TimerIntStatus(TIMER0_BASE, true);

    // Clear interrupt.
    TimerIntClear(TIMER0_BASE, intStatus);

    // Check if the interrupt was the correct one (timeout).
    if((intStatus & TIMER_TIMA_TIMEOUT) == TIMER_TIMA_TIMEOUT)
    {     
        ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
        ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_TS);
        ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_TS);
        ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_TS);
        ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_TS|ADC_CTL_IE|ADC_CTL_END);
        ADCSequenceEnable(ADC0_BASE, 1);
        ADCIntClear(ADC0_BASE, 1);
        ADCProcessorTrigger(ADC0_BASE, 1);

        while(!ADCIntStatus(ADC0_BASE, 1, false)) //Unknown time in this loop.
        {
        }

        ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
        ui32TempAvg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2] + ui32ADC0Value[3] + 2)/4;
        //Allows for whole number temperature. Does not allow for floating point values. Look at data sheet
        ui32TempValueC = (1475 - ((2475 * ui32TempAvg)) / 4096)/10;
        //ui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;
        ui32TempValueF = (ui32TempValueC * 9/5) + 32;

        //////////////////////////////////////////////////////////////////////////
        //Programs the data array we created, to the start of the block(10k), of the length of the array
        pui32Data[0] = ui32TempValueF;
        FlashErase(0x10000);
        FlashProgram(pui32Data, 0x10000,sizeof(pui32Data));
        GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x02);
        SysCtlDelay(20000000);

        SysCtlPeripheralEnable (SYSCTL_PERIPH_EEPROM0);
        EEPROMInit();
        EEPROMMassErase();
        EEPROMRead(pui32Read, 0x0, sizeof(pui32Read));
        EEPROMProgram(pui32Data, 0x0, sizeof(pui32Data));
        EEPROMRead(pui32Read, 0x0, sizeof(pui32Read));
        GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x04);
        
        while(1){
        }
        //////////////////////////////////////////////////////////////////////////


        msg.tempF = ui32TempValueF;
        UARTprintf("\nTemperature sent is %d\n",msg.tempF);


        // Cast the structure into a byte array.
        ptr = (uint8_t *)&msg;

        // Loop through the entire message.
        for(byte = 0; byte < sizeof(message_t); byte++)
        {
            // Is there space in the Tx FIFO?
            if(UARTSpaceAvail(UART1_BASE) == true)
            {
                // Put the byte into the Tx FIFO.
                UARTCharPut(UART1_BASE, ptr[byte]);

            }
            else
            {
                // Otherwise, stash the byte in our FIFO for when there's space.
                RingBufWriteOne(&txRingBuf, ptr[byte]);
            }
        }
    }
}

  • Hello Erik

    Is that the code in an Interrupt Handler?

    Regards
    Amit
  • Hi Amit

    Yes it is in the Timer0Interrupt. Unless there is a better way of handling it.

    Thanks!

  • Hello Erik

    The interrupt routine needs to be slimmed down. There is a lot of processing being done in the interrupt which I think is not required.

    There are 2 parts to programming microcontroller

    1. Initialization
    2. Processing

    As an example, the ADC initialization can be in the main loop and only the trigger in the timer interrupt handler. Or even better would be to trigger the ADC from the timer, and in the ADC interrupt handler, where your code reads the ADC value, push the value to the EEPROM. Again, EEPROM initialization can be done in the main of the code.

    Regards
    Amit
  • Fantastic. I'll start breaking those things apart. Once it is pushed to EEPROM how would I obtain the correct value from the array or whatever I decide to use? Is there a second read function I should use?

  • It should be noted that MCU's EEPROM requires careful & compliant: set-up, configuration, & usage dictates. Prepare for in-depth reading & time devoted to (necessary) experimentation - and return visits (to Amit) here.

    Unless you (need) to store your values for retrieval (after) a power-cycle - it would appear that use of "MCU's Flash Ram memory" would be, faster, simpler, and a more productive method for your objective...

    Review of "Pointers" will enable your "read" (and "write") from/to specific addresses w/in the MCU's Flash area.

    [edit] poster Robert noted (temporary) insanity...

  • Hello Erik

    What interface the user uses to get data from the uC?

    Regards
    Amit
  • Did you mean to say RAM? After all flash is retained across a power cycle as well and is also relatively complex to program.

    Another item to note is that EE can take a long time to program on this processor, the max programming time is several seconds.

    Robert
  • Hello Robert

    The program time in seconds when the EEPROM is at end of life. I have run this experiment on multiple devices and it has taken a code which does nothing but write to EEPROM in a manner that causes the maximum wear and tear and read back the data to confirm its validity. Under such circumstance the first visible sign of slow down is at 3 days and the first error happens at 5 days.

    Having said that, yes EE can take a long time, but based on the code presented so far, i doubt the user would be performing an EEPROM access at such an rate.

    Regards
    Amit
  • Yes - indeed, Robert - RAM. I've edited (w/out erasing) and credited you w/the identification of my error - w/in original post.
    As always - unguided posters are unprepared to provide "all of the necessary & sufficient facts." (only vendor here believes that is ok...)
  • Amit Ashara said:
    ...based on the code presented so far, i doubt the user would be performing...

    Hello Amit,

    As you/I long have probed/discussed - "Unguided posters cannot (reasonably) be expected to present the "necessary/sufficient" code" - so that you & others do not have to "guess" their (real) objectives.

    Proof of this rains down daily - and each user is "DEPRIVED" of the keen learning experience which, "Proper Guidance" is sure to provide & encourage!

  • Hello Amit,

    I intend for one mcu to sample the adc data and store it(I am now unclear as to which form of memory I should be using). The user will then request the data and it will be transmitted over uart to a second mcu. That second mcu will be connected to some type of putty terminal to view the data. I will be using uartprintf statements to display the data in the appropriate variable.


    The files that you have from me with my previous post has a main.c with a main function. At the end of that function I pull from a message structure and use uartprintf to communicate with the terminal.


    If you have further questions please let me know

  • Hello,
    The reason I was using flash was because there was an available TI Workshop lab that discussed EEPROM and Flash. I understood that EEPROM was slower, but there was some sort of "reading" happening with the example code. Because of this, I thought that EEPROM may be easier to start running with.

    I would like to use flash, but none of these replies assisted in how I should go about reading from that memory address. The lab uses memory address 10k, which is also fine for my use. The temperature that I sample is successfully stored there...but now I need to know how to retrieve it.

    Thanks!
  • Erik,
    The only reason to prefer Flash or EEPROM over RAM is if you need to preserve the data over power cycles. Both flash and EE and slower and more complex to use than RAM. They also wear out.

    From your problem description there doesn't appear to be any need to introduce the complexities of flash and EE.

    Robert
  • Understood, thank you for the clarification!

    For my uses, the simplest of methods should prove to be useful. Do you have an example of how to use RAM instead?

    Also, can you indicate the difference between
    uint32_t
    volatile uint32_t
    I wasn't sure if this would solve my issues...as volatile is obviously lost during a power cycle.

    Thank you!
  • Hello Erik

    Both EEPROM and Flash are easy to use. The Flash has lesser endurance and you have to manage the sector where you would be writing the data.

    A read of the flash uses the macro HWREG(ADDR) and programming required FMA, FMD and FMC control registers as given in the Internal memory section. The programming sequence is also mentioned in the same section of the data sheet.

    If you can add Battery Backed Hibernate module, then the HIBDATA register is the best place to store such data without having it get lost. It is relatively fast, does not have wear and tear as EEPROM/Flash and can work of a coin cell for extended period of time.

    Regards
    Amit
  • Erik A said:
    Do you have an example of how to use RAM instead?

    int x;

    void sub1(void)

    {

    x = 3;

    }

    int sub2(void)

    {

    return x;

    }

    Erik A said:
    Also, can you indicate the difference between
    uint32_t
    volatile uint32_t

    Both are stored in RAM and lost during a power cycle.

    volatile provides the guarantee that all accesses (read or write) are performed.

    Also with some little care it ensures the order that the accesses are performed in.

    so given

    volatile int t;

    and

    x = t + t;

    t = x;

    You are guaranteed there will be two reads and one write of t and that the two reads will be performed before the write.

    Given

    volatile int t;

    volatile int y;

    and

    x = t + y;

    t = x;

    You are guaranteed one read of t and y plus one write of t.  The read of t and y will occur before the write of t but you cannot be guaranteed the read order of t and y.

    This is useful for when you are dealing with interrupts and threads (you can be sure the values are not cached1 by the compiler but written or read) and when reading from hardware (again no caching1 so you read changes that occur outside the compilers knowledge) or writing to hardware (the compiler cannot skip writes that have no apparent code effects).

    It also means that the following code (give the above definition for t)

    (void)t;

    is actually well defined and potentially useful. So too is the definition

    const volatile int q;

    Robert

    1 - Important note: This does not guarantee that the hardware will not cache the read/write. If that is a concern additional steps must be taken.

  • Thank you for the clarification with your response. I also notice that I misread a previous post. I thought you had stated RAM would be sufficient and would work with a power cycling application. I knew that was incorrect but I figured I was missing something. I see now that you suggested RAM if I wasn't worried about power cycling.

    The MCU which samples the ADC will do so for a set amount while it is connected to battery power. The board well then shut off when the battery dies(hence my concern for a power cycle) and will need to retain the data once the battery is recharged enough for the board to power back on. This is the goal of my code. Hopefully that brings in some more clarification.

    So that is why I started exploring flash and/or eeprom once I played around with the workshop lab. I inserted both into my code and I was able to view the stored contents in flash memory and also in eeprom variable memory. But I was having difficulty reading back from memory so that the data could be stored into a variable.
  • Erik, would an SD card be of use to you?

    The SD card library for Tiva is pretty nice, and once you get the swing of reading/writing, you'll have so much storage from today's cards you won't know what to do with it all. Plus, you can always remove the card, and use the data elsewhere.
  • Poster "Phil's" suggestion of SD card does vastly increase the amount of "non-volatile" storage available. Yet it extracts penalties of added size, connector cost, & added power drain upon your battery.

    Should your storage requirements "challenge" that available w/in the MCU - you may consider 8 pin, SPI Flash memory devices which are far more compact while drawing less current than SD card.
  • First, and very important, check the errata for your micro. The TM4C123 series at least has errata which I think renders the internal EE unusable for this purpose. Flash writes may also have issues if interrupted mid-write.

    Second, I think you need to decouple the collecting of data from writing to storage..

    Robert
  • Or, if going that route consider FRAM which is orders of magnitude faster and simpler than either. It does suffer from limited size though and its cost/byte is higher.

    Robert
  • Hello Robert,

    Thanks for bringing it up. I guess the poster can be redirected to the I2C Application Note where a FRAM is used for test and the user can instead migrate the storage to external FRAM instead.

    www.ti.com/.../spma073.pdf

    Regards
    Amit
  • SPI is both simpler and faster Amit.

    It appears you can also get larger sizes in SPI but that's less of a factor.

    Robert

  • Hello Robert

    Agreed. Since the user has tried to use existing solution of EEPROM and Flash without having success (which beats me as it is extensively used by other customers) providing for a working solution on I2C seemed reasonable to reduce further heartburn.

    Regards
    Amit
  • Good Morning to all. I apologize that my replies have been intermittent.
    I have followed software-dl.ti.com/.../TM4C123G_LaunchPad_Workshop_Workbook.pdf which consists of memory instructions within lab 8. The code provides aide on writing to both EEPROM and flash...which works without a hiccup.

    My issue is when it comes time to read back from either EEPROM or flash. The lab does not cover this portion. I was searching before and did not come up with any results. However, I looked again and I did find some reference posts on this forum. EEPROMread which I was unable to locate in CCS... But I will give it a go and see what issues I have.

    But ultimately, I wanted to know how to read from flash memory. That seemed difficult to locate. But that is because there seems to be no API for reading. Thus we must use:
    read_byte = *(unsigned char *)0x1234;

    ...so if ui32tempvaluF is a uint32 used within:
    pui32Data[0] = ui32TempValueF;
    FlashErase(0x10000);
    FlashProgram(pui32Data, 0x10000,sizeof(pui32Data));

    Would I then be able to use read_byte=*(uint32*)0x10000 to get the first stored value? If I then have say...10 tempvalueF stored in flash...how would I want to increment the address?

    Although I am asking the question, I am also going to play around with the code to see if I come up with an answer first.



    To answer some of the previous questions, I am unable to use an SD card. The project is for device power and device communication to be wireless as the product is sealed and self contained. Thus, I wouldn't have a way of removing an sd card. Thus I need to store to memory(to protect against battery power loss) and then communicate using uart infrared the data that was stored in memory when it comes time to do so.

    Thanks for the replies. My deadline is coming up so I hope I can figure out this storage issue. The next part will be making a GUI to interface with the receiving board. Not looking forward to it...
  • Hello Erik,

    And it tells TI that "fix the workshop" Tutorial.

    Another way of accessing the data would be

    for(ui8Index=0; ui8Index<10; ui8Index++)
    {
    read_byte[ui8Index] = HWREG(0x1000+(ui8Index*0x4))
    }

    Regards
    Amit