I have some programming knowledge with regards to Arduino and Msp430 (using Embedded C). But, I am unable to understand where to start learning when it comes to LPC4370. I have a requirement for programming the above mentioned chip but I don't find any material that explains the various function that can be used in programming the LPC4370. LPCopen has a lot of codes but I can find out the utility of various functions used. If someone could give a hint on where to start, it would be really helpful.
Thanks in advance.
I have not worked with LPC 4370 but I have experience with lpc2148.
Few things I would suggest you :
Download LPCEXPRESSO IDE from here
Download LPCXPRESSO IDE GUIDE from here
Learn how to create projects . How to load into hardware.
Then learn to create simple task from rtos like FreeRTOS
Read this ST manual for various RTOS function
Here is sample program of creating simple task. you can refer and similarly you can read following exercises and proceed.
/*
FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
***NOTE*** The exception to the GPL is included to allow you to distribute
a combined work that includes FreeRTOS without being obliged to provide the
source code for proprietary components outside of the FreeRTOS kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
#include "FreeRTOS.h"
#include "task.h"
/* Demo includes. */
#include "basic_io.h"
/* Used as a loop counter to create a very crude delay. */
#define mainDELAY_LOOP_COUNT ( 0xfffff )
/* The task functions. */
void vTask1( void *pvParameters );
void vTask2( void *pvParameters );
int main( void )
{
/* Init the semi-hosting. */
printf( "\n" );
/* Create one of the two tasks. */
xTaskCreate( vTask1, /* Pointer to the function that implements the task. */
"Task 1", /* Text name for the task. This is to facilitate debugging only. */
240, /* Stack depth in words. */
NULL, /* We are not using the task parameter. */
1, /* This task will run at priority 1. */
NULL ); /* We are not using the task handle. */
/* Create the other task in exactly the same way. */
xTaskCreate( vTask2, "Task 2", 240, NULL, 1, NULL );
/* Start the scheduler so our tasks start executing. */
//
vTaskStartScheduler();
for( ;; );
return 0;
}
/*-----------------------------------------------------------*/
void vTask1( void *pvParameters )
{
const char *pcTaskName = "Task 1 is running\n";
volatile unsigned long ul;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
vPrintString( pcTaskName );
/* Delay for a period. */
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{
/* This loop is just a very crude delay implementation. There is
nothing to do in here. Later exercises will replace this crude
loop with a proper delay/sleep function. */
}
}
//??????delete your task
}
void vTask2( void *pvParameters )
{
const char *pcTaskName = "Task 2 is running\n";
volatile unsigned long ul;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task. */
vPrintString( pcTaskName );
/* Delay for a period. */
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{
/* This loop is just a very crude delay implementation. There is
nothing to do in here. Later exercises will replace this crude
loop with a proper delay/sleep function. */
}
}
}
/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook( void )
{
/* This function will only be called if an API call to create a task, queue
or semaphore fails because there is too little heap RAM remaining. */
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName )
{
/* This function will only be called if a task overflows its stack. Note
that stack overflow checking does slow down the context switch
implementation. */
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook( void )
{
/* This example does not use the idle hook to perform any processing. */
}
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
/* This example does not use the tick hook to perform any processing. */
}
What type of example you can practice ? it can be found here
Related
we have a C software on a i.MX53 (SO based on Linux) that have to compute a FFT; for this purpose we have adopted the FFTW library. For performances reasons we have decided to separate the FFT from the main application, using a separated thread. The overall application seems work, but after a while we have a segmentation fault in correspondence of fftwf_execute. I am sure of this because without this single istruction we have not segmentation faults. We have made several attempts but the problem persists. Here parte of the thread function:
void* vGestDiag_ThreadFFT( void* unused )
{
Int32U idx = 0, idxI = 0, idxJ = 0, idxZ = 0, idxK = 0;
Flo32 lfBufferAccm_chn01[LEN_BUFFER_SAMPLES];
Flo32 lfBufferAccm_chn02[LEN_BUFFER_SAMPLES];
Flo64 dblBufferFFT[LEN_BUFFER_SAMPLES];
Int32U ulCntUtilSample = 0;
float *in;
fftwf_complex *out;
fftwf_plan plan;
/* other variables.... */
/* Init */
memset(lfBufferAccm_chn01, 0x00, LEN_BUFFER_SAMPLES*sizeof(Flo32));
memset(lfBufferAccm_chn02, 0x00, LEN_BUFFER_SAMPLES*sizeof(Flo32));
memset(dblBufferFFT, 0x00, LEN_BUFFER_SAMPLES*sizeof(Flo64));
/* other local memsets .... */
/* Inputs */
pthread_mutex_lock(&lockIN);
ulCntUtilSample = wulCntUtilSample;
/* other inputs.... */
for (idxJ = 0; idxJ < ulCntUtilSample; idxJ++)
{
boBuffCirc_ReadBuffer(&wulBufferAcc01, &ulTmpValue);
lfBufferAccm_chn01[idxJ] = (Flo32)((((Flo32)ulTmpValue - ACC_Q)/ACC_M) * ACC_U) * wlfSensAcc;
boBuffCirc_ReadBuffer(&wulBufferAcc02, &ulTmpValue);
lfBufferAccm_chn02[idxJ] = (Flo32)((((Flo32)ulTmpValue - ACC_Q)/ACC_M) * ACC_U) * wlfSensAcc;
}
pthread_mutex_unlock(&lockIN);
/* --------- Plan FFT ------------------------- */
in = (float*) fftwf_malloc(sizeof(float) * ulCntUtilSample);
out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * ulCntUtilSample);
fftwf_plan_with_nthreads(1);
plan = fftwf_plan_dft_r2c_1d(ulCntUtilSample, in, out, FFTW_ESTIMATE);
for (idxI = 0; idxI <= 1; idxI++)
{
switch(idxI)
{
case 0:
memcpy(in, lfBufferAccm_chn01, ulCntUtilSample*sizeof(float));
break;
case 1:
memcpy(in, lfBufferAccm_chn02, ulCntUtilSample*sizeof(float));
break;
default:
break;
}
/* --------- FFT ------------------------- */
/* EXEC */
fftwf_execute(plan);
/* Complex -> Real */
for (idxZ = 0; idxZ < ulCntUtilSample; idxZ++)
{
dblBufferFFT[idxZ] = cabs(out[idxZ]);
}
/* --------- End FFT ------------------------- */
/* Post-Processing FFT */
/* post-processing and outputs in module static variables, within mutex */
}
/* DEL plan */
fftwf_destroy_plan(plan);
fftwf_free(in);
fftwf_free(out);
/* exit */
pthread_exit(NULL);
}
Variables starting with 'w' are module static variables, LEN_BUFFER is oversized respect the number of samples.
Thanks everyone for helping!!
This is my first project involving threads and also my coworkers have not a great experience, so we have not considered several issues. The first one was the difference between DETACHABLE and JOINABLE: our application have not to wait for thread completing; indeed this was the problem that lead us to thread (the main that waited a long time for FFT completing, while this was not necessary). The previous version of my SW was default, joinable, so resources allocated to the thread were never free. The second point that we have not considered was that generating a thread requires additional resources. In the previous version of my SW was generated a thread each time that FFT had to be computed; in our application this append about every 10 second or more, so apparently not critical; moreover the fastest is FFT beginning, the less data are used for FFT (is a long story, but we can summerized so); finally, the use of mutex and the logic of the algorithm apparently protected the shared resources (it was quite improbable that a shared resources was used from the threads and main at the same time). Unfortunately, the thread generation, after several cycles saturated the memory (we are working not on a PC but on a simple microprocessor....), and this was the origin of the segmentation faults, so i believe.
I have solved the problem in this way: the FFT thread is generated at the start of the application, so it is generated only a single thread, together with the main. Within the thread is an infinite loop that periodically (at the moment 4 times fastest than the main loop) check for a shared variable that indicate the request for FFT: if true, the thread read and copy locally a shared memory that cointains the FFT inputs and other required parameters. At the end of the processing, outputs are saved in a shared memory and another flag is set to indicated the main loop that a fft is available. Each shared data is accessed R/W using mutex, both within thread and main, and only data used by the thread are controlled by mutexes. The thread is generated as detachable without any kills or exits, because the thread has to live "forever" together with the main. Yesterday this SW has run for several hours without problems (i have stopped manually) and also in stress conditions.
What is the best way to create a timer with Microblaze which would allow me to have it work more similarly to a function like delay_ms() or sleep() in more conventional scripts?
Easily, I can create a stupid function like this:
void delay_ms(int i) {
//mind that I am doing this on the top of my head
for(delays=0; delay<(i*((1/frequency of the device)/2)); delays++) {
}
}
... but that would only have processor process nothing until it finishes, while in reality I need it to have the function allow me to do stop one process for a certain period of time while another one continues working.
Such thing is possible, no doubt about that, but what would the simplest solution to this problem be?
(I am using Spartan-3A, but I believe the solution would work for different kits, FPGAs as well.)
TL;DR
Use a micro OS, like FreeRTOS.
Bad answer
Well, if you have no OS, no task commutation but have an external timer, you can
use the following approach:
Enable interruption for your hardware timer, and manage a counter driven by this interrution:
You should have something like
/**timer.c**/
/* The internal counters
* each task have its counter
*/
static int s_timers[NUMBER_OF_TASKS] = {0,0};
/* on each time tick, decrease timers */
void timer_interrupt()
{
int i;
for (i = 0; i < NUMBER_OF_TASKS; ++i)
{
if (s_timer[i] > 0)
{
s_timer[i]--;
}
}
}
/* set wait counter:
* each task says how tick it want to wait
*/
void timer_set_wait(int task_num, int tick_to_wait)
{
s_timer[task_num] = tick_to_wait;
}
/**
* each task can ask if its time went out
*/
int timer_timeout(int task_num)
{
return (0 == s_timer[task_num]);
}
Once you have something like a timer (the code above is easily perfectible),
program your tasks:
/**task-1.c**/
/*TASK IDÂ must be valid and unique in s_timer */
#define TASK_1_ID 0
void task_1()
{
if (timer_timeout(TASK_1_ID))
{
/* task has wait long enough, it can run again */
/* DO TASK 1 STUFF */
printf("hello from task 1\n");
/* Ask to wait for 150 ticks */
timer_set_wait(TASK_1_ID, 150);
}
}
/**task-2.c**/
/*TASK IDÂ must be valid and unique in s_timer */
#define TASK_2_ID 1
void task_2()
{
if (timer_timeout(TASK_2_ID))
{
/* task has wait long enough, it can run again */
/* DO TASK 2 STUFF */
printf("hello from task 2\n");
/* Ask to wait for 250 ticks */
timer_set_wait(TASK_2_ID, 250);
}
}
And schedule (a big word here) the tasks:
/** main.c **/
int main()
{
/* init the program, like set up the timer interruption */
init()
/* do tasks, for ever*/
while(1)
{
task_1();
task_2();
}
return 0;
}
I think what I have described is a lame solution that should not be seriously used.
The code I gave is full of problems, like what happens if a task become to slow to execute...
Instead, you --could-- should use some RT Os, like FreeRTOS which is very helpful in this kind of problems.
I recently wrote a little curses game and as all it needs to work is some timer mechanism and a curses implementation, the idea to try building it for DOS comes kind of naturally. Curses is provided by pdcurses for DOS.
Timing is already different between POSIX and Win32, so I have defined this interface:
#ifndef CSNAKE_TICKER_H
#define CSNAKE_TICKER_H
void ticker_init(void);
void ticker_done(void);
void ticker_start(int msec);
void ticker_stop(void);
void ticker_wait(void);
#endif
The game calls ticker_init() and ticker_done() once, ticker_start() with a millisecond interval as soon as it needs ticks and ticker_wait() in its main loop to wait for the next tick.
Using the same implementation on DOS as the one for POSIX platforms, using setitimer(), didn't work. One reason was that the C lib coming with djgpp doesn't implement waitsig(). So I created a new implementation of my interface for DOS:
#undef __STRICT_ANSI__
#include <time.h>
uclock_t tick;
uclock_t nextTick;
uclock_t tickTime;
void
ticker_init(void)
{
}
void
ticker_done(void)
{
}
void
ticker_start(int msec)
{
tickTime = msec * UCLOCKS_PER_SEC / 1000;
tick = uclock();
nextTick = tick + tickTime;
}
void
ticker_stop()
{
}
void
ticker_wait(void)
{
while ((tick = uclock()) < nextTick);
nextTick = tick + tickTime;
}
This works like a charm in dosbox (I don't have a real DOS system right now). But my concern is: Is busy waiting really the best I can do on this platform? I'd like to have a solution allowing the CPU to at least save some energy.
For reference, here's the whole source.
Ok, I think I can finally answer my own question (thanks Wyzard for the helpful comment!)
The obvious solution, as there doesn't seem any library call doing this, is putting a hlt in inline assembly. Unfortunately, this crashed my program. Looking for the reason, it is because the default dpmi server used runs the program in ring 3 ... hlt is reserved to ring 0. So to use it, you have to modify the loader stub to load a dpmi server running your program in ring 0. See later.
Browsing through the docs, I came across __dpmi_yield(). If we are running in a multitasking environment (Win 3.x or 9x ...), there will already be a dpmi server provided by the operating system, and of course, in that case we want to give up our time slice while waiting instead of trying the privileged hlt.
So, putting it all together, the source for DOS now looks like this:
#undef __STRICT_ANSI__
#include <time.h>
#include <dpmi.h>
#include <errno.h>
static uclock_t nextTick;
static uclock_t tickTime;
static int haveYield;
void
ticker_init(void)
{
errno = 0;
__dpmi_yield();
haveYield = errno ? 0 : 1;
}
void
ticker_done(void)
{
}
void
ticker_start(int msec)
{
tickTime = msec * UCLOCKS_PER_SEC / 1000;
nextTick = uclock() + tickTime;
}
void
ticker_stop()
{
}
void
ticker_wait(void)
{
if (haveYield)
{
while (uclock() < nextTick) __dpmi_yield();
}
else
{
while (uclock() < nextTick) __asm__ volatile ("hlt");
}
nextTick += tickTime;
}
In order for this to work on plain DOS, the loader stub in the compiled executable must be modified like this:
<path to>/stubedit bin/csnake.exe dpmi=CWSDPR0.EXE
CWSDPR0.EXE is a dpmi server running all code in ring 0.
Still to test is whether yielding will mess with the timing when running under win 3.x / 9x. Maybe the time slices are too long, will have to check that. Update: It works great in Windows 95 with this code above.
The usage of the hlt instruction breaks compatibility with dosbox 0.74 in a weird way .. the program seems to hang forever when trying to do a blocking getch() through PDcurses. This doesn't happen however on a real MS-DOS 6.22 in virtualbox. Update: This is a bug in dosbox 0.74 that is fixed in the current SVN tree.
Given those findings, I assume this is the best way to wait "nicely" in a DOS program.
Update: It's possible to do even better by checking all available methods and picking the best one. I found a DOS idle call that should be considered as well. The strategy:
If yield is supported, use this (we are running in a multitasking environment)
If idle is supported, use this. Optionally, if we're in ring-0, do a hlt each time before calling idle, because idle is documented to return immediately when no other program is ready to run.
Otherwise, in ring-0 just use plain hlt instructions.
Busy-waiting as a last resort.
Here's a little example program (DJGPP) that tests for all possibilities:
#include <stdio.h>
#include <dpmi.h>
#include <errno.h>
static unsigned int ring;
static int
haveDosidle(void)
{
__dpmi_regs regs;
regs.x.ax = 0x1680;
__dpmi_int(0x28, ®s);
return regs.h.al ? 0 : 1;
}
int main()
{
puts("checking idle methods:");
fputs("yield (int 0x2f 0x1680): ", stdout);
errno = 0;
__dpmi_yield();
if (errno)
{
puts("not supported.");
}
else
{
puts("supported.");
}
fputs("idle (int 0x28 0x1680): ", stdout);
if (!haveDosidle())
{
puts("not supported.");
}
else
{
puts("supported.");
}
fputs("ring-0 HLT instruction: ", stdout);
__asm__ ("mov %%cs, %0\n\t"
"and $3, %0" : "=r" (ring));
if (ring)
{
printf("not supported. (running in ring-%u)\n", ring);
}
else
{
puts("supported. (running in ring-0)");
}
}
The code in my github repo reflects the changes.
I already used FreeRTOS for some embedded projects for some year time and It worked really perfectly until now. Currently i'm facing a difficult problem related to using High Speed Interrupt in FreeRTOS porting to PIC24H, hope you all can help me to though this problem. Thanks in advance
I created a small demo project for easy testing:
Two task:
// Task 1
if (xTaskCreate(RTOSTask_1, (signed char) "[T1]", configMINIMAL_STACK_SIZE2, NULL, tskIDLE_PRIORITY + 1, &hTask1) == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
{
LREP("\r\nCannot create Task 1.");
Display_Error(1000);
}
// Task 2
if (xTaskCreate(RTOSTask_2, (signed char) "[T2]", configMINIMAL_STACK_SIZE2, NULL, tskIDLE_PRIORITY + 2, &hTask2) == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
{
LREP("\r\nCannot create Task 2.");
Display_Error(1000);
}
Implementation of tasks:
void RTOSTask_1(void* pvParameter)
{
while(1)
{
if (xSemaphoreTake(hTask1Semaphore, portMAX_DELAY) == pdTRUE)
{
putchar1('1');
}
}
}
void RTOSTask_2(void* pvParameter)
{
while(1)
{
if (xSemaphoreTake(hTask2Semaphore, portMAX_DELAY) == pdTRUE)
{
putchar1('2');
}
}
}
To let above two tasks running i use one Timer & one UART to give them Semaphores:
void attribute((interrupt, auto_psv)) _T2Interrupt (void)
{
_T2IF = 0;
static signed portBASE_TYPE xTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(hTask1Semaphore, &xTaskWoken );
if( xTaskWoken != pdFALSE )
{
taskYIELD();
}
}
void attribute((interrupt, auto_psv)) _U1TXInterrupt()
{
_U1TXIF = 0;
putchar1('E');
}
void attribute((interrupt, auto_psv)) _U1RXInterrupt()
{
_U1RXIF = 0;
if(U1STAbits.URXDA == 1)
{
uint8 u8Recv = U1RXREG;
}
static signed portBASE_TYPE xTaskWoken;
xTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(hTask2Semaphore, &xTaskWoken);
if( xTaskWoken != pdFALSE )
{
taskYIELD();
}
}
My Timer interrupts in every 100us, UART working at 230400 bps baudrate speed.
After running some second or minutes the program is crashed and the program jump to Traps:
_AddressError or
_StackError
I don't know how this problem could happen. After a long investigating & testing i thought that the problem happen when the program running in & running out of the Interrupt service routine (ISR). It seems we need a couple of SAVE_CONTEXT() & RESTORE_CONTEXT() functions. but on PIC24 port there is no one like that.
Please you kindly give me some advises for this problem
Thank you all !
I already find out my problem, i think. The problem is introduced when the PIC24H gets in & gets out Interrupt Service Routines, here they are UART RX, TX, Timer Interrupts.
Currently i don't use the ISR like this:
void attribute((interrupt, auto_psv))
instead of it i created a mechanism myself with Assembly code:
__U1RXInterrupt:
; Push CPU registers in to Stack
PUSH SR
PUSH W0
PUSH W1
PUSH.D W2
PUSH.D W4
PUSH.D W6
PUSH.D W8
PUSH.D W10
PUSH.D W12
PUSH W14
PUSH RCOUNT
PUSH TBLPAG
PUSH CORCON
PUSH PSVPAG
; Call my ISR
call _UART1_RxISRHandler
; Pop out CPU registers
POP PSVPAG
POP CORCON
POP TBLPAG
POP RCOUNT
POP W14
POP.D W12
POP.D W10
POP.D W8
POP.D W6
POP.D W4
POP.D W2
POP.D W0
POP SR
retfie
UART1_RxISRHandler is my implement of ISR. I do the same with TX, Timer interrupts.
The result is that my program run more smoothly, longer 1 hour (before the program crash after 1-5 minutes only). But at the end it still crash after running 1-2 hours. That means my approach is correct but still there is something wrong. May be i miss something with above code.
If you all have any ideal for this situation, please let me know.
Thanks
I've got a similar problem.
What is the priority of your uart interrupt ?
It should not be higher than the RTOS Kernel interrupt priority set into the FreeRTOSConfig.h which has a default priority of 1 while PIC interrupt have a default priority of 3.
This seem to have caused a very occasionally crash.
The SAVE_CONTEXT() & RESTORE_CONTEXT() are not necessary with PIC as the compiler takes car of that, at least if you are using the compiler function declaration and avoid using _FASTISR or shadowing.
Try using queues.
Example for this on LPC1769. You can easily port it for your mcu.
define mainQUEUE_LENGTH ( 1 )
This will fix maximum bytes that can be stored in queue. Modify this as per your requirement and hence will immune from stack error or address error
:
#include "FreeRTOS.h"
#include "task.h"
#include "queue.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 bit of port 0 that the LPCXpresso LPC13xx LED is connected. */
#define mainLED_BIT ( 22 )
/* The rate at which data is sent to the queue, specified in milliseconds. */
#define mainQUEUE_SEND_FREQUENCY_MS ( 500 / portTICK_RATE_MS )
/* The number of items the queue can hold. This is 1 as the receive task
will remove items as they are added, meaning the send task should always find
the queue empty. */
#define mainQUEUE_LENGTH ( 1 )
/*
* The tasks as described in the accompanying PDF application note.
*/
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );
/*
* Simple function to toggle the LED on the LPCXpresso LPC17xx board.
*/
static void prvToggleLED( void );
/* The queue used by both tasks. */
static xQueueHandle xQueue = NULL;
/*-----------------------------------------------------------*/
int main(void)
{
/* Initialise P0_22 for the LED. */
LPC_PINCON->PINSEL1 &= ( ~( 3 << 12 ) );
LPC_GPIO0->FIODIR |= ( 1 << mainLED_BIT );
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the accompanying application
note. */
xTaskCreate( prvQueueReceiveTask, ( signed char * ) "Rx", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
/* Start the tasks running. */
vTaskStartScheduler();
}
/* If all is well we will never reach here as the scheduler will now be
running. If we do reach here then it is likely that there was insufficient
heap available for the idle task to be created. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvQueueSendTask( void *pvParameters )
{
portTickType xNextWakeTime;
const unsigned long ulValueToSend = 100UL;
/* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount();
for( ;; )
{
/* Place this task in the blocked state until it is time to run again.
The block state is specified in ticks, the constant used converts ticks
to ms. While in the blocked state this task will not consume any CPU
time. */
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
/* Send to the queue - causing the queue receive task to flash its LED.
0 is used as the block time so the sending operation will not block -
it shouldn't need to block as the queue should always be empty at this
point in the code. */
xQueueSend( xQueue, &ulValueToSend, 0 );
}
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it the expected value? If it is, toggle the LED. */
if( ulReceivedValue == 100UL )
{
prvToggleLED();
}
}
}
/*-----------------------------------------------------------*/
static void prvToggleLED( void )
{
unsigned long ulLEDState;
/* Obtain the current P0 state. */
ulLEDState = LPC_GPIO0->FIOPIN;
/* Turn the LED off if it was on, and on if it was off. */
LPC_GPIO0->FIOCLR = ulLEDState & ( 1 << mainLED_BIT );
LPC_GPIO0->FIOSET = ( ( ~ulLEDState ) & ( 1 << mainLED_BIT ) );
}
It might be a stack overrun.
How much stack are you allocating for each task?
Since FreeRTOS interrupt handler shares a stack with FreeRTOS task (AFAIK, there is no system stack), it can easily cause overrun when stack usage of both a task and a handler adds up.
Since any task could be running when interrupt kicks in, this leads to sporadic behavior as a task's stack usage at the point of interrupt differs.
To check it, you can simply increase stack allocation size of ALL tasks, including implicitly-created IDLE task (and other system tasks, if configured to use one). Or, you can add following to your code to catch stack overrun:
// in FreeRTOSConfig.h
#define configCHECK_FOR_STACK_OVERFLOW 1
=== somewhere in your code ===
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
// Embed assembler code to put your processor into debughalt state.
// I'm not familiar with PIC24 asm, but
//
// - http://www.microchip.com/forums/tm.aspx?m=434136
//
// may help.
MACRO_TO_DEBUG_HALT();
}
GNU libc's backtrace and In-circuit emulators/debuggers are not always available when porting code to a new platform, especially when the target is a micro C compiler such as for the Z80. (Typically a program bug would "just hang" somewhere, or crash the gadget.)
Is there an alternative to the classic "wolf fencing" method of manually inserting printf? Something simple and portable (using no C extensions) that a coder can do while developing a program that includes tracing and backtracing into a C program?
BTW: Here are a couple of other question on stackoverflow that are related, but these both use GNU GLIBC's backtrace and backtrace is often compiler/implementation specific:
Is there a function to invoke a stack dump in C?
How to generate a stacktrace when my gcc C++ app crashes
Here is the kernel of the kernel of my answer: write some code.
The kernel of my answer is: If your compiler allocates locals on the stack always, then...
Add blobs to the stack at every function entry that record the name of the function, throw in some magic numbers to maybe catch stack smashes.
typedef struct stack_debug_blob_ {
int magic1;
const char * function_name;
int magic2;
struct stack_debug_blob_ * called_by;
int magic3;
} stack_debug_blob;
stack_debug_blob * top_of_stack_debug_blobs = 0;
Create a macro ENTER(f) taking the name of the function. The macro should be about the first line of code in every function after the opening {. It adds a struct with a pointer to the (const) char * function name, a pointer to the previous struct on the stack, and maybe some magic numbers to check sanity. Make the top of blob stack pointer point at this new struct.
#define ENTER(f) \
stack_debug_blob new_stack_debug_blob = { \
MAGIC1, (f), MAGIC2, top_of_stack_debug_blobs, MAGIC3}; \
stack_debug_blob * evil_hack = (top_of_stack_debug_blobs = (&new_stack_debug_blob))
To keep things as portable as possible, all ENTER can do is declare and initialize variables. Hence the evil_hack to do a little extra computation than just initializing a variable.
Create a function to walk down the list of blobs checking pointers and magic numbers. It should signal an error (maybe print to stderr, maybe lockup the cpu with while (1) { /* nada */ }, maybe enter the debugger... depends on your hardware) if it finds things messed up.
Create a macro EXIT() that checks your stack of blobs, then de-links the topmost from the linked list. It needs to be put at the exit points of all your functions.
#define EXIT() do { \
check_debug_blobs(); \
top_of_stack_debug_blobs = new_stack_debug_blob.called_by; \
new_stack_debug_blob.magic1 -= 1; /* paranoia */ \
} while (0)
Probably will also need to replace all return's with RETURN macro calls, the RETURN macro is just like EXIT, but has a return before the } while (0).
Create a function to walk down the list of blobs printing out the function names, call it something like stacktrace or backtrace maybe.
Write a program to instrument your C code with calls to ENTER(f) and EXIT() and RETURN(x).
Left out a few details to let you have fun with it...
See also Any porting available of backtrace for uclibc?
There is an implementation at RosettaCode.org which uses the same basic idea as #jsl4tv's suggestion.
Example, given the following classic C code with built in "hang":
#include <stdio.h>
#include <stdlib.h>
void inner(int k)
{
for(;;){} /* hang */
}
void middle(int x, int y)
{
inner(x*y);
}
void outer(int a, int b, int c)
{
middle(a+b, b+c);
}
int main()
{
outer(2,3,5);
return(EXIT_SUCCESS);
}
#define STACK_TRACE_ON and #include "stack_trace.h" from RosettaCode.org then insert BEGIN(f)/ENDs where required:
#include <stdio.h>
#include <stdlib.h>
#define STACK_TRACE_ON /* compile in these "stack_trace" routines */
#include "stack_trace.h"
void inner(int k)
BEGIN(inner)
print_indent(); printf("*** Now dump the stack ***\n");
print_stack_trace();
for(;;){} /* hang */
END
void middle(int x, int y)
BEGIN(middle)
inner(x*y);
END
void outer(int a, int b, int c)
BEGIN(outer)
middle(a+b, b+c);
END
int main()
BEGIN(main)
stack_trace.on = TRUE; /* turn on runtime tracing */
outer(2,3,5);
stack_trace.on = FALSE;
RETURN(EXIT_SUCCESS);
END
Produces:
stack_trace_test.c:19: BEGIN outer[0x80487b4], stack(depth:1, size:60)
stack_trace_test.c:14: BEGIN middle[0x8048749], stack(depth:2, size:108)
stack_trace_test.c:8: BEGIN inner[0x80486d8], stack(depth:3, size:156)
stack_trace_test.c:8: *** Now dump the stack ***
stack_trace_test.c:8: inner[0x80486d8] --- stack(depth:4, size:156) ---
stack_trace_test.c:14: middle[0x8048749] --- stack(depth:3, size:108) ---
stack_trace_test.c:19: outer[0x80487b4] --- stack(depth:2, size:60) ---
stack_trace_test.c:24: main[0x804882a] --- stack(depth:1, size:0) ---
stack_trace_test.c:8: --- (depth 4) ---
A well polished [open source] version of this BEGIN ~ END method would be perfect. (Esp if it has a "FINALLY" clause for exception handling).
Hints/URLs appreciated.
on Symbian there were some scripts made to go over the registers and stack looking for things that looked like code addresses.
This is not portable, but it doesn't depend on decorating the code either. This was a necessary tradeoff on a platform where byte counts mattered... and it wasn't nearly as limited as Z80! But limited enough to compile without frame-pointers and such.
To calculate a backtrace from a stack without frame-pointers you have to work up the stack not down it.