I am learning FreeRTOS on a STM32F103C8T6 (on a Blue-Pill board).
I am trying to use queues and tasks.
#include <FreeRTOS.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <queue.h>
#include <task.h>
static QueueHandle_t queue;
static void
task_receive(void *args __attribute__((unused)))
{
bool nothing;
while (1)
{
if (xQueueReceive(queue, ¬hing, 10) == pdPASS)
gpio_set(GPIOC, GPIO13); // Turn off
else
taskYIELD(); // Yeld so that other taks can run
}
}
static void
task_send(void *args __attribute__((unused)))
{
bool nothing = false;
while (1)
{
gpio_clear(GPIOC, GPIO13); // Turn on
vTaskDelay(pdMS_TO_TICKS(100));
xQueueSendToBack(queue, ¬hing, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
int
main(void)
{
rcc_clock_setup_in_hse_8mhz_out_72mhz();
// Blue-Pill led
rcc_periph_clock_enable(RCC_GPIOC);
gpio_set_mode(
GPIOC,
GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL,
GPIO13);
gpio_set(GPIOC, GPIO13); // Turn off (polarity of the led is inversed!)
queue = xQueueCreate(32, sizeof(bool));
if (queue == 0)
{
while (1)
{
gpio_toggle(GPIOC, GPIO13);
for (uint32_t i = 0; i < 80000; ++i)
__asm__("nop");
};
}
xTaskCreate(task_receive, "RECEIVE", 200, NULL, configMAX_PRIORITIES-1, NULL);
xTaskCreate(task_send, "SEND", 200, NULL, configMAX_PRIORITIES-2, NULL);
vTaskStartScheduler();
while(1);
return 0;
}
Expected behavior:
main
Configures the clocks
Configures GPIO for Blue Pill LED
Turns off the led
Creates a queue
Checks the queue was correctly created: if not blink the LED fast and forever.
Schedule two tasks
Runs the scheduler
task_send (loops indefinetely)
Turn on the LED
Wait 100 ms
Push a message in the queue (content does not matter here)
Wait 1 sec
task_receive (loops indefinetely)
Check if a message is in the queue
Yes: turn off the led
No: yeld
I expect the led to be turned on for 100 ms and then turned off for 900 ms.
Real behavior: The led is always on, the execution of the program seems to be blocking at xQueueSendToBack.
Why is the call blocking?
FreeRTOSConfig.h
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 8 ) /* fix for vTaskDelay() */
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
/* 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 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
Your task_receive priority is higher than the task_send priority. taskYIELD will run the same calling task over and over again if there are no higher priority tasks.
To achieve what you want, try changing the task_receive in the following manner.
static void
task_receive(void *args __attribute__((unused)))
{
bool nothing;
while (1)
{
if (xQueueReceive(queue, ¬hing, portMAX_DELAY) == pdPASS)
gpio_set(GPIOC, GPIO13); // Turn off
}
}
For more information on taskYIELD please refer the following.
https://www.freertos.org/a00020.html#taskYIELD
The problem was solved by updating the compiler to the latest version.
Kubuntu 18.04 ships with arm-none-eabi-gcc (15:6.3.1+svn253039-1build1) 6.3.1 20170620, with this compiler the code does not work.
memcpy seems to be the problematic function call in the code, it is called by FreeRTOS when adding an element to the queue.
If I use the Version 8-2018-q4-major Linux 64-bit compiler then the code executes fine. It can be downloaded here: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
Related
I use GD32VF103C_START kit from GigaDevice and try LED blinking sample project. I found this project in the Internet and it compiles just fine (I've only changed from 500ms to 1000ms=1s).
main.c:
#include "gd32vf103.h"
#include "gd32vf103c_start.h"
#include "systick.h"
int main(void)
{
/* enable the LED clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* configure LED GPIO port */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
gpio_bit_reset(GPIOA, GPIO_PIN_7);
while(1){
/* insert 1s delay */
delay_1ms(1000);
/* toggle the LED */
gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));
/* insert 1s delay */
delay_1ms(1000);
gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));
}
}
systick.c:
#include "gd32vf103.h"
#include "systick.h"
void delay_1ms(uint32_t count)
{
uint64_t start_mtime, delta_mtime;
/* don't start measuruing until we see an mtime tick */
uint64_t tmp = get_timer_value();
do{
start_mtime = get_timer_value();
}while(start_mtime == tmp);
do{
delta_mtime = get_timer_value() - start_mtime;
}while(delta_mtime <(SystemCoreClock/4000.0 *count));
}
But instead of 1s delay it delays like for 13s. Where is mistake?
Problem is non in main.c, neither in systick.c, it's in system_gd32vf103.c.
There are:
/* system frequency define */
#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */
/* select a system clock by uncommenting the following line */
/* use IRC8M */
//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000)
/********************************************************************/
//#define __SYSTEM_CLOCK_HXTAL (HXTAL_VALUE)
//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000)
/********************************************************************/
//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000)
//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000)
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000)
#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
and you need uncomment #define __SYSTEM_CLOCK_HXTAL (HXTAL_VALUE) line. That's it.
I want to implement a simple "GPT" timer that generates an interrupt every 1ms.
However, I get an interrupt exactly every 3ms (instead of the desired 1ms).
Where is my error? What values should I set to get a 1ms timer?
Here is my calculation for the GPT timer:
EXPLANATION OF TIMER VALUES:
We take for source clock the PLL1 DIV2 400MHz
We define the root divisor at 4 => 400MHz / 4 = 100MHz
100MHz = one increment every 10ns
We want an interrupt to be generated every 1 ms
So we have :
Output_compare_value = delay_time x GPT_frequency
Output_compare_value = 1 x 10^-3 x (1/(10 x 10^-9)) = 100000
Here is my code (I change the state of a GPIO at each interrupt to check the operation of my timer on the oscilloscope):
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_gpt.h"
#include "fsl_gpio.h"
#include "fsl_common.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define GPT_IRQ_ID GPT1_IRQn
#define EXAMPLE_GPT GPT1
//#define EXAMPLE_GPT_CLK_FREQ \
// (CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootGpt1)) / \
// (CLOCK_GetRootPostDivider(kCLOCK_RootGpt1)) / 2) /* SYSTEM PLL1 DIV2 */
#define EXAMPLE_GPT_CLK_FREQ 100000
#define EXAMPLE_GPT_IRQHandler GPT1_IRQHandler
#define EXAMPLE_LED_GPIO GPIO3
#define EXAMPLE_LED_GPIO_PIN 23U
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
volatile bool gptIsrFlag = false;
/* The PIN status */
volatile bool g_pinSet = false;
/*******************************************************************************
* Code
******************************************************************************/
void EXAMPLE_GPT_IRQHandler(void)
{
/* Clear interrupt flag.*/
GPT_ClearStatusFlags(EXAMPLE_GPT, kGPT_OutputCompare1Flag);
gptIsrFlag = true;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F, Cortex-M7, Cortex-M7F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U || __CORTEX_M == 7U)
__DSB();
#endif
}
/*!
* #brief Main function
*/
int main(void)
{
uint32_t gptFreq;
gpt_config_t gptConfig;
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
/* Board pin, clock, debug console init */
/* Board specific RDC settings */
BOARD_RdcInit();
BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
BOARD_InitMemory();
CLOCK_SetRootMux(kCLOCK_RootGpt1, kCLOCK_GptRootmuxSysPll1Div2); /* Set GPT1 source to SYSTEM PLL1 DIV2 400MHZ */
CLOCK_SetRootDivider(kCLOCK_RootGpt1, 1U, 4U); /* Set root clock to 400MHZ / 4 = 100MHZ */
GPT_GetDefaultConfig(&gptConfig);
/* Initialize GPT module */
GPT_Init(EXAMPLE_GPT, &gptConfig);
/* Divide GPT clock source frequency by 3 inside GPT module */
GPT_SetClockDivider(EXAMPLE_GPT, 1);
/* Get GPT clock frequency */
gptFreq = EXAMPLE_GPT_CLK_FREQ;
/* GPT frequency is divided by 3 inside module */
gptFreq /= 1;
/* Set both GPT modules to 1 second duration */
GPT_SetOutputCompareValue(EXAMPLE_GPT, kGPT_OutputCompare_Channel1, gptFreq);
/* Enable GPT Output Compare1 interrupt */
GPT_EnableInterrupts(EXAMPLE_GPT, kGPT_OutputCompare1InterruptEnable);
/* Enable at the Interrupt */
EnableIRQ(GPT_IRQ_ID);
PRINTF("\r\nPress any key to start the example");
GETCHAR();
/* Init output LED GPIO. */
GPIO_PinInit(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, &led_config);
/* Start Timer */
PRINTF("\r\nStarting GPT timer ...");
GPT_StartTimer(EXAMPLE_GPT);
while (true)
{
/* Check whether occur interupt and toggle LED */
if (true == gptIsrFlag)
{
PRINTF("\r\n GPT interrupt is occurred !");
gptIsrFlag = false;
if (g_pinSet)
{
GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 0U);
g_pinSet = false;
}
else
{
GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 1U);
g_pinSet = true;
}
}
else
{
__WFI();
}
}
}
I found out what my problem was with the timer. The truth is that all my values were fine, but it was the execution of the logging that was taking time (line PRINTF("GPT interrupt is occurred !");) So I could have lowered my reload value even more, but I would still have the logging that was taking time to run.
I am building a simple Timer/Counter application, that generates a delay using the normal mode in Atmel's ATmega48PA, using Timer1, toggling an LED in a constant time interval. What happens is when using the interrupt, the LED toggles for a definite amount of time, then the toggling effect halts, keeping the LED always ON!
I believe there is something with the sei() function or enabling the global interrupt in SREG, as I had experienced such behavior with the same microcontroller before when using interrupts.
Here is a code snippet provided with my question, although anybody will see this code as very normal and have to be working correctly!
#include <avr/io.h>
#include <atmel_start.h>
#include <util/delay.h>
#include <math.h>
#include <clock_config.h>
#include "avr/iom48pa.h"
#define LOAD_VALUE 49911UL
#define SET_BIT( REG, BIT ) REG |= ( 1 << BIT )
#define CLR_BIT( REG, BIT ) REG &= ~( 1 << BIT )
#define TOG_BIT( REG, BIT ) REG ^= ( 1 << BIT )
void Timer16_Init( void );
void Timer16_DelayMS( unsigned short delayMS );
unsigned short delayMS = 50;
ISR( TIMER1_OVF_vect ){
Disable_global_interrupt();
TOG_BIT( PORTC, 2 );
TOG_BIT( PORTC, 3 );
TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;
Enable_global_interrupt();
}
int main( void ){
/* Initializes MCU, drivers and middle ware */
atmel_start_init();
/* configure pin 2 and pin 3 in PORTC as output */
SET_BIT( DDRC, 3 );
SET_BIT( DDRC, 2 );
Enable_global_interrupt();
Timer16_Init();
TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;
while( 1 ){
}
}
void Timer16_Init( void ){
SET_BIT( TCCR1B, CS10 );
SET_BIT( TCCR1B, CS12 );
SET_BIT( TIMSK1, TOIE1 );
}
I just want to know, what in the world happens right here ?!
Well at the first look, there is no special problem in your code. So let's check the possibilities:
First you have done some 32-bit long calculations and put the result in the 16-bit register:
TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;
it results in an unpredictable value that has been entered in the register. so I recommend you to use appropriate values or using (long) and (int) to your code to prevent data overflow.
Second You have not entered the correct data line order:
Enable_global_interrupt();
Timer16_Init();
TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;
you enabled the interrupts, then initialized the timer, and then applied the value of timer. this is incorrect since the timer runs and is able to make an interrupt, but its value has not been set yet. the order must be like this:
TCNT1 = ( ( 4194304 - delayMS ) * 1000 ) / 64;
Enable_global_interrupt();
Timer16_Init();
Third you have used the timer in normal mode, entering overflow interrupt and setting the timer value inside of interrupt routine. I highly recommend you to use the compare mode instead, since it does not require the timer value setting in the interrupt routine.
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" );
}
}
}
I am using a sensor and reading values from it. I have added uart_lite in the xilinx EDK and mapped it's pins to the boards GPIO. The PS (Zynq PS) clock is 50Mhz/100Mhz/200Mhz.
I am receiving data from the RX of UART at 115200 baud rate with 2 stop bits and even parity.
I am using the UART using the registers provided in the document. Four registers are there: ctrl_reg, stat_reg, RX_reg, TX_reg. Using these I can configure my uart to receive data and transmit data. Here is the documentation for uartlite.
Now I am receiving data in and trying to print the data on Teraterm.
Here is the code to set up the uart in correct mode and its registers.
#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
#define UART_BASE XPAR_AXI_UARTLITE_0_BASEADDR
#define RX_FIFO_REG UART_BASE + 0x00
#define TX_FIFO_REG UART_BASE + 0x04
#define STAT_REG UART_BASE + 0x08
#define CTRL_REG UART_BASE + 0x0C
// Control Register
#define ENA_INTR 27
#define RST_RXFIFO 30
#define RST_TXFIFO 31
// Control Register
// xsp module
unsigned int *pAddr;
#define RS_DXEN 0
#define RS_UART_OUI 1
#define RS_HF_OUT 2
#define RS_RXEN_BAR 3
#define RS_TE_485 4
unsigned int Setting;
// xsp module
unsigned int *pData1, *pData2, *pData3, *pData4;
unsigned int RxStat = 0;
unsigned int RxData = 0;
int main()
{
init_platform();
pAddr = XPAR_UART_IP_0_BASEADDR;
// RS485 RX Mode
Setting = ( 0<<RS_TE_485 | 0<<RS_RXEN_BAR | 1<<RS_HF_OUT | 1<<RS_UART_OUI | 0<<RS_DXEN );
// RS485 TX Mode
//Setting = ( 0<<RS_TE_485 | 1<<RS_RXEN_BAR | 1<<RS_HF_OUT | 1<<RS_UART_OUI | 1<<RS_DXEN );
*pAddr = Setting;
// Control Register
pData1 = CTRL_REG;
*pData1 = (1<<ENA_INTR)|(1<RST_RXFIFO)|(1<RST_TXFIFO);
pData2 = RX_FIFO_REG;//FIFO REG;
pData3 = STAT_REG;//STAT_REG;
pData4 = TX_FIFO_REG; // TX_FIFO_REG
while (1) {
xil_printf("success");
xil_printf("0x%X\r\n",*pData2);
}
return 0;
}
So My while loop should continuously run and print values but it stops only after printing 18 bytes??
but My output is like this:
Here is my debug try: