Jump to content
vineetp

Tiva C launchpad runs too slow.

Recommended Posts

I'm using a Tiva C series launchpad (TM4C123G) to sample analog data using an external ADC (ADC0804). The ADC is clocked at 1.4MHz. The SysCtlClockSet command was used to set clock freq to 80MHz. 

A square wave is being generated on a pin, with a frequency same as the sampling rate, using the code given below. So this gives us the sampling rate on an oscilloscope. 

For some reason the sampling rate is TOO low. It is only ~330KHz with NO command in the loop. It drops to about ~280KHz with one digitalRead and to just a few hundred Hz with a SerialPrintln(). 

What is causing it to run so slow and how can it be improved?

#include <tm4c123ge6pm.h>
#include <stdint.h>
#include <stdbool.h>
#include <pin_map.h>
#include <sysctl.h>

int db0 = PB_3;
int db1 = PC_4;
int db2 = PC_5;
int db3 = PC_6;
int db4 = PC_7;
int db5 = PD_6;
int db6 = PD_7;
int db7 = PF_4;
int cs = PB_5;
int rd = PD_1;
int wr = PD_0;
int intr = PE_4;
int out = PD_3;
int a = 0;
int count = 1;
int b;
boolean flag = 0;


void setup()
{
 SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); 
//SysCtlClockSet(SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ|SYSCTL_SYSDIV_2_5);


  pinMode(db0, INPUT); 
  pinMode(db1, INPUT);
  pinMode(db2, INPUT);
  pinMode(db3, INPUT);
  pinMode(db4, INPUT);
  pinMode(db5, INPUT);
  pinMode(db6, INPUT);
  pinMode(db7, INPUT);
  pinMode(out, OUTPUT);
  pinMode(cs, OUTPUT);
  pinMode(rd, OUTPUT);
  pinMode(wr, OUTPUT);
  pinMode(out, OUTPUT);
  pinMode(intr, INPUT);
  pinMode(db0, INPUT); 
  pinMode(db1, INPUT);
  pinMode(db2, INPUT);
  pinMode(db3, INPUT);
  pinMode(db4, INPUT);
  pinMode(db5, INPUT);
  pinMode(db6, INPUT);
  pinMode(db7, INPUT);

Serial.begin(9600);


  //Code of initialzation...
  //Step C
  digitalWrite(cs, LOW);
  delay(100);                                            //has to be type unsigned long
  digitalWrite(out,HIGH);
  b=1;
}


void loop()
{
   flag = !flag;
digitalWrite(out,flag);


a= digitalRead(db0);
   count = 1;
  a = 0;
  a = a+ digitalRead(db0)*count;
  count = count*2;


  a = a+ digitalRead(db1)*count;
  count = count*2;


  a = a+ digitalRead(db2)*count;
  count = count*2;


  a = a+ digitalRead(db3)*count;
  count = count*2;


  a = a+ digitalRead(db4)*count;
  count = count*2;


  a = a+ digitalRead(db5)*count;
  count = count*2;


  a = a+ digitalRead(db6)*count;
  count = count*2;


  a = a+ digitalRead(db7)*count;
  count = count*2;

Serial.println(a);
//Serial.println(SysCtlClockGet());
  }




 

Share this post


Link to post
Share on other sites

How to improve? Don't use any Energia function.

What sampling rate? How to do you test that if there is not a single command according to you.

Serial print is really slow. Not sure how it handles just 1 variable but still.
digitalRead is also really slow when compared to alternatives. 

Let's see the function:
 

int digitalRead(uint8_t pin)
{
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    uint32_t portBase = (uint32_t) portBASERegister(port);
    if (port == NOT_A_PORT) return LOW;
    if(ROM_GPIOPinRead(portBase, bit)){
    	return HIGH;
    }
    return LOW;
}

I would estimate your addition of 1 digital read (it seems you add some math too, not only the reading) takes about 43 cycles! If you want the full potential of the MCU capabilities, you have to be go lower and lower until you reach your desired performance.


This would be so much faster with register programming or Tivaware.
 

Share this post


Link to post
Share on other sites

Thanks for the reply. The following code was used for the same effect. But the Serial.println() was returning no value on the serial monitor. So we used a DAC to convert the bits back and see the output on an oscilloscope. There was no output at all. No hardware faults were found. 


#include <tm4c123ge6pm.h>
volatile int In = 0;  // input from PF4
int cs = PA_2; 
int rd = PA_3; 
int wr = PA_4; 

// The above pins are connected to ADC for initialization. 
#define ldata (*((volatile unsigned long *)0x400053FC))

void PortB_Init(void){ volatile unsigned long delay;
  SYSCTL_RCGC2_R |= 0x02;     // 1) activate clock for Port F
  delay = SYSCTL_RCGC2_R;           // allow time for clock to start
//  GPIO_PORTB_LOCK_R = 0x4C4F434B;   // 2) unlock GPIO Port F
//  GPIO_PORTB_CR_R = 0x1F;           // allow changes to PF4-0
  // only PF0 needs to be unlocked, other bits can't be locked
  GPIO_PORTB_AMSEL_R &= 0x00;        // 3) disable analog on PF
  GPIO_PORTB_PCTL_R &= 0x00;   // 4) PCTL GPIO on PF4-0
  GPIO_PORTB_DIR_R &= 0x00;          // 5) PF4,PF0 in, PF3-1 out
  GPIO_PORTB_AFSEL_R &= 0x00;        // 6) disable alt funct on PF7-0
  //GPIO_PORTB_PUR_R = 0x11;          // enable pull-up on PF0 and PF4
  GPIO_PORTB_DEN_R |= 0xFF;          // 7) enable digital I/O on PF4-0void setup() {
  // put your setup code here, to run once:
 
}
void PortA_Init(void){
  volatile unsigned long delay;
  SYSCTL_RCGC2_R |= 0x01;           // 1) activate clock for Port A
  delay = SYSCTL_RCGC2_R;           // allow time for clock to start
                                    // 2) no need to unlock PA2 
  GPIO_PORTA_PCTL_R &= ~0x00000F00; // 3) regular GPIO 
  GPIO_PORTA_AMSEL_R &= ~0x1C;      // 4) disable analog function on PA2 
  GPIO_PORTA_DIR_R |= 0x1C;         // 5) set direction to output 
  GPIO_PORTA_AFSEL_R &= ~0x1C;      // 6) regular port function 
  GPIO_PORTA_DEN_R |= 0x1C;         // 7) enable digital port PA2
  GPIO_PORTA_DATA_R &= 0xEF;  // wr
  GPIO_PORTA_DATA_R |= 0x10;   // wr
  GPIO_PORTA_DATA_R |= 0x08;  //rd
  GPIO_PORTA_DATA_R &= 0x07;  //rd
}

void setup()
{
  Serial.begin(9600);
  PortB_Init(); 
  digitalWrite(cs, LOW);
  delay(1000);
}

void loop()
{
  PortA_Init(); //Initialization commands in the loop. 
  
delayMicroseconds(10);
}

Share this post


Link to post
Share on other sites

That's because you are constantly initializing it, probably, maybe.

Still, you should try to use Tivaware, for at least the initialization, in the future. It will allow you for faster coding and it's easier to help you.

Why not make a simpler test first? And slower so you can analyze it better.

Share this post


Link to post
Share on other sites

Once you get this going if you need to make it even faster the Tiva C has some nice features for reading/writing GPIO pins - if you read/write from an address that is at an offset from the base port address the offset acts as a mask - so you don't have to suffer the overhead of read/modify/write, or have to mask the read value.

 

See the Tiva C documentation.  I posted some macros that help with this someplace on 43oh, (think it is in the thread about porting arduino libraries) but don't have time now to find the post.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×