global variable corruption on at90can128

sebamz wrote on Tuesday, November 12, 2013:

Hi,

I’m having a problem with a global variable I use in my main.c.
I use CAN_FIFO as a buffer to store measured data. When I start the debugger and the program counter is at the beginning of main, there are already values different from zero in CAN_FIFO. The amount of values already written in CAN_FIFO seems to be dependent on how many tasks I create. E.g. if I create only one task, about four values in CAN_FIFO are written and the rest can be used as intended for buffering data. If I create more tasks, there are only a few elements left in which data is stored in the course of the program.
I’m not sure whether my problem is only a compiler issue or about FreeRTOS.
Could someone please give me a few ideas on what could be the cause of this effect?

Please pardon the german comments in my code.

Best regards.

compiler: avrgcc 4.5.1 (AVR Studio 4.19)
debugger: Olimex AVR-JTAG-USB

main.c

/*

FreeRTOS V7.5.2 - Copyright © 2013 Real Time Engineers Ltd.

Changes from V4.0.5

+ Modified to demonstrate the use of co-routines.

*/

#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

/* EEPROM routines used only with the WinAVR compiler. */
#include <avr/eeprom.h>

/* Scheduler include files. */
#include “FreeRTOS.h”
#include “task.h”
//#include “croutine.h”
#include “semphr.h”

/* My file headers. */
#include “systemtasks.h”
#include “sensors.h”
#include “init.h”
#include “buffer.h”
#include “datablock.h”
#include “spi_lib.h”
#include “bma020.h”

/* Priority definitions for most of the tasks in the application. Some
tasks just use the idle priority. The higher the Value, the higher is the actual priority.*/
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainTIME_TASK_PRIORITY ( tskIDLE_PRIORITY + 2)
#define mainREADC_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainHALL_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainREAD_TEMP_ADC_PRIORITY ( tskIDLE_PRIORITY )
#define mainREAD_SPI_TEMP_PRIORITY ( tskIDLE_PRIORITY )
#define mainREAD_SPI_3DBS_PRIORITY ( tskIDLE_PRIORITY ) //die SPI-Tasks muessen gleiche Prio haben, sonst muss ein Mutex für SPI eingefuert werden!

/* Baud rate used by the serial port tasks. */
#define mainCOM_TEST_BAUD_RATE ( ( unsigned long ) 38400 )

/* Scheduler TickPeriod in ms*/
#define mainTICK_RATE_MS ( 1000/configTICK_RATE_HZ )

/* LED used by the serial port tasks. This is toggled on each character Tx,
and mainCOM_TEST_LED + 1 is toggles on each character Rx. */
#define mainCOM_TEST_LED ( 4 )

//Idle Hook Task
//void vApplicationIdleHook( void );

//Flashing of LEDs Task
//void vLEDFlashTask( void *pvParameters );

//Flashing of LEDs Co-Routine
//void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex );

//Read Port C Task
void vReadPortCTask( void *pvParameters );

//ADC Sample Battery Voltage Task
void vReadBattVolt(void * pvParameters);

//ADC Sample Intake Temperature Task
void vReadIntakeTemp(void * pvParameters);

//Incrementing of Systemtime Task
void vRefreshSystemTime( void *pvParameters );

//Read Counter 3 counting Result Task
void vReadHallPeriod( void *pvParameters );

//Read MAX6675 Temperature over SPI
void vReadSPITemp (void * pvParameters);

//Read BMA020 Acceleration
void vRead3DBS (void * pvParameters);

/-----------------------------------------------------------/

//Systemzeit
struct time_s SysTime;

//Der Datenpuffer für CAN und sein Mutex
struct Buffer CAN_FIFO = {{}, 0, 0};
xSemaphoreHandle xFIFOmutex;

//letztes Zaehlergebniss des Timer2 fuer eine Periode des Hall-Signals
volatile uint16_t HallPeriod;

/-----------------------------------------------------------/

//tritt auf, wenn Int0 ausgeloest wird
ISR(INT0_vect){
if(TOV3 == 0){ //kein Overflow aufgetreten
//Zwischenspeichern vom Timer3 Zaehlregister (=Zaehlergebnis=>Periodendauer der Radumdrehung)
HallPeriod = TCNT3;
//Reset Timer3 Zaehlregister
}
else{ //Overflow aufgetreten
HallPeriod = 0xFFFF; //Ergebnis soll Maximalwert sein =>langsamste messbare Raddrehzahl
TIFR3 &= ~(1 << TOV3); //Overflow-Flag loeschen
}
TCNT3 = 0; //Zaehlergebnis zuruecksetzen
}

