mega8 using OSA rtos , writes to undefined memory

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a strange issue.
Below is a minimal example that reproduces the problem, it uses OSA rtos http://www.pic24.ru/doku.php/en/... with just two tasks.

#include 
#include 
#include 


/*  // this works
uint8_t myarray[16]="000000";

#define S1 myarray[0]
#define S2 myarray[1]
#define M1 myarray[2]
#define M2 myarray[3]
#define H1 myarray[4]
#define H2 myarray[5]
*/

// this doesn't work
uint8_t myarray[16]="00:00:00";

#define S1 myarray[0]
#define S2 myarray[1]
#define M1 myarray[3]
#define M2 myarray[4]
#define H1 myarray[6]
#define H2 myarray[7]

// Timer 1 output compare A interrupt service routine
ISR(TIMER1_COMPA_vect)
{
    // Place your code here
    OS_Timer();
}

void Task1(void)
{
    while(1)
    {		
        myarray[0]++;   // increment seconds

        if(S1 == ':') // : is the next ASCII char after 9
        {
            S2++;   // increase sec decade
            S1 = '0';
        }

        if(S2 == '6')
        {
            M1++; // increase minutes, this is where the error 
                     happens when the counter reaches "06:00:00"
            S2 = '0';
        }

        if(M1 == ':')
        {
            M2++; // increase minute decade
            M1 = '0';
        }

        if(M2 == '6')
        {
            H1++; // increase hour
            M2 = '0';
        }

        if(H1== ':')
        {
            H2++; // increase minute decade
            H1 = '0';
        }

        OS_Delay(1);  // delay for 1 tick (1ms for this example)
    };
}


void Task2(void)
{
    while(1)
    {
        OS_Yield();
    };
}


int main(void)
{
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 8000,000 kHz
    // Mode: CTC top=OCR1A
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer 1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: On
    // Compare B Match Interrupt: Off
    TCCR1A = 0x00;
    TCCR1B = 0x09;
    TCNT1H = 0x00;
    TCNT1L = 0x00;
    ICR1H = 0x00;
    ICR1L = 0x00;
    OCR1A = 8000;    // 1ms @8MHz
    OCR1BH = 0x00;
    OCR1BL = 0x00;


    OS_Init();                   // Init OS
    OS_Task_Create(0, Task1);    // Create tasks.
    OS_Task_Create(0, Task2);
    OS_EI();                     // Enable interrupts
    OS_Run();                    // Running scheduler
}

The first task writes to a global array in order to keep time and at 60 sec (06:00:00) when it tries to increment the minutes (00:10:00) it writes to invalid memory location 0x4800

I'm attaching the images from avr studio simulator (right click and select view image for full size)

I also noticed that when I try the same code using the following format (ssmmhh) it works fine

/*  // this works
uint8_t myarray[16]="000000";

#define S1 myarray[0]
#define S2 myarray[1]
#define M1 myarray[2]
#define M2 myarray[3]
#define H1 myarray[4]
#define H2 myarray[5]
*/

but when I use the following format "ss:mm:hh" I get the memory error

// this doesn't work
uint8_t myarray[16]="00:00:00";

#define S1 myarray[0]
#define S2 myarray[1]
#define M1 myarray[3]
#define M2 myarray[4]
#define H1 myarray[6]
#define H2 myarray[7]

I have also tried without defines (myarray[0] instead of S1...) but the problem remains, it is not a define problem.

I also tried with different optimization levels and here are the results

opt.level           000000            00:00:00
O0                    ok                ok
O1                  no count         no count
O2                    ok            no count
O3                    ok          memory error
Os                    ok          memory error

Does anyone have an explanation why this can be happening?
I'm using latest winavr 20100110.

Thank you
Alex

Attachment(s): 

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The difference between this:

uint8_t myarray[16]="000000";

and this:

uint8_t myarray[16]="00:00:00";

may be the way .data is initialised. What is the avr-objcopy command you are using?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi
Thank you for your reply.

I'm using an AVR studio project with default options, I'm attaching an image.

This is the project make file

###############################################################################
# Makefile for the project test_osa_1
###############################################################################

## General Flags
PROJECT = test_osa_1
MCU = atmega8
TARGET = test_osa_1.elf
CC = avr-gcc

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -std=gnu99     -DF_CPU=8000000UL -O0 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d 

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Wl,-Map=test_osa_1.map


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings


