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.

Using clock modules

Hi,

After finishing all the labs of the workshop using TM4C1294XL,  I tried to use clock module to build the first part of the lab 3 quiz.

I set the tick to 5us and set a function to run with a period of two. The problem is this function never gets called even though the swi get posted every 10us. Can anyone help me figure out what is wrong with my code?

Main:

//---------------------------------------------------------------------------------
// Project: Quiz lab 3
//
//
// Date: Jan 2016
//
//----------------------------------------------------------------------------------


//----------------------------------------
// BIOS header files
//----------------------------------------
#include <xdc/std.h>  						//mandatory - have to include first, for BIOS types
#include <ti/sysbios/BIOS.h> 				//mandatory - if you call APIs like BIOS_start()
#include <xdc/runtime/Log.h>				//needed for any Log_info() call
#include <xdc/cfg/global.h> 				//header file for statically defined objects/handles
#include <xdc/runtime/Timestamp.h>			// used for Timestamp() calls


//------------------------------------------
// TivaWare Header Files
//------------------------------------------
#include <stdint.h>
#include <stdbool.h>

#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "inc/hw_ints.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "driverlib/adc.h"
#include "driverlib/fpu.h"
#include "arm_math.h"


//----------------------------------------
// Prototypes
//----------------------------------------
void hardware_init(void);
void ledToggle(void);
void Timer_ISR(void);
void PIDSpeedCalc(void);
//void PIDPosCalc(void);
void ADSpeed(void);
//void ADPos(void);

//---------------------------------------
// Globals
//---------------------------------------
volatile int16_t i16ToggleCount = 0;
uint32_t g_ui32SysClock;
uint32_t ui32Period;
volatile float32_t speed, pos;
volatile float32_t PIDSpeed_out, PIDPos_out;

arm_pid_instance_f32 pidStructSpeed_f32;
arm_pid_instance_f32 pidStructPos_f32;


//---------------------------------------------------------------------------
// main()
//---------------------------------------------------------------------------
void main(void)
{

   hardware_init();							// init hardware via Xware

   BIOS_start();

}


//---------------------------------------------------------------------------
// hardware_init()
//---------------------------------------------------------------------------
void hardware_init(void)
{
	//Set CPU Clock
	g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
	                SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
	                SYSCTL_CFG_VCO_480), 120000000);

	// ADD Tiva-C GPIO setup - enables port, sets pins 1-3 (RGB) pins for output
	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);


	TimerControlTrigger(TIMER2_BASE, TIMER_A, true);

	GPIOPinTypeADC(GPIO_PORTA_BASE, GPIO_PIN_0|GPIO_PIN_1);

	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 0);
	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END);

	ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 0);
	ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH2|ADC_CTL_IE|ADC_CTL_END);

	ADCSequenceEnable(ADC0_BASE, 1);
	ADCSequenceEnable(ADC0_BASE, 2);


	FPULazyStackingEnable();
	FPUEnable();

	pidStructSpeed_f32.Kp = 1.00f;
	pidStructSpeed_f32.Kd = 1.00f;
	pidStructSpeed_f32.Ki = 1.00f;

	pidStructPos_f32.Kp = 1.00f;
	pidStructPos_f32.Kd = 1.00f;
	pidStructPos_f32.Ki = 1.00f;

	arm_pid_init_f32(&pidStructSpeed_f32, 1);
	arm_pid_init_f32(&pidStructPos_f32, 1);

// Timer 2 setup code
//	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);			// enable Timer 2 periph clks
//	TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);		// cfg Timer 2 mode - periodic
//
//	ui32Period = (g_ui32SysClock /2);						// period = CPU clk div 2 (500ms)
//	TimerLoadSet(TIMER2_BASE, TIMER_A, ui32Period);			// set Timer 2 period
//
//	TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);		// enables Timer 2 to interrupt CPU
//
//	TimerEnable(TIMER2_BASE, TIMER_A);

}

void ADSpeed(){

	uint32_t ui32SpeedValue;

	ADCIntClear(ADC0_BASE,1);
	while(!ADCIntStatus(ADC0_BASE,1,false)){
	}
	ADCSequenceDataGet(ADC0_BASE, 1, &ui32SpeedValue);
	speed = ((float32_t)ui32SpeedValue)/((float32_t)4096);

	Semaphore_post(SpeedSem);
}

void PIDSpeedCalc(){
	while(1){

		Semaphore_pend(SpeedSem,BIOS_WAIT_FOREVER);

		PIDSpeed_out = arm_pid_f32(&pidStructSpeed_f32,10-speed);

		Log_info1("Speed = %f.02", speed);
		Log_info1("PIDSpeed = %f.02", PIDSpeed_out);

	}
}

CFG Script:

/*
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== empty.cfg ========
 */

