Jump to content
L.R.A

TM4C129 Hibernation RTC and Calendar Mode

Recommended Posts

This code only works with TM4C1294XL launchpad, don't try it in the older TM4C123 

 

 

Hi guys so i bring you more a basic example code about peripherals. this one i also had some trouble fiding info on how to use it but notigh beats checking out the source files

If you think i should keep geting this simple but handy (i think they are) examples, tell me since i alredy have to make them for some people i know

Hope it helps someone:

/*

  Code made with energia-0101E0012

  This code is suposed to help clarify anyone with doubts of how to use very basic fuctions of the RTC
  in the hibernation peripheral and also the hardware calendar mode. Any sugestions and improvements are always welcome
  
  This example only changes and show hour, minutes and seconds but there's:
    psTime->tm_min
    psTime->tm_sec 
    psTime->tm_mon 
    psTime->tm_mday 
    psTime->tm_wday 
    psTime->tm_year
    psTime->tm_hour

*/
#include "driverlib/hibernate.c"


void HibernateHandler(void)
{
  //Use this to reset interrupt flag
  uint32_t ui32Status = HibernateIntStatus(1);
  HibernateIntClear(ui32Status);
  
  //Place here code to execute every second, ex: LCD or 7 segment display
  //Altough it should be as fastest as possible
  
  
  //To keep the interrupt hapening every second you need this
  HibernateRTCMatchSet(0,HibernateRTCGet()+1);  
}

/*It's need a struct pointer of the type "tm" so i use new to do that. This type of struct is defined in the driverlib/hibernation
  you could also create it like this: tm temp; and then use &temp and temp.values in the fuctions                              
*/
tm *temp = new tm;



void setup()
{
  Serial.begin(9600);
  // put your setup code here, to run once:
  
  //Enable Hibernate peripheral. I'm using Energia so i use F_CPU for geting the clock frequency
  HibernateEnableExpClk(F_CPU);
  HibernateRTCEnable();
  
  //We set a interrupt for the RTC after second. You can change the value
  HibernateRTCMatchSet(0,HibernateRTCGet()+1);
  HibernateIntRegister(HibernateHandler);
  HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);
  
  //Set up calender mode. HibernateCounterMode() is always needed but can be set to 12hr mode
  HibernateCounterMode(HIBERNATE_COUNTER_24HR);
  HibernateCalendarSet(temp); //<-- the struct declared
  
  //We change the hour, minutes and seconds
  temp->tm_hour= 23;
  temp->tm_min=59;
  temp->tm_sec = 50;
  //This fuction below is what actualy updates the values inside the peripheral. 
  //if you don't use it, the value changes above won't do anytigh
  HibernateCalendarSet(temp);
  
}

void loop()
{
  //This is to take the "live" values that the RTC keeps updating into our struct
  HibernateCalendarGet(temp);
  Serial.print(temp->tm_hour);
   Serial.print(':'); 
   Serial.print(temp->tm_min);
  Serial.print(':'); 
  Serial.println(temp->tm_sec);
  delay(1000);
}

Share this post


Link to post
Share on other sites

Nice job!

 

Are you considering packaging it into a library and pulling the code at the Energia repository?

 

I was but,

Altough i alredy learnt alot about classes i am not sure how to do this libraries from TivaWare

 

The problem i have is using stuff like GPIO_PIN_6, TIMER2_BASE,TIMER_A, into easy energia usage.

you know, stuff like that. Do you usualy use like compiler macros to identify them?

 

Also i have 0 knowledge in how to use a repository :P

Share this post


Link to post
Share on other sites

I was but,

Altough i alredy learnt alot about classes i am not sure how to do this libraries from TivaWare

 

The problem i have is using stuff like GPIO_PIN_6, TIMER2_BASE,TIMER_A, into easy energia usage.

you know, stuff like that. Do you usualy use like compiler macros to identify them?

 

Also i have 0 knowledge in how to use a repository :P

 

One way to get started putting together a library for Energia is to look at some of the existing libraries

(find something similar and borrow the code, then adapt to your needs).

Either browse the built in energia libraries, or check out examples posted in the forums.

 

As far as the macros - just include whatever header file defines the macro (for things like TIMER_A).

For something like GPIO_PIN_6 - if want to let the user of the library decide what pin to use, make the pin an argument (e.g. to the class constructor).

In cases where can't do that (e.g. need to be compiled in for speed), make the pin a #define in the library source file (so can change by editing one spot in the library).

 

As far as repository - git/github is not hard to use, there are some reasonable graphical front ends.

Took a little while to get started, but now I find it quite helpful (even for things that I am not sharing it is nice to be able to edit away, secure in the knowledge that if I 

mess something up I can always look back at older versions of my code to see what I messed up, or go back and resurrect an old idea).

Share this post


Link to post
Share on other sites

One way to get started putting together a library for Energia is to look at some of the existing libraries

(find something similar and borrow the code, then adapt to your needs).

Either browse the built in energia libraries, or check out examples posted in the forums.

 

As far as the macros - just include whatever header file defines the macro (for things like TIMER_A).

For something like GPIO_PIN_6 - if want to let the user of the library decide what pin to use, make the pin an argument (e.g. to the class constructor).