## Include Directories
INCLUDES = -I"C:\projects\test_osa_array\..\..\osa" -I"C:\projects\test_osa_array\." 

## Objects that must be built in order to link
OBJECTS = test_osa_1.o osa.o 

## Objects explicitly added by the user
LINKONLYOBJECTS = 

## Build
all: $(TARGET) test_osa_1.hex test_osa_1.eep test_osa_1.lss size

## Compile
test_osa_1.o: ../test_osa_1.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

osa.o: ../../../osa/osa.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

##Link
$(TARGET): $(OBJECTS)
	 $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
	avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
	-avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET)
	avr-objdump -h -S $< > $@

size: ${TARGET}
	@echo
	@avr-size -C --mcu=${MCU} ${TARGET}

## Clean target
.PHONY: clean
clean:
	-rm -rf $(OBJECTS) test_osa_1.elf dep/* test_osa_1.hex test_osa_1.eep test_osa_1.lss test_osa_1.map


## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)


I'm also attaching an image of how the assembly code looks for the no optimized compile (O0) that works fine.

Alex

Attachment(s): 

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is an image of the RAM for the Os optimization setting (that doesn't work)

Attachment(s): 

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Below is a minimal example that reproduces the problem,
Really?
In your screen shots the names are different and (more important) a stack frame is involved (the faulty pointer is read from there). In your "minimal example" I don't see any reason for a stack frame (like local variables).

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To make sure that there wasn't a conflict with the defines I have added the prefix alex in all of them at one point so S1 became alexS1, S2 became alexS2 etc. so in the first images you will see alexS1 and in the last one S1 because I reverted the names back, the rest of the code is the same.
After that I also tried using the array directly instead of defines but I got same result.
The assembly images in all case are from the code I have provided.

I have no variable in the code apart from the array so I guess what you refer to is caused by the RTOS kernel.

Alex

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As this appears to be a trivial example can you not just Zip up a complete project that shows the effect? Then explain exactly what we must do to see the same thing happen ourselves?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alexan_e wrote:
I have no variable in the code apart from the array so I guess what you refer to is caused by the RTOS kernel.
Very unlikely (how could the kernel influence what code is generated by the compiler?).

I tried your code (without OSA) and it looks like the compiler generates a stack frame for "internal" temporary variables with -O1. But only with -O1, so now I have some doubts regarding this:

opt.level           000000            00:00:00
O0                    ok                ok
O1                  no count         no count
O2                    ok            no count
O3                    ok          memory error
Os                    ok          memory error 

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm attaching the project.

I have included the osa folder in the project directory and the included project directories are already set so it should run without a need to download anything else.
I'm using the latest version of OSA 110306, AVR studio 4.18 b716 with winavr 20100110

In order to see the problem I use a breakpoint in the first line of task1 myarray[0]++; and run the code until I reach '95' (myarray[0]=='9' and myarray[1]=='5').

Then I open the disassemble window and the error is shown when the execution reaches M1++;

Alex

Attachment(s): 

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

Last Edited: Wed. Nov 7, 2012 - 02:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A faster method would be to replace if(S2 == '6') with if(S2 == '1'), then you just need to reach myarray[0]=='9' and see the M1++ execution

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd like to post some additional info because my friend bigdogguru managed to find an article that describes the problem.
The article (written by the author of OSA) is in Russian so the link I'm including is the English translation.

http://translate.google.com/tran...

The author has used the following code to demonstrate the problem and has a detailed explanation for the problem in the article

# Include 
# Include 
# Include 

// ************************************************ ******************************
// Variables
// ************************************************ ******************************

char Hello [6] // Buffer to store the word "HELLO"
char World [6] // Buffer to store the word "WORLD"


jmp_buf j_task1, j_task2; // task context


// ************************************************ ******************************
// Function Prototypes
// ************************************************ ******************************

void task1 (void);
void task2 (void);
void strcpy_hello (char * data) __ attribute__ ((noinline));
void strcpy_world (char * data) __ attribute__ ((noinline));

// ************************************************ ******************************
// Functions
// ************************************************ ******************************


void main (void)
{
    task1 (); // Initialize the task
    task2 ();

    longjmp (j_task1, 1) // Start queued execution,
                            // From problem Taks1
}

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

void strcpy_hello (char * str) // copy a word "HELLO" in str
{
    str [0] = 'H';
    str [1] = 'E';
    str [2] = 'L';
    str [3] = 'L';
    str [4] = 'O';
    str [5] = 0;
}

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

void strcpy_world (char * str) // copy a word "WORLD" in str
{
    str [0] = 'W';
    str [1] = 'O';
    str [2] = 'R';
    str [3] = 'L';
    str [4] = 'D';
    str [5] = 0;
}

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

void task1 (void) // TASK 1
{
    if (! setjmp (j_task1)) return; // Initialize the context

    for (; ;)
    {
        Hello [1] ^ = Hello [0] // Address to the two elements of the array
                                                    // Read and write
        if (! setjmp (j_task1)) longjmp (j_task2, 1) // Context Switching
        strcpy_hello (Hello); // Copy the constant "HELLO" to the array
    }
}

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

void task2 (void) // TASK 2
{
    if (! setjmp (j_task2)) return; // Initialize the context

    for (; ;)
    {
        World [1] ^ = World [0] // Address to the two elements of the array
                                                    // Read and write
        if (! setjmp (j_task2)) longjmp (j_task1, 1) // Context Switching
        strcpy_world (World); // Copy the constant "WORLD" to the array
    }
}

He also provides a link to the sample project with this code for AVRstudio http://www.pic24.ru/lib/exe/fetc...

Unfortunately the only workaround he found is to turn off the compiler optimization :(

It would be great if someone with a deeper knowledge of the compiler could come up with a solution, apparently this problem happens only in winavr and not in IAR or codevision.

Alex

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The translation doesn't show the code tags correctly (at least in my firefox) so in case you can't see the assembly code provided in the article it is the following

000000c2 :
}

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

void task1 (void) / / TASK 1
{
  c2: df 93 push r29
  c4: cf 93 push r28
  c6: 00 d0 rcall. +0
  c8: cd b7 in r28, SPL
  ca: de b7 in r29, SPH

  cc: 80 e6 ldi r24, 0x60; if (! setjmp (j_task1)) return;
  ce: 90 e0 ldi r25, 0x00
  d0: 28 d0 rcall setjmp
  d2: 89 2b or r24, r25
  d4: 29 f4 brne. +10

  d6: 0f 90 pop r0
  d8: 0f 90 pop r0
  da: cf 91 pop r28
  dc: df 91 pop r29
  de: 08 95 ret

                                                ; For (; ;)
                                                , {
  e0: 8d e7 ldi r24, 0x7D; Note: 0x7D - variable address Hello
  e2: 90 e0 ldi r25, 0x00;
  e4: 89 83 std Y +1, r24;
  e6: 9a 83 std Y +2, r25;
  e8: 03 c0 rjmp. +6;

  ea: 89 81 ldd r24, Y +1; strcpy_hello (Hello);
  ec: 9a 81 ldd r25, Y +2;
  ee: a5 df rcall strcpy_hello;

  f0: ed e7 ldi r30, 0x7D; Hello [1] ^ = Hello [0];
  f2: f0 e0 ldi r31, 0x00;
  f4: 80 81 ld r24, Z
  f6: ee e7 ldi r30, 0x7E;
  f8: f0 e0 ldi r31, 0x00;
  fa: 90 81 ld r25, Z
  fc: 89 27 eor r24, r25
  fe: 80 83 st Z, r24


 100: 80 e6 ldi r24, 0x60; if (! Setjmp (j_task1))
 102: 90 e0 ldi r25, 0x00;
 104: 0e d0 rcall setjmp;
 106: 89 2b or r24, r25
 108: 81 f7 brne 0xEA

 10a: 83 e8 ldi r24, 0x83; longjmp (j_task2, 1);
 10c: 90 e0 ldi r25, 0x00;
 10e: 61 e0 ldi r22, 0x01;
 110: 70 e0 ldi r23, 0x00;
 112: 28 d0 rcall longjmp;

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
It would be great if someone with a deeper knowledge of the compiler could come up with a solution, apparently this problem happens only in winavr and not in IAR or codevision.
The generating of the stack frame for temporary variables is obviously dependent on the optimization level, so very likely there is a specific optimization option responsible for that (and switching that off would resolve the problem). But there are tons of optimization options and I have no idea which one it could be. At first I would simply try a newer avr-gcc.

Stefan Ernst