Jump to content
Sign in to follow this  
Bernard

LM4F120 Timer issue

Recommended Posts

Hello,

 

First of all I apologize for my broken English.

 

I am  a beginner and I am  trying to understand some examples from TI workbook.

 

Some examples work but I have problems with the blink timer  I ported under Energia.

 


#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include"Energia.h"

unsigned long ulPeriod;

void setup()
{    
  //SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
  TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
  ulPeriod = (SysCtlClockGet() / 10) / 2;
  TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
  IntEnable(INT_TIMER0A);
  TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
  IntMasterEnable();
  TimerEnable(TIMER0_BASE, TIMER_A);
}

void loop()
{
}

void Timer0IntHandler()
{
  // Clear the timer interrupt
  TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
// Read the current state of the GPIO pin and
// write back the opposite state
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
{
  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
}
else
{
  GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
}
}

Tried to add in startup_gcc.c :

Timer0IntHandler at its right place 

and :  extern void Timer0IntHandler(void); at the top of file.

 

I still am getting the same error message :

core.a(startup_gcc.c.o) :(.isr_vector+0x8c): undefined reference to `Timer0IntHandler'
collect2: error: ld returned 1 exit status

 

Any help would be appreciated.

 

Salutations.
 




			
		

Share this post


Link to post
Share on other sites

Tried to add in startup_gcc.c :

Timer0IntHandler at its right place 

and :  extern void Timer0IntHandler(void); at the top of file.

 

I still am getting the same error message :

core.a(startup_gcc.c.o) :(.isr_vector+0x8c): undefined reference to `Timer0IntHandler'

collect2: error: ld returned 1 exit status

 

Any help would be appreciated.

 

Salutations.

 


 

 

Could you upload your startup.gcc file?

Share this post


Link to post
Share on other sites

Hello,

 

My project actually is the ino file in my first post.

 

Here is the original project from TI worbook.

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "Energia.h" // added .. mandatory or not ? tried with and without this  .. no change

int main(void)
{
unsigned long ulPeriod;

SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
ulPeriod = (SysCtlClockGet() / 10) / 2;
TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
IntEnable(INT_TIMER0A);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
IntMasterEnable();
TimerEnable(TIMER0_BASE, TIMER_A);
while(1)
{
}
}

void Timer0IntHandler(void)
{
// Clear the timer interrupt
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
// Read the current state of the GPIO pin and
// write back the opposite state
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_2))
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
}
else
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
}
}

then example says for startup_ccs.c :

 

Timer0IntHandler         //Timer0  subtimer  A

You will also need to declare this function at the top of this file as external. This is


necessary for the compiler to resolve this symbol. Find the line containing:


extern void _c_int00(void); // doesn't exist on Energia startup_gcc.c


and add:


extern void Timer0IntHandler(void);
 

This is driving me mad ... :)

 

Salutations

Share this post


Link to post
Share on other sites

Hello bluehash,

 

The only file of the project is the .ino one .. Energia is supposed to do the rest of the job. no particular settings.

I am running Energia on Linux 10.04 32 bits ... I don't think it would be a problem since some other examples like " internal temp sensor " (I posted on the forum hours ago ) work.

 

I won't give up ... Stellarpad is new on the market and the community will grow ... I hope :)

 

I appreciate your help ... I don't feel alone in this world :)

Share this post


Link to post
Share on other sites

Using Energia, you don't supply the main(). One just implements a setup() and loop() function.  The startup.c and main.c are provided automatically by the ide when you press Verify.  Look at this introduction to Arduino style programming.  http://arduino.cc/en/Tutorial/BareMinimum

 

When you compile an '.ino' file it is compiled with arm-none-eabi-g++, that means your void Timer0IntHandler() gets C++ name managling which is the reason your link phase is failing. You could add extern "C" void Timer0IntHandler() to get C calling conventions however, Energia programs aren't meant to compile the TI samples without modification. Energia is going to use its own startup.c and main.cpp https://github.com/energia/Energia/blob/master/hardware/lm4f/cores/lm4f/startup_gcc.c https://github.com/energia/Energia/blob/master/hardware/lm4f/cores/lm4f/main.cpp . Energia also compiles your arm code with hardware floating point enabled so it does the floating point hw initialization in the startup code.  If the fp hw isn't initialized it will probably trigger a fault at some point.

 

If you want to use the arm-none-eabi-gcc compiler included with Energia for arbitrary programs then you shouldn't use the ide. Just setup your PATH environment in your command line. It works just fine from the command line and should happily compile using make.

 

Energia is a C++ api framework with an integrated build environment for c++ programs. Its main purpose is to abstract the low level hardware peripherals into a higher level api that can be used with different microcontrollers with minium change.

 

-rick

Share this post


Link to post
Share on other sites

Hi rick,

 

Thank you for information.

 

I know that Energia,  like Arduino uses  setup()  and loop()  and my initial post uses this way . I just wanted to know if my blink Timer example could work using TI driverlib libraries . it compiles but no led blinking.

 

This example works and display internal LM4F120 internal temperature on terminal :

 

/* Read internal temperature sensor of LM4F120 
 Stellaris Launchpad
 Example from TI LM4F120 workbook
 A la mode Energia
 */

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "Energia.h"

unsigned long ulADC0Value[4];
volatile unsigned long ulTempAvg;
volatile unsigned long ulTempValueC;
volatile unsigned long ulTempValueF;