/-----------------------------------------------------------/
int main( void )
{
//Test für Debugging
CAN_FIFO.data[0]=11;
CAN_FIFO.data[1]=11;
CAN_FIFO.data[2]=11;
CAN_FIFO.data[3]=31;
CAN_FIFO.data[4]=111;
CAN_FIFO.data[5]=11;
CAN_FIFO.data[10]=12;
CAN_FIFO.data[14]=13;
CAN_FIFO.data[15]=34;
CAN_FIFO.data[20]=99;
//Mutex für CAN_FIFO erstellen, damit nicht mehrere Tasks gleichzeitig auf CAN_FIFO zugreifen können
xFIFOmutex = xSemaphoreCreateMutex();

<span style="color: #408080; font-style: italic">//Initialisierungen</span>
vIO_Init();
vInitExtInt0();
vInitTimer3();
<span style="color: #408080; font-style: italic">//Reihenfolge wichtig!</span>
vInitSPI_SS ();
spi_init((<span style="color: #B00040">uint8_t</span>)(SPI_MASTER<span style="color: #666666">|</span>SPI_MSB_FIRST<span style="color: #666666">|</span>SPI_DATA_MODE_0<span style="color: #666666">|</span>SPI_CLKIO_BY_16));
vInit3DBS();
<span style="color: #408080; font-style: italic">//Reihenfolge wichtig!</span>

<span style="color: #408080; font-style: italic">//Create Tasks</span>
<span style="color: #408080; font-style: italic">// xTaskCreate (task function name, task name (choose freely), stack size, pointer to task parameters, task priority, pass back handle by reference)</span>

<span style="color: #408080; font-style: italic">//xTaskCreate( vLEDFlashTask, ( signed char * ) &quot;LED&quot;, configMINIMAL_STACK_SIZE, NULL, mainLED_TASK_PRIORITY, NULL );</span>
xTaskCreate ( vRefreshSystemTime, ( <span style="color: #B00040">signed</span> <span style="color: #B00040">char</span> <span style="color: #666666">*</span> ) <span style="color: #BA2121">&quot;SYSTIME&quot;</span>, configMINIMAL_STACK_SIZE, ( <span style="color: #B00040">void</span> <span style="color: #666666">*</span> ) <span style="color: #666666">&amp;</span>SysTime, mainTIME_TASK_PRIORITY, <span style="color: #008000">NULL</span>);
xTaskCreate ( vReadPortCTask, ( <span style="color: #B00040">signed</span> <span style="color: #B00040">char</span> <span style="color: #666666">*</span> ) <span style="color: #BA2121">&quot;READC&quot;</span>, configMINIMAL_STACK_SIZE, <span style="color: #008000">NULL</span>, mainREADC_TASK_PRIORITY, <span style="color: #008000">NULL</span>);
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadBattVolt, ( signed char * ) &quot;ADCBATT&quot;, configMINIMAL_STACK_SIZE, NULL, mainREAD_TEMP_ADC_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadIntakeTemp, ( signed char * ) &quot;INTEMP&quot;, configMINIMAL_STACK_SIZE, NULL, mainREAD_TEMP_ADC_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadHallPeriod, ( signed char * ) &quot;HALL&quot;, configMINIMAL_STACK_SIZE, NULL, mainHALL_TASK_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadSPITemp, ( signed char * ) &quot;ET1&quot;, configMINIMAL_STACK_SIZE, ( void * ) SS0, mainREAD_SPI_TEMP_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadSPITemp, ( signed char * ) &quot;ET2&quot;, configMINIMAL_STACK_SIZE, ( void * ) SS1, mainREAD_SPI_TEMP_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadSPITemp, ( signed char * ) &quot;ET3&quot;, configMINIMAL_STACK_SIZE, ( void * ) SS2, mainREAD_SPI_TEMP_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vReadSPITemp, ( signed char * ) &quot;ET4&quot;, configMINIMAL_STACK_SIZE, ( void * ) SS3, mainREAD_SPI_TEMP_PRIORITY, NULL);</span>
<span style="color: #408080; font-style: italic">//xTaskCreate ( vRead3DBS, ( signed char * ) &quot;3DBS&quot;, configMINIMAL_STACK_SIZE, NULL, mainREAD_SPI_3DBS_PRIORITY, NULL);</span>


<span style="color: #408080; font-style: italic">//Create Co-Routines</span>
<span style="color: #408080; font-style: italic">//xCoRoutineCreate (co-routine name, co-routine priority, index)</span>
<span style="color: #408080; font-style: italic">//xCoRoutineCreate( vFlashCoRoutine, 0, 0 );</span>

HallPeriod <span style="color: #666666">=</span> <span style="color: #666666">0xFFFF</span>;		<span style="color: #408080; font-style: italic">//Maximalwert =&gt;langsamste messbare Raddrehzahl</span>
sei();
vTaskStartScheduler();


<span style="color: #008000; font-weight: bold">while</span> (<span style="color: #666666">1</span>){};
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">0</span>;

}//int main( void )

/-----------------------------------------------------------/
//Implementation of tasks
//…

rtel wrote on Tuesday, November 12, 2013:

If this happens before you have started the scheduler then I doubt it is an RTOS problem, and is most likely a simple linker script problem.

When you create a task FreeRTOS will call pvPortMalloc() to allocate some RAM. Where that RAM comes from is dependent on which memory allocator you have included in your project. http://www.freertos.org/a00111.html

Are you using heap_1.c, heap_2.c or heap_4.c? If so then the RAM will come from a statically allocated array, and if writing to that array is also writing into your CAN buffer then there is a problem with the memory map/linker script. You can configure a malloc() failed hook function with these to trap running out of memory in the static array.

If instead you are using heap_3.c then the memory will come from the heap as allocated by GCC when the standard GCC malloc() is called. In this case your build files must allocate a heap that is large enough. Often with GCC an overflowed heap is not detectable.

Your code does not show what a struct Buffer type is. Are you sure it is itself actually allocating a buffer and not just a pointer to a buffer that you should be allocating yourself?

Regards.

sebamz wrote on Tuesday, November 12, 2013:

Hi Richard,

thank you for the fast response. I’m using heap_2.c and in my settings heap size for tasks should be way enough for about ten tasks.

#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 85 )

#define configTOTAL_HEAP_SIZE ( (size_t ) ( 3500 ) )

this is struct Buffer defined in buffer.h

struct Buffer {

uint16_t data[BUFFER_SIZE];
uint8_t read;
uint8_t write;
};

You’re right, I’m not sure if I’m introducing CAN_FIFO the right way (in this case I don’t really know what I’m doing, which is bad…).
I’ll try to force the compiler to allocate memory for CAN_FIFO before allocating memory for other purposes.

Best regards.