exgreyfox wrote on Thursday, September 08, 2016:
Hello,
I am currently doing development on the ATSAMG55 using FreeRTOS version 8.0.1 and I have a need for changing the RTOS ticker from using to default SysTick to use the ATSAMG55’s Real Time Timer (RTT). The reason for this is due to the fact that my application requires me to use the lowest power mode that the SAMG55 has (Wait Mode) however the Systick is not a wakeup source for this mode so a new tick source (RTT) that is supported by wait mode as a wakeup source is my goal.
I have followed the instructions here on how to do this regarding “Generating a tick interrupt from a clock other than SysTick”: http://www.freertos.org/low-power-ARM-cortex-rtos.html
I have dumbed things down by keeping tickless idle mode disabled so that I can install the RTT tick interrupt and watch it run a single task that toggles an LED then blocks for x ticks without any sleep modes for now.
I have enabled the tick hook and I am toggling a pin inside vApplicationTickHook at the rate of my RTT interrupt to verify that the ticker is working and it is. I see the pin toggle. The problem that I am having however is that my task does not run. When I swap back to the SysTick ticker source my task runs fine, but it does not seem to want to run from the RTT tick interrupt.
-I have made sure to comment out the following inside FreeRTOSConfig.h so that the kernel does not install the SysTick as the default interrupt : #define xPortSysTickHandler SysTick_Handler
-I have set configTICK_RATE_HZ to 128Hz
-I have verified that my RTT handler ticks at a rate of 128Hz to match configTICK_RATE_HZ
Here is my implementation. Thank you for any help:
int main (void)
{
/* ASF function to setup clocking. */
sysclk_init();
board_init();
/* Debugging traces */
ioport_set_pin_dir(EXT1_PIN_3, IOPORT_DIR_OUTPUT); /* Task1 */
ioport_set_pin_dir(EXT1_PIN_4, IOPORT_DIR_OUTPUT); /* TickHook */
ioport_set_pin_dir(EXT1_PIN_5, IOPORT_DIR_OUTPUT); /* PreSleep PostSleep */
ioport_set_pin_dir(EXT1_PIN_6, IOPORT_DIR_OUTPUT); /* IdleHook */
ioport_set_pin_dir(EXT1_PIN_7, IOPORT_DIR_OUTPUT); /* RTT ISR */
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
configASSERT( xQueue );
xTaskCreate( prvTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, configTASK1_TASK_PRIORITY, NULL );
/* Start the scheduler running running. */
vTaskStartScheduler();
/* If all is well the next line of code will not be reached as the
scheduler will be running. If the next line is reached then it is likely
there was insufficient FreeRTOS heap available for the idle task and/or
timer task to be created. See http://www.freertos.org/a00111.html. */
for( ;; ) {
}
}
static void prvTask1( void *pvParameters )
{
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{
ioport_set_pin_level(EXT1_PIN_3, IOPORT_PIN_LEVEL_HIGH);
vTestToggleLED(mainQUEUE_LED);
delay_ms(10);
ioport_set_pin_level(EXT1_PIN_3, IOPORT_PIN_LEVEL_LOW);
vTaskDelay( task1Delay ); /* Delay 1000ms */
}
}
void vPortSetupTimerInterrupt( void )
{
rtt_write_alarm_time(RTT,0x01);
configure_rtt();
}
void vApplicationTickHook( void )
{
ioport_toggle_pin_level(EXT1_PIN_4);
}
void configure_rtt(void)
{
uint32_t ul_previous_time;
/* Configure RTT for a 128 Hz ticker */
rtt_init(RTT,256); /* us_prescalar for 128Hz RTOS tick ISR */
ul_previous_time = rtt_read_timer_value(RTT);
while (ul_previous_time == rtt_read_timer_value(RTT));
/* Enable RTT interrupt */
NVIC_DisableIRQ(RTT_IRQn);
NVIC_ClearPendingIRQ(RTT_IRQn);
NVIC_SetPriority(RTT_IRQn, 10);
NVIC_EnableIRQ(RTT_IRQn);
rtt_enable_interrupt(RTT, RTT_MR_ALMIEN);
}
void RTT_Handler(void)
{
uint32_t ul_status;
uint32_t ul_previous_time;
/* Protect incrementing the tick with an interrupt safe critical section. */
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
{
if( xTaskIncrementTick() != pdFALSE )
{
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
/* Just completely clear the interrupt mask on exit by passing 0 because
it is known that this interrupt will only ever execute with the lowest
possible interrupt priority. */
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
ioport_toggle_pin_level(EXT1_PIN_7);
/* Get RTT status */
ul_status = rtt_get_status(RTT);
rtt_write_alarm_time(RTT,0x01);
configure_rtt();
}