void  setup()
{
  Serial.begin(9600);

  SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
  SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS); // 250
  ADCSequenceDisable(ADC0_BASE, 1);
  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);
}
void loop()
{  
  ADCIntClear(ADC0_BASE, 1);
  ADCProcessorTrigger(ADC0_BASE, 1);
  
  while(!ADCIntStatus(ADC0_BASE, 1, false))
  {    
  }

  ADCSequenceDataGet(ADC0_BASE, 1, ulADC0Value);
  ulTempAvg = (ulADC0Value[0] + ulADC0Value[1] + ulADC0Value[2] + ulADC0Value[3] + 2)/4;
  ulTempValueC = (1475 - ((2475 * ulTempAvg)) / 4096)/10;
  ulTempValueF = ((ulTempValueC * 9) + 160) / 5;
  Serial.println(ulTempValueC);
  delay(300);
}

So I was wondering why blink with timer wouldn't work.

 

Salutations.

Share this post


Link to post
Share on other sites

When you compile an '.ino' file it is compiled with arm-none-eabi-g++, that means your void Timer0IntHandler() gets C++ name managling which is the reason your link phase is failing. You could add extern "C" void Timer0IntHandler() to get C calling conventions however, Energia programs aren't meant to compile the TI samples without modification.

 

So the key to what I was saying is that Energia sketches are really C++ files. That means functions compiled with g++ will end up with different names than functions compiled with gcc. Look up C++ name mangling on the web. The way to force Energia to compile your C functions without name mangling is to create a new tab and call it "something.c". In the example below I created two new tabs, "timer_blink.c" which has the interrupt implementation, and "timer_blink.h" which has the declaration of those functions. I put some special sauce ( the ifdef __cplusplpus ) around the header to use 'extern "C" { }' when compiling with g++. When you compile with gcc that will break your compile if it isn't excluded.

 

In your code, I made some modification to show how to better work with Energia. I added an initTimer() function. In "timer_blink.h" I got rid of the headers that are already being included by Energia. You want to include Energia first so you pick up all the board related header defines before using the other "inc/xxx.h" files. In "timer_blink.c" I got rid of the calls to functions that Energia already takes care of, I also showed how you can use the pinMode in combination with the low-level Stellariware calls.

 

post-4-14264605169633_thumb.png

 

In the gist below, the diff shows what I changed in the Energia startup_gcc.c and timer_blink.ino is the c++ code

 

[/gist]

 

The better way to deal with missing features you want is to write a C++ wrapper and share it with the rest of us. A generic Timer class that provided useful stopwatch, interval and other useful timer functions would be welcome by all of us.

 

This is the first release on the lm4f so we wanted to get it out the door as soon as possible. There are many features to be added and help from the community is much appreciated.

 

Thanks,

 

-rick

Share this post


Link to post
Share on other sites

Hi ,

 

I am trying to configure timer interrupt at run-time using TimerIntRegister according to Stellaris® Peripheral Driver Library USER’S GUIDE.

 

Put startup-gcc file in initial state. it seems we don't have to modify anything.

 

Timer_blink.c

void initTimer(unsigned Hz)
{
  //ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
  
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
  //TimerIntRegister(TIMER0_BASE, TIMER_A, timer0_interrupt); 
  TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); //TIMER_CFG_32_BIT_PER deprecated use CFG_PERIODIC
  
  unsigned long ulPeriod = (SysCtlClockGet() / Hz) / 2;
  TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
  //IntEnable(INT_TIMER0A);
  TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
  TimerEnable(TIMER0_BASE, TIMER_A);
  TimerIntRegister(TIMER0_BASE, TIMER_A, timer0_interrupt); 
  
}

  void timer0_interrupt(void)
{
 TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);  // Clear the timer interrupt
 digitalWrite(RED_LED, digitalRead(RED_LED) ^ 1);// toggle LED pin
}

Timer_blink.h now

 

#ifdef __cplusplus
extern "C" {
#endif

void initTimer(unsigned);
void timer0_interrupt();

#ifdef __cplusplus
}
#endif

Compile Ok but  upload freezes ( I never see "success" )

If I unplug and plug again  the card I can see the program working  ( tried different frequencies to make  that clear)

Looks like program runs before the end of uploading process ????

 

 

Thank you for help.

 

Salutations.

 

Bernard

 

I have read some posts about that on TI forums ... seems to be a Vtable relocating problem , conflict with bootloader...

 

 

 

 

 

 




 

Edited by brownfox

Share this post


Link to post
Share on other sites

The real problem arround here, is the interrupt routines definition in the startup.gcc

 

I have been fighting for 2 weeks with Energia, trying to enable the timer 0 and the interrupt based ADC. But when I declare the interrupt functions on the startup.gcc file, the code compiles without problem, and its loaded into the stellaris without errors, or freezings, like the ones that brownfox is having.

 

My code idea was to sample a signal at full speed (1Msps) and have a constant clock signal at 1hz, all interrupt based. Actually Im sampling at 950Ksps, filling a 2048 samples block, without DMA. Im trying to make a DSO like board for my laptop, so its a good start. 

 

The code, and some explanation (spanish post, so open google translate in a new window  :D ) is in this url http://patolin.com/blog/2013/05/16/stellaris-launchpad-y-energia-programando-un-cortex-m3-facilmente/

 

Honestly, using CCS for the stellaris, was not so funny for me. I dont like eclipse, and its pretty slow in my not-so-top-notch laptop, so Energia makes the things more easy for me, and I think that it will help more people to use the launchpads

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.

Sign in to follow this  

×
×
  • Create New...