I am learning freeRTOS. I need to write software interrupt ISR handler in freeRTOS for PIC32 platform (cerebot Mx7ck). I went through the documentation but no help. Please somebody help.
/* sW timer */
TimerHandle_t xSysMonTimer = NULL;
xSysMonTimer = xTimerCreate("SysMonTimer",( 500 / portTICK_PERIOD_MS),pdFALSE,0,Sys_Mon_Callback);
if( xSysMonTimer == NULL )
{
/* The timer was not created. */
}
else
{
/* Start the timer. No block time is specified, and even if one was
it would be ignored because the RTOS scheduler has not yet been
started. */
if( xTimerStart( xSysMonTimer, 0 ) != pdPASS )
{
/* The timer could not be set into the Active state. */
}
}
void Sys_Mon_Callback( TimerHandle_t pxTimer )
{
if( xTimerReset( xSysMonTimer, 10 ) != pdPASS )
{
/* The reset command was not executed successfully. Take appropriate
action here. */
}
}
Are you looking for Software timer interrupts or something like SPI/I2C/UART? I have some examples of all. I don't know if what I have is exactly to what FreeRTOS would want, but it works.
Below is the UART ISR in uart.c and my isr.S files.
void vU5InterruptHandler( void );
void __attribute__( (interrupt(ipl0), vector(_UART_5_VECTOR))) vU5InterruptWrapper( void );
void vU5InterruptHandler( void )
{
/* Declared static to minimize stack use. */
static char cChar;
static portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
/* Are any Rx interrupts pending? */
if( IFS2bits.U5RXIF == 1)
{
//while( U5STAbits.URXDA )
//{
/*
** Retrieve the received character and place it in the
** queue of received characters.
*/
cChar = U5RXREG;
if(cChar != '\n')
{
xQueueSendFromISR( gps_event_queue, &cChar, &xHigherPriorityTaskWoken );
}
//}
IFS2CLR = _IFS2_U5RXIF_MASK;
}
/* Are any Tx interrupts pending? */
if( IFS2bits.U5TXIF == 1 )
{
IFS2CLR = _IFS2_U5TXIF_MASK;
}
/* If sending or receiving necessitates a context switch, then switch now. */
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
/* isr.S */
.extern vU5InterruptHandler
.global vU5InterruptWrapper
.ent vU5InterruptWrapper
vU5InterruptWrapper:
portSAVE_CONTEXT
jal vU5InterruptHandler
nop
portRESTORE_CONTEXT
.end vU5InterruptWrapper
For Demo source code you can refer to FreeRTOS/Demo/ and get the suitable one for your project
Example code of software interrupt: (main_blinky.c)
/* Standard includes. */
#include <stdio.h>
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
/* Priorities at which the tasks are created. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* The rate at which data is sent to the queue. The times are converted from
milliseconds to ticks using the pdMS_TO_TICKS() macro. */
#define mainTASK_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200UL )
#define mainTIMER_SEND_FREQUENCY_MS pdMS_TO_TICKS( 2000UL )
/* The number of items the queue can hold at once. */
#define mainQUEUE_LENGTH ( 2 )
/* The values sent to the queue receive task from the queue send task and the
queue send software timer respectively. */
#define mainVALUE_SENT_FROM_TASK ( 100UL )
#define mainVALUE_SENT_FROM_TIMER ( 200UL )
/*-----------------------------------------------------------*/
/*
* The tasks as described in the comments at the top of this file.
*/
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );
/*
* The callback function executed when the software timer expires.
*/
static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle );
/*-----------------------------------------------------------*/
/* The queue used by both tasks. */
static QueueHandle_t xQueue = NULL;
/* A software timer that is started from the tick hook. */
static TimerHandle_t xTimer = NULL;
/*-----------------------------------------------------------*/
/*** SEE THE COMMENTS AT THE TOP OF THIS FILE ***/
void main_blinky( void )
{
const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS;
printf( "Blinky Demo\n" );
esp32_init(9600);
esp32_create_tasks();
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this simple case. */
mainQUEUE_RECEIVE_TASK_PRIORITY,/* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Create the software timer, but don't start it yet. */
xTimer = xTimerCreate( "Timer", /* The text name assigned to the software timer - for debug only as it is not used by the kernel. */
xTimerPeriod, /* The period of the software timer in ticks. */
pdTRUE, /* xAutoReload is set to pdTRUE, so he timers will auto-reload themselves when they expire. */
NULL, /* The timer's ID is not used. */
prvQueueSendTimerCallback );/* The function executed when the timer expires. */
/* Start the tasks and timer running. */
xTimerStart( xTimer, 0 );
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
line will never be reached. If the following line does execute, then
there was insufficient FreeRTOS heap memory available for the idle and/or
timer tasks to be created. See the memory management section on the
FreeRTOS web site for more details. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle )
{
const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TIMER;
/* This is the software timer callback function. The software timer has a
period of two seconds and is reset each time a key is pressed. This
callback function will execute if the timer expires, which will only happen
if a key is not pressed for two seconds. */
/* Avoid compiler warnings resulting from the unused parameter. */
( void ) xTimerHandle;
/* Send to the queue - causing the queue receive task to unblock and
write out a message. This function is called from the timer/daemon task, so
must not block. Hence the block time is set to 0. */
xQueueSend( xQueue, &ulValueToSend, 0U );
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
uint32_t ulReceivedValue;
/* Prevent the compiler warning about the unused parameter. */
( void ) pvParameters;
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. It will not use any CPU time while it is in the
Blocked state. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it an expected value? Normally calling printf() from a task is not
a good idea. Here there is lots of stack space and only one task is
using console IO so it is ok. However, note the comments at the top of
this file about the risks of making Windows system calls (such as
console output) from a FreeRTOS task. */
if( ulReceivedValue == mainVALUE_SENT_FROM_TIMER )
{
printf( "Message received from software timer\r\n" );
}
else
{
printf( "Unexpected message\r\n" );
}
}
}
Related
I want to notify my task to run from an ISR. I red the RTOS docs but I could not do it. I would really appreciate if you tell me what I am supposed to do and give an example if it is possible. I used cmsis-V2.
Inside the ISR which I am sure the ISR works correctly I wrote:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM15) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
if (htim == &htim16)
{
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR(ADXL_HandlerHandle , &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/* USER CODE END Callback 1 */
}
I also used systick timer for FREE RTOS and timer 15 as the system timer . is it possible that the problem is related to this part ? I dout because task_notify_give function only add up and is not a blocking mechanism like semaphore.
and inside the thask, inside the for loop the first lines are:
ulNotifiedValue = ulTaskNotifyTake( pdFALSE, portMAX_DELAY);
if( ulNotifiedValue > 0 ){
//my codes ....
}
before for loop I defined:
uint32_t ulNotifiedValue;
but the task is not executed. even once.
I use Nucleo H755ZIQ.
before the definition of global variable, tasks are defined like this:
/* Definitions for ADXL_Handler */
osThreadId_t ADXL_HandlerHandle;
const osThreadAttr_t ADXL_Handler_attributes = {
.name = "ADXL_Handler",
.priority = (osPriority_t) osPriorityNormal,
.stack_size = 1024 * 4
};
then inside the main function initializing the schduler is as follows :
osKernelInitialize();
ADXL_HandlerHandle = osThreadNew(ADXL_Handler_TaskFun, NULL, &ADXL_Handler_attributes);
osKernelStart();
Then the timers will be started:
HAL_TIM_Base_Start_IT(&htim16);
In CMSIS there is no such a thing like task notification, I took a short look. The functions I used inside the ISR routine are from FreeRTOS. will not there a contradiction? should I use only Free RTOS task create function instead of CMSIS functions?
Thanks in advance.
I have the following code for a task that requires me to use the following code to use the Timer_A0 module in the CCS IDE to control the speeds of the motors for a robot that uses the MSP432P401R launchpad as the control unit. How do I initialize the Timer_A0 module in the C programming code below?:
#include "driverlib.h"
#include "mechrev.h"
/* Define macros and function prototypes if needed */
#define BTN1_PIN GPIO_PORT_P1,GPIO_PIN1
#define BTN2_PIN GPIO_PORT_P1,GPIO_PIN4
#define ENB1_PIN GPIO_PORT_P1,GPIO_PIN6
#define ENB2_PIN GPIO_PORT_P1,GPIO_PIN7
#define PWM1_PIN GPIO_PORT_P2,GPIO_PIN4
#define PWM2_PIN GPIO_PORT_P2,GPIO_PIN5
#define PWM3_PIN GPIO_PORT_P2,GPIO_PIN6
#define PWM4_PIN GPIO_PORT_P2,GPIO_PIN7
#define BMP0_PIN GPIO_PORT_P4,GPIO_PIN0
#define BMP7_PIN GPIO_PORT_P4,GPIO_PIN7
#define BMP2_PIN GPIO_PORT_P4,GPIO_PIN2
#define BMP6_PIN GPIO_PORT_P4,GPIO_PIN6
#define BMP3_PIN GPIO_PORT_P4,GPIO_PIN3
#define BMP5_PIN GPIO_PORT_P4,GPIO_PIN5
#define BTN3_PIN GPIO_PORT_P4, GPIO_PIN0 | GPIO_PIN7
#define BTN4_PIN GPIO_PORT_P4, GPIO_PIN2 | GPIO_PIN6
#define BTN5_PIN GPIO_PORT_P4, GPIO_PIN3 | GPIO_PIN5
/* Define configuration structs if needed */
/* Declare global variables if needed */
int i = 0;
uint32_t counter = 0;
/* Main program */
void main(void)
{
/* Stop Watchdog Timer */
WDT_A_holdTimer();
/* Call the mechrev_setup function included in the mechrev.h header file */
mechrev_setup();
/* Initialize GPIOs P1.1 and P1.4 for PushButtons (S1 and S2 switches) */
MAP_GPIO_setAsInputPinWithPullUpResistor(BTN1_PIN);
MAP_GPIO_setAsInputPinWithPullUpResistor(BTN2_PIN);
/* Initialize GPIOs P1.6 and P1.7 for Motor Driver IC Enable Pins */
MAP_GPIO_setAsOutputPin(ENB1_PIN);
MAP_GPIO_setAsOutputPin(ENB2_PIN);
/* Initialize GPIOs P2.4, P2.5, P2.6 and P2.7 for PWM functionality */
MAP_GPIO_setAsInputPin(PWM1_PIN);
MAP_GPIO_setAsInputPin(PWM2_PIN);
MAP_GPIO_setAsInputPin(PWM3_PIN);
MAP_GPIO_setAsInputPin(PWM4_PIN);
/* Initialize Timer A0 to generate PWM signals */
(Timer_A0 module needs to be initialized here)
/* Declare local variables if needed */
/* Call the initialization grading macro */
MACRO_LAB4_INIT();
while(1)
{
/* Design a Polling process to detect PushButtons press and adjust the PWM duty cycles
accordingly */
if (MAP_GPIO_getInputPinValue(BTN1_PIN) == GPIO_INPUT_PIN_LOW)
{
if(i == 1)
{
TA0CCR1 = 999;
TA0CCR2 = 0;
TA0CCR3 = 999;
TA0CCR4 = 0;
}
if(i == 2)
{
TA0CCR1 = 1998;
TA0CCR2 = 0;
TA0CCR3 = 1998;
TA0CCR4 = 0;
}
if(i == 3)
{
TA0CCR1 = 3000;
TA0CCR2 = 0;
TA0CCR3 = 3000;
TA0CCR4 = 0;
}
for (i=0; i<10000; i++); // switch debouncing
}
else if (MAP_GPIO_getInputPinValue(BTN2_PIN) == GPIO_INPUT_PIN_LOW)
{
if(i == 1)
{
TA0CCR1 = 0;
TA0CCR2 = 999;
TA0CCR3 = 0;
TA0CCR4 = 999;
}
if(i == 2)
{
TA0CCR1 = 0;
TA0CCR2 = 1998;
TA0CCR3 = 0;
TA0CCR4 = 1998;
}
if(i == 3)
{
TA0CCR1 = 0;
TA0CCR2 = 3000;
TA0CCR3 = 0;
TA0CCR4 = 3000;
}
for (i=0; i<10000; i++); // switch debouncing
}
else
{
TA0CCR1 = 0;
TA0CCR2 = 0;
TA0CCR3 = 0;
TA0CCR4 = 0;
}
/* Note: Call the event grading macro after changing PWMs */
MACRO_LAB4_EVENT();
}
}
void PORT4_IRQHandler(void)
{
/* Check the interrupt status */
uint32_t status;
status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P4);
if (status)
{
if(MAP_GPIO_getInputPinValue(BMP0_PIN) == GPIO_INPUT_PIN_LOW ||
MAP_GPIO_getInputPinValue(BMP7_PIN) == GPIO_INPUT_PIN_LOW)
{
i = 1;
counter++;
}
else if (MAP_GPIO_getInputPinValue(BMP2_PIN) == GPIO_INPUT_PIN_LOW ||
MAP_GPIO_getInputPinValue(BMP6_PIN) == GPIO_INPUT_PIN_LOW)
{
i = 2;
counter++;
}
else if (MAP_GPIO_getInputPinValue(BMP3_PIN) == GPIO_INPUT_PIN_LOW ||
MAP_GPIO_getInputPinValue(BMP5_PIN) == GPIO_INPUT_PIN_LOW)
{
i = 3;
counter++;
}
}
else
{
counter++;
}
MACRO_LAB3_EVENT();
/* Clear the PORT4 interrupt flag */
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P4, status);
}
Before you can configure the timer itself, you need to initialize a struct that you will use to configure the timer (there are slight differences in the values needed for upmode, updownmode, continuous mode). You can download the Driverlib Manual MSP432 DriverLib for MSP432 devices which contains detailed use of the timers.
Another very helpful tutorial is Interrupts, Timers & Debugging
You are mixing both Driverlib names and register-level names in your code. That's fine, just make sure you keep the nomenclature straight and don't confuse register access names with user variables, etc..
Now, to configure your timer Timer_A0, you need to initialize a structure to use configuring the time. An example for configuring the timer in up mode would be:
/* TimerA0 UpMode Configuration Parameter */
const Timer_A_UpModeConfig upConfigTA0 =
{
TIMER_A_CLOCKSOURCE_ACLK, /* ACLK Clock 32 KHz (uint_fast16_t clockSource) */
TIMER_A_CLOCKSOURCE_DIVIDER_1, /* Rollover in 1 sec (uint_fast16_t clockSourceDivider) */
ACLKMAX, /* 32767 ticks (uint_fast16_t timerPeriod) */
TIMER_A_TAIE_INTERRUPT_DISABLE, /* Rollover TAIE (uint_fast16_t timerInterruptEnable_TAIE) */
TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE, /* CCR0 CCR0IE (uint_fast16_t captureCompareInterruptEnable_CCR0_CCIE) */
TIMER_A_DO_CLEAR /* Clear Timer (uint_fast16_t timerClear) */
};
Above the timer is configured to use ACLK (32KHz), but you can use SMCLK as well.
Within your code you will need to configure the timer using the struct above. For example:
/* Configuring TimerA0 for Up Mode */
MAP_Timer_A_configureUpMode (TIMER_A0_BASE, &upConfigTA0);
You can also configure/set any additional timer interrupts you plan to use, e.g.
/* Set Capture/Compre Register 3 */
MAP_Timer_A_setCompareValue (TIMER_A0_BASE, MPUCCR, MPUCCRTICKS);
/* enable CCRn compare interrupt */
MAP_Timer_A_enableCaptureCompareInterrupt (TIMER_A0_BASE, MPUCCR);
At this point you have your timer and interrupts configured and read to use, but the timer is not yet started. Before the timer and interrupts are active, you must start the timer itself. Generally, you do this right before you enter you program loop (the while (1) { ... } loop). That way you can configure other peripherals without having your interrupts starting to fire until you complete all your configuration. After everything is configured, start the timer:
/* Starting the Timer_A0 in up mode (just before while loop) */
MAP_Timer_A_startCounter (TIMER_A0_BASE, TIMER_A_UP_MODE);
With every timer, you have two primary interrupt service routines provided by driverlib. The first handles CCR0 and is named TA0_0_IRQHandler() for Timer_A0 (or TA1_0_IRQHandler for Timer_A1, etc..)). It's declaration is:
/**
* Timer A0 CCR0 Interrupt
*/
void TA0_0_IRQHandler(void)
{
...
}
All other interrupts associated with the timer use TA0_N_IRQHandler(). For instance for capture/compare registers CCR1 - CCR5 and the TAIE rollover interrupt (one clock-cycle after CCR0). It has a declaration of
/**
* Timer A0 Interrupt Handler (remaining interrupts)
*/
void TA0_N_IRQHandler(void)
{
...
}
Since you are looking to control a robot arm, I presume you will be using the timer for PWM control. The tutorial covers that fairly well.
I placed complete example using Timer_A to driver PWM on pastebin at MSP432 PWM Control of Tri-Color LED. That shows the use of upmode to drive PWM.
DO NOT OVERLOAD THE INTERRUPT FUNCTIONS WITH FUNCTION CALLS OR COMPUTATIONALLY INTENSIVE CODE. They are effectively signal-handlers. You want to avoid time consuming processing in the ISR (Interrupt Service Request) functions. Instead, the best approach is to set a flag in the interrupt function to complete processing in your program loop, e.g.
/* Starting the Timer_A0 in up mode */
MAP_Timer_A_startCounter (TIMER_A0_BASE, TIMER_A_UP_MODE);
while (1)
{
if (btn1pressed) { /* respond to button presses by calling button handlers */
btn1_handler();
}
if (btn2pressed) {
btn2_handler();
}
if (getmpudata) { /* retrieve data from MPU9250 */
get_MPU_data();
}
if (getmagdata) { /* retrieve data from AK8963 */
get_MAG_data();
}
...
Above, each of the variable names contained in the if (...) statements are simply bool variables set in the interrupt functions that tell your program it's time to process whatever function they trigger. Processing is done in main() not in the interrupt functions. The reason being that heavy computation in the interrupt function can cause the interrupt to fire again before your processing is complete (your code takes more time than the time between interrupts). That is a sure-fire way to cause your program to crater.
The driverlib user's guide is a goldmine for configuring all the peripherals. See if you can get your timer working and look at the tutorial link I provided above. Let me know if you have further questions.
I am just trying to toggle on Board LED and listen to incoming Data from the terminal window at the same time, but the whole Loop function hangs when it reachs the fgets(), until I send something the the terminal window then it continues to loop. There must be something like "if Serial available , then start to read ?? Here is my Code, I'm new in Atmel studio
#include <asf.h>
#include <string.h>
char incomingData [256];
// /**
// * \brief Configure UART for debug message output.
// */
static void configure_console(void)
{
const usart_serial_options_t uart_serial_options = {
.baudrate = CONF_UART_BAUDRATE,
#ifdef CONF_UART_CHAR_LENGTH
.charlength = CONF_UART_CHAR_LENGTH,
#endif
.paritytype = CONF_UART_PARITY,
#ifdef CONF_UART_STOP_BITS
.stopbits = CONF_UART_STOP_BITS,
#endif
};
// /* Configure console UART. */
sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
stdio_serial_init(CONF_UART, &uart_serial_options);
}
int main (void)
{
/* Insert system clock initialization code here (sysclk_init()). */
board_init();
sysclk_init();
configure_console();
/* Insert application code here, after the board has been initialized. */
gpio_set_pin_low(LED0_GPIO);
while (1)
{
printf("Hello\r\n");
gpio_toggle_pin(LED0_GPIO);
fgets(incomingData,sizeof(incomingData),stdin);
printf("%s\r\n",incomingData);
}
}
The code below is an example of how to use the real time clock on an mcu.
My question is in relation to callbacks and function pointers.
I have included the struct declaration for rtc_config_t below.
My question is, on the line cfg.callback = rtc_example_callback
Why is the & sign not used before rtc_example_callback.
Why is not necessary to pass the arguments to rtc_example_callback?
The last struct memeber void *callback_data; is set to NULL, I don't understand what this does?
When or what would you want to return?
Many tanks for your inputs
#include "rtc.h"
#include "interrupt.h"
#include "isr.h"
#define ALARM (QM_RTC_ALARM_MINUTE / 6)
#define MAX_RTC_FIRINGS (5)
void rtc_example_callback(void *);
static volatile uint32_t rtc_fired = 0;
/* RTC app example */
int main(void)
{
/* Variables */
rtc_config_t cfg; //create a struct variable to configure the RTC
PRINTF("Starting: RTC\n");
/* Initialise RTC configuration */
cfg.init_val = 0;
cfg.alarm_en = true;
cfg.alarm_val = ALARM;
cfg.callback = rtc_example_callback;
cfg.callback_data = NULL;
irq_request(IRQ_RTC_0, rtc_isr_0); //submit the RTC to the interrupt service routine
clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); //switch on RTC and Periphal clock
rtc_set_config(RTC_0, &cfg); //Set the RTC configuration
/* Wait for RTC to fire 5 times and then finish. */
while (rtc_fired < MAX_RTC_FIRINGS) {
}
PRINTF("Finished: RTC\n");
clk_periph_disable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK); //turn off the clocks
return 0;
}
void rtc_example_callback(void *data)
{
PUTS("Alarm!!\n");
qm_rtc_set_alarm(RTC_0, (RTC[RTC_0].rtc_ccvr + ALARM));
rtc_fired++;
}
-----------------------------------------------------------------------
/**
* RTC configuration type.
*/
typedef struct {
uint32_t init_val; /**< Initial value in RTC clocks. */
bool alarm_en; /**< Alarm enable. */
uint32_t alarm_val; /**< Alarm value in RTC clocks. */
/**
* User callback.
*
* #param[in] data User defined data.
*/
void (*callback)(void *data);
void *callback_data; /**< Callback user data. */
} rtc_config_t;
name of the function is a pointer to the function
function will be called with arguments from rtc library, you are not invoking it (you cannot pass arguments here).
I guess that NULL assigned to custom_callback will not call custom method from library (default function or no function will be called), just assign NULL if you dont want to use custom callback.
usually library code looks like:
if(custom_callback)
{
custom_callback(some_parameters);
}
else
{
default_callback(some_parameters);
}
Hardware:
NXP M4 MKE14
Software:
MCUXpresso 10.1.1
Implementation of one software timer goes very well. When starting a second timer the microcontroller doesn't respond anymore. I get the error back "taskSCHEDULER_RUNNING". But if this not runs the system doesn't do anything.
I implemented the timers and one task like this:
/* Create the queue used by the queue send and queue receive tasks. */
xQueue = xQueueCreate(/* The number of items the queue can hold. */
mainQUEUE_LENGTH,
/* The size of each item the queue holds. */
sizeof(uint32_t));
xSensorTimer = xTimerCreate(/* A text name, purely to help
debugging. */
"SensorTimer",
/* The timer period, in this case
1000ms (1s). */
SENSOR_TIMER_PERIOD_MS,
/* This is a periodic timer, so
xAutoReload is set to pdTRUE. */
pdTRUE,
/* The ID is not used, so can be set
to anything. */
(void *)0,
/* The callback function */
vTimerCallback_SensorTimer);
if(xSensorTimer==NULL) {
for(;;); /*failure! */
}
xSUS_BUS_TIMEOUT_Timer = xTimerCreate(/* A text name, purely to help
debugging. */
"SUS_BUS_TIMEOUT_Timer",
/* The timer period, in this case
1000ms (1s). */
SUS_BUS_TIMEOUT_PERIOD_MS,
/* This is a periodic timer, so
xAutoReload is set to pdTRUE. */
pdFALSE,
/* The ID is not used, so can be set
to anything. */
(void *)1,
/* The callback function */
vTimerCallback_SUSBUSTIMEOUT);
if(xSUS_BUS_TIMEOUT_Timer==NULL) {
for(;;); /*failure! */
}
xTaskCreate(/* The function that implements the task. */
prvQueueModuleTask,
/* Text name for the task, just to help debugging. */
"Module",
/* The size (in words) of the stack that should be created
for the task. */
configMINIMAL_STACK_SIZE + 166,
/* A parameter that can be passed into the task. Not used
in this simple demo. */
NULL,
/* The priority to assign to the task. tskIDLE_PRIORITY
(which is 0) is the lowest priority. configMAX_PRIORITIES - 1
is the highest priority. */
mainQUEUE_MODULE_TASK_PRIORITY,
/* Used to obtain a handle to the created task. Not used in
this simple demo, so set to NULL. */
NULL);
/* Start the tasks and timers running. */
vTaskStartScheduler();
/* The program should never enter this while loop */
while(1)
{
;
}
}
static void vTimerCallback_SensorTimer (xTimerHandle pxTimer)
{
ReadTemperature();
ADCMeasurement();
}
static void vTimerCallback_SUSBUSTIMEOUT (xTimerHandle pxTimer)
{
//Reset the communication state back to the header state
}
Not sure what you mean by "got the error taskSCHEDULER_RUNNING back". When and how did you get that error?
With regards to the creating of timers; have you allocated enough heap for FreeRTOS (in your FreeRTOSConfig.h)?