Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12589 Discussions

FreeRTOS and Nios II in a Cyclone IV FPGA: the system executes the task but not responding to vTaskDelay()

MPere4
Beginner
2,739 Views

Hi. I am having trouble with a Nios II and FreeRTOS. I will post all the information I think is relevant, thank you in advance for reading and trying to help.

 

I have this board, a Cyclone IV EP4CE6E22C8N

fpga board.jpg

Ebay (https://www.aliexpress.com/item/TB276-IV-FPGA-Board-EP4CE6E22C8N-EP4CE6-Development-ALTERA-Cyclone-PLD-NiosII-Core-Board-CPLD-PLD-SOPC/32787648663.html)

 

Currently, I was able to use Qsys to generate a system with Nios II, On-chip ram, RS-232 and a few more PIO, LEDS, and so on.

 

qsys.png

 

I program the Nios II with the Eclipse IDE, creating a memory initialization file that later I upload to the On-chip memory.

 

I was able also to successfully use the timer interrupts by my own, but when I try to implement the FreeRTOS, it is not working as expected.

 

When I use this sample code in Main.c:

 

  #include <stdio.h> #include "system.h" # include "sys/alt_stdio.h"   #include "FreeRTOS.h" #include "task.h" #include "timers.h" #include "StackMacros.h"   #include "altera_avalon_pio_regs.h" #include "io.h"   #include "altera_avalon_timer_regs.h" #include "altera_avalon_timer.h" #include "sys/alt_irq.h" #include "altera_up_avalon_rs232_regs.h" #include "altera_up_avalon_rs232.h" #include "alt_types.h"     #define WRITE_FIFO_EMPTY 0x80     #include "FreeRTOS.h" #include "task.h"   #define mainTASK1_PRIORITY ( tskIDLE_PRIORITY + 2 )   void imprimir (char * cadena); void delay(int time);   static void prvPrintTask1( void *pvParameters );   int main() {   xTaskCreate( prvPrintTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, mainTASK1_PRIORITY, NULL );   vTaskStartScheduler();   while(1) { alt_irq_enabled()==0 ? IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_BASE,0x80): IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_BASE,0x80); imprimir("Main\r\n\0");   }   return 0; }     static void prvPrintTask1( void *pvParameters ) { int i=0; int count2=0; for( ;; ) { alt_irq_enabled()==0 ? IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_BASE,0x80): IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_BASE,0x80);   if(i==0) { i=2; IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_BASE,0x01); IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_BASE,0x02);   } else { i=0; IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_BASE,0x01); IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_BASE,0x02); } delay(2); vTaskDelay(1000);   } }     int k=0; int count3=0; void vApplicationIdleHook( void ) {   k ==2 ? set_bit(0x20) : clear_bit(0x20); if(k==0) k=2; else k=0;   //imprimir("IdleHook\r\n\0");   }     int l=0; void vApplicationTickHook( void ) {   alt_irq_enabled()==0 ? IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_BASE,0x80): IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_BASE,0x80); l==2 ? IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_BASE,0x04): IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_BASE,0x04); if(l==0) l=2; else l=0; delay(2);       }   void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName ) {   set_bit(0x08);   imprimir("StackOverflow\r\n\0");     }     void imprimir (char * cadena) {     int i=0,exit=0; int write_FIFO_space=0;   alt_up_rs232_dev* rs232_dev;   rs232_dev = alt_up_rs232_open_dev("/dev/rs232_0");   // open the RS232 UART port   if(rs232_dev == NULL)   { IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,0xf0); while(1); }   else { while(exit==0) { write_FIFO_space = alt_up_rs232_get_available_space_in_write_FIFO( rs232_dev); if (write_FIFO_space >= WRITE_FIFO_EMPTY) { alt_up_rs232_write_data(rs232_dev, cadena[i]); if(cadena[i]!='\0') i++; else exit=1;   } } }   } void delay(int time) { int count=0; while (count <100000*time) count++;   }

With this FreertosConfig.h

 

#ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H   #include "system.h"     #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 1 #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configCPU_CLOCK_HZ ( ( unsigned long ) SYS_CLK_FREQ ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 10 ) #define configMINIMAL_STACK_SIZE ( 128 ) #define configISR_STACK_SIZE configMINIMAL_STACK_SIZE #define configTOTAL_HEAP_SIZE ( ( size_t ) 10000 )//( ( size_t ) 8388608 ) #define configMAX_TASK_NAME_LEN ( 8 ) #define configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 0 #define configUSE_MUTEXES 0 #define configUSE_RECURSIVE_MTEXES 0 #define configUSE_COUNTING_SEMAPHORES 0 #define configCHECK_FOR_STACK_OVERFLOW 2 #define configQUEUE_REGISTRY_SIZE 0   /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )   /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */   #define INCLUDE_vTaskPrioritySet 0 #define INCLUDE_uxTaskPriorityGet 0 #define INCLUDE_vTaskDelete 0 #define INCLUDE_vTaskCleanUpResources 0 #define INCLUDE_vTaskSuspend 0 #define INCLUDE_vTaskDelayUntil 0 #define INCLUDE_vTaskDelay 1 #define INCLUDE_uxTaskGetStackHighWaterMark 0   /* The priority at which the tick interrupt runs. This should probably be kept at 1. */ #define configKERNEL_INTERRUPT_PRIORITY 0x01   /* The maximum interrupt priority from which FreeRTOS.org API functions can be called. Only API functions that end in ...FromISR() can be used within interrupts. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY 0x03   #endif /* FREERTOS_CONFIG_H */

And the Nios II port from the FreeRTOS page (this is the one I am using)

 

https://drive.google.com/file/d/1s-cwfXSmzCXlUQyTv8qg9cuDt6Mm0OLh/view?usp=sharing

 

The behavior is more or less like this:

 

-The scheduler starts, I can verify this because it never reaches below that statement, and also, the Task1 is executed.

 

-I have verified the overflow, but the StackOverflow hook is never called.

 

-The system hangs in the Task, doing it over and over again like an infinite loop without responding to vTaskDelay(). I see the Led's blinking only because of the delay.

 

-I assume it is not switching context, the Idle hook never turns on the Led, and the tick hook is not being called neither.

 

My assumption is that the interrupts are being disabled and never turned on again, because the alt_irq_enabled() is always 0, as I can see from the LED 0x80.

 

I was nos able to debug it, because when I ran the debugger, it claims that the System ID and the timestamp are not correct, so I am not able to track the code in order to find where it is getting stuck. (Could it be a Qsys interconnection problem?)

 

So, I would appreciate any clue to solve this issue.

 

Thanks again.

 

0 Kudos
6 Replies
Ahmed_H_Intel1
Employee
1,311 Views

Hi,

Please use this function as mentioned here in this link:

https://www.freertos.org/a00127.html

 

You are not following the desired definitions of the tick time.

void vTaskDelay( const TickType_t xTicksToDelay );

INCLUDE_vTaskDelay must be defined as 1 for this function to be available

 

0 Kudos
MPere4
Beginner
1,311 Views

First of all, thank you for your answer.

 

I have tested what you have mentioned, but I had to change this definition

 

const TickType_t xDelay = 500 / portTICK_PERIOD_MS;

For this one

const portTickType xDelay = 500 / portTICK_RATE_MS;

Because the re was no definition of TickType_t and portTICK_PERIOD_MS. Is it a problem?

This is my pormacro.h file where they are defined

#ifndef PORTMACRO_H #define PORTMACRO_H   #ifdef __cplusplus extern "C" { #endif   #include "sys/alt_irq.h"   /*----------------------------------------------------------- * Port specific definitions. * * The settings in this file configure FreeRTOS correctly for the * given hardware and compiler. * * These settings should not be altered. *----------------------------------------------------------- */   /* Type definitions. */ #define portCHAR char #define portFLOAT float #define portDOUBLE double #define portLONG long #define portSHORT short #define portSTACK_TYPE unsigned portLONG #define portBASE_TYPE long   #if( configUSE_16_BIT_TICKS == 1 ) typedef unsigned portSHORT portTickType; #define portMAX_DELAY ( portTickType ) 0xffff #else typedef unsigned portLONG portTickType; #define portMAX_DELAY ( portTickType ) 0xffffffff #endif /*-----------------------------------------------------------*/   /* Architecture specifics. */ #define portSTACK_GROWTH ( -1 ) #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portBYTE_ALIGNMENT 4 #define portNOP() asm volatile ( "NOP" ) #define portCRITICAL_NESTING_IN_TCB 1 /*-----------------------------------------------------------*/   extern void vTaskSwitchContext( void ); #define portYIELD() asm volatile ( "trap" ); #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()     /* Include the port_asm.S file where the Context saving/restoring is defined. */ __asm__( "\n\t.globl save_context" );   /*-----------------------------------------------------------*/   extern void vTaskEnterCritical( void ); extern void vTaskExitCritical( void );   #define portDISABLE_INTERRUPTS() alt_irq_disable_all() #define portENABLE_INTERRUPTS() alt_irq_enable_all( 0x01 ); #define portENTER_CRITICAL() vTaskEnterCritical() #define portEXIT_CRITICAL() vTaskExitCritical() /*-----------------------------------------------------------*/   /* Task function macros as described on the FreeRTOS.org WEB site. */ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )   #ifdef __cplusplus } #endif   #endif /* PORTMACRO_H */

I apologize for the indentation in freeRTOSConfig.h but the vTaskDelay wouldn't be available without this line

#define INCLUDE_vTaskDelay 1

I have tried different xDelay numbers, from 1, to 10000, but the systems keeps ignoring these pauses.

 

I want to add and correct some details of the behavior described above.

As far as I can see:

 

-The RS-232 terminal that is receiving all the messages coming out form the UART through the "imprimir" (print) function, are "T1" , "T2", "T1", "T2", so I understand that the system is inside that loop at a high speed, ignoring the vTakDelay and the delay functions.

-The 0x80 LED is on, so the interrupts are disabled

-The 0x01 and 0x02 LED's are both on at the same time, ignoring the blinking I was trying to produce with the delays functions

-The 0x04 LED is constant on too, so I can tell that the TIckHook is at least executed once, but it is not blinking, so I think the system never calls this interrupt again.

 

I do not understand why the program keeps ignoring both delays, the delay function and vTaskDelay.

 

Thank you again for your time.

Regards.

 

 

 

0 Kudos
Ahmed_H_Intel1
Employee
1,310 Views

So after changing, does everything working fine?

 

0 Kudos
MPere4
Beginner
1,310 Views

I'm sorry, but it still does not work.

 

"I do not understand why the program keeps ignoring both delays, the delay function and vTaskDelay."

 

Thank you for your time.

Regards.

0 Kudos
Ahmed_H_Intel1
Employee
1,310 Views

Hello,

First, I see you are connecting the NIOS II instruction master to all the IPs in the system. Please connect only the Data master. The Instruction master must be connected to the On-Chip memory where the code will be executed.

Then make sure all the Header libraries are appearing in the BSP with the same exact name you are calling them.

0 Kudos
Ahmed_H_Intel1
Employee
1,310 Views

Did you manage to solve the issue?

0 Kudos
Reply