In cases where can't do that (e.g. need to be compiled in for speed), make the pin a #define in the library source file (so can change by editing one spot in the library).

 

As far as repository - git/github is not hard to use, there are some reasonable graphical front ends.

Took a little while to get started, but now I find it quite helpful (even for things that I am not sharing it is nice to be able to edit away, secure in the knowledge that if I 

mess something up I can always look back at older versions of my code to see what I messed up, or go back and resurrect an old idea).

 

 

I always program in a cloud like Dropbox so i also have older versions of my codes saved :P

 

Right now i'm having the weirdest error...

 

In file included from D:\MEOCloud\MEOCloud\energia-0101E0012\hardware\lm4f\libraries\RTChardware\RTChardware.c:3:0:
D:\MEOCloud\MEOCloud\energia-0101E0012\hardware\lm4f\libraries\RTChardware\RTChardware.h:7:1: error: unknown type name 'class'
D:\MEOCloud\MEOCloud\energia-0101E0012\hardware\lm4f\libraries\RTChardware\RTChardware.h:8:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
 
if i remove #include RTChardware.h from RTChardware.c the error doesn't happen.
This is so weird, i'm writing a class like how i do in visual studio
 
 
XD it can't be .c file it needs to be .cpp, nevermind

Share this post


Link to post
Share on other sites

Can anyone advice in how to use interrupts in a class / library? looking for various ways to do this to see what is the best one

Share this post


Link to post
Share on other sites

Can anyone advice in how to use interrupts in a class / library? looking for various ways to do this to see what is the best one

 

I would start looking in the internals of energia - 

e.g. wiring.c (see how handles functions to be called on the SysTick interrupt)

also WInterrupts.c (part of the handling of pin interrupts, finding the rest is left as an exercise to the reader ;-)

Tone.cpp gives example of using a timer interrupt.

 

Unfortunately, as far as I know there is no general mechanism provided for managing timers or timer interrupts in Energia.

 

These files are under the energia install directory, in hardware/lm4f/cores/lm4f

 

For another approach to managing interrupt handlers, look at something like the cmsis startup files for the use of weak attributes.

(Declaring the default handler weak means you can provide a handler, but user code can provide another handler which will override the weak one.)

Share this post


Link to post
Share on other sites

figured I would try this on my old stellaris launchpad just to see what happens. Very weird results. The entire setup routine runs without issue.

 

HibernateCalendarGet(temp);   //causes the chip to hang every time, stops responding to interrupts too.

 

The hibernate handler, that "kinda" works. I added a line to invert a boolean variable I declared at the start of my code and changed the loop routine to simply write that state to the red LED. Now, run the sketch, the LED seems to blink at 0.5Hz, very nice. But after a completely unpredicatable amount of time it stops. Totally unpredictable. I mean it. I had it work for a few minutes while I went to get a drink, then leave to throw something in the bin and come back to find its stopped. Then I reset the board, it blinked 3 times and it stopped. Reset it before writing this post and it gave out while typing HibernateCalendarGet(temp);

 

No idea whats going on. My first thought was that maybe the stellaris doesnt have RTC (havent checked datasheet in all honesty) but the setup routine does all work and the hibernate module is still triggering 1 secondly interrupts. Who knows??? I don't have a tiva c launchpad to see if it works there, only the connected launchpad the code was originally demoed for (now it does work there)

Share this post


Link to post
Share on other sites

Hi,

The "calendar mode" is a feature available only for TM4C129x microcontrollers. Does not exist on 123 series. It is an addition of several registers with bit fields allocated for year, months, day of the week, hours, minutes, seconds.

On "old" Launchpad you will get hard fault, since calendar mode writes to non-existing registers (of coarse you need to initialize with some data before calling HibernateCalendarGet() ).

However, the RTC counter mode is still available, can be used - and that implies of coarse the transformations with time structure, instead to be read at once.

L

Share this post


Link to post
Share on other sites

To use in tm4c123 you can just do this to turn on the RTC:

 

HibernateEnableExpClk(F_CPU);
HibernateRTCEnable();

 

 

This will set the interrupt to every second:

HibernateRTCMatchSet(0,HibernateRTCGet()+1);

HibernateIntRegister(HibernateHandler);
HibernateIntEnable(HIBERNATE_INT_RTC_MATCH_0);

 

and here is the interrupt function:

void HibernateHandler(void)

{
//Use this to reset interrupt flag
uint32_t ui32Status = HibernateIntStatus(1);
HibernateIntClear(ui32Status);

//Place here code to execute every second, ex: LCD or 7 segment display
//Altough it should be as fastest as possible


//To keep the interrupt hapening every second you need this
HibernateRTCMatchSet(0,HibernateRTCGet()+1);
}

Share this post


Link to post
Share on other sites

Thanx for posting that. Nice work.

 

Now something that's always made me curious. On the TM4C123 launchpad, is there a way to hook up a separate VBAT somehow, say from a coincell, so that the RTC in the hibernation module keeps on running ? Why ? Well, I have a microSD attached, and would like to get a reasonable time/date set ...

 

- Thomas

Share this post


Link to post
Share on other sites

On the launchpad? nope. Vbat is soldered into the power mains...

It just doesn't makes sense that TI wastes the hibernation module like this.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...