/* ================ General configuration ================ */
var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var Main = xdc.useModule('xdc.runtime.Main');
var Memory = xdc.useModule('xdc.runtime.Memory');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');

var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');

/*
 *  Program.stack is ignored with IAR. Use the project options in
 *  IAR Embedded Workbench to alter the system stack size.
 */
if (!Program.build.target.$name.match(/iar/)) {
    /*
     *  Reducing the system stack size (used by ISRs and Swis) to reduce
     *  RAM usage.
     */
Program.stack = 4096;
}

/* ================ System configuration ================ */
var SysMin = xdc.useModule('xdc.runtime.SysMin');
System.SupportProxy = SysMin;

/* Enable Semihosting for GNU targets to print to CCS console */
if (Program.build.target.$name.match(/gnu/)) {
    var SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');
}

/* ================ Logging configuration ================ */
var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');

/* ================ Kernel configuration ================ */
/* Use Custom library */
var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.libType = BIOS.LibType_Custom;
BIOS.logsEnabled = true;
BIOS.assertsEnabled = true;

/* ================ Driver configuration ================ */
var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
TIRTOS.useGPIO = true;
Clock.tickPeriod = 10;
Clock.timerId = 2;
var task0Params = new Task.Params();
task0Params.instance.name = "taskPIDSpeed";
task0Params.priority = 3;
Program.global.taskPIDSpeed = Task.create("&PIDSpeedCalc", task0Params);
var semaphore0Params = new Semaphore.Params();
semaphore0Params.instance.name = "SpeedSem";
Program.global.SpeedSem = Semaphore.create(0, semaphore0Params);
var semaphore1Params = new Semaphore.Params();
semaphore1Params.instance.name = "PosSem";
Program.global.PosSem = Semaphore.create(null, semaphore1Params);
LoggingSetup.sysbiosSwiLogging = true;
LoggingSetup.sysbiosSemaphoreLogging = true;
LoggingSetup.loadTaskLogging = true;
LoggingSetup.loadSwiLogging = true;
BIOS.heapSize = 0;
Clock.tickSource = Clock.TickSource_TIMER;
var clock0Params = new Clock.Params();
clock0Params.instance.name = "clock_AD";
clock0Params.period = 1;
clock0Params.startFlag = true;
Program.global.clock_AD = Clock.create("&ADSpeed", 1, clock0Params);

  • Leonardo,

    I’m not familiar with the workshop labs.  But I think the 10 us tick rate is probably too fast.  As a first step, does the test work OK if you use a slower Clock tick period, say 1000 us?

    Thanks,
    Scott

  • That really was the problem.
    That is a big issue for me actually because the system I'm developing is supposed to control a system every 10us, so I guess the RTOS will not be good for this, right?
  • Leonardo,

    Without more details I can't say whether it will work with an RTOS or not.  There are several things that can be done to address applications with high interrupt rates, including buffering data in a peripheral, or in an ISR, using DMAs, posting the buffers to a task for batch processing, carefully assigning thread priorities, etc.

    Can you provide more details about your application and its processing requirements?

    Thanks,
    Scott

  • We have a system with 5 variables to be read using the ADC, 4 PIDs to be calculated with those variables (probably using the cmsis function) and 3 PWM outputs to be changed using all the results. Since the PWMs run at 100khz we need to be able to change their values on the 10us window. 

    Parallel to that, I need to have a function that checks if the variables read with the ADC have "normal" values, if not I need to take some actions to make sure the system remains safe.

    Since the processor has 2 ADCs with 2msps rate and I can calculate a PID with less than 600ns using the arm_pid function I though that wouldn't be a problem and I wanted to use the RTOS to guarantee the correct timing synchronization, to parallel the activities and prioritize the threads accordingly.

  • Leonardo,

    OK, thanks for the additional info.  Your application has significant real-time work to do. It will probably require careful partitioning of work to the different thread contexts.  For example, maybe real-time stuff is kept only in Hwi or Swi threads.  Or you use basic ISRs versus dispatched Hwis?   And, less time critical stuff is all run in Task context, where it can be preempted as necessary.

    I don’t know if I’m helping any.  My main point is that, if it is important for other reasons for you to use an RTOS, it seems you may still be able to do that.  Hard real-time stuff is run with a mix of low-level threads with minimal latency.  And for non-critical stuff, you can still have typical RTOS benefits by running that in lower-priority task contexts.

    Regards,
    Scott

  • Thank's, Scott.

    I'm now trying to solve this problem without the rtos (using timers and usual ISRs) and I've had good results, with the entire algorithm running in about 8us.

    I'll still try to use the RTOS with your suggestions and do my best to use it, since it's much more controllable, but at least I already have an option.

    Thank you very much.

  • Leonardo,

    I'm marking the above post as "Verify Answer" to close out the thread. If you feel there is more discussion on the topic, please feel free to "Reply".

    Todd