Создание исходного задания на ОС Arduino - PullRequest
2 голосов
/ 29 марта 2011

Я пишу операционную систему в режиме реального времени для курса в школе. У меня много проблем с переключением контекста начального процесса (передача из ОС в процесс), поэтому я упростил задачу, чтобы попытаться выяснить, где я совершаю ошибку.

В следующем коде я пытаюсь разместить адрес test_func на указателе стека, а затем вернуть его, таким образом загружая адрес этой функции в программный счетчик. Происходит то, что плата повторно вызывает метод Arduino setup (), который повторяет весь процесс.

void test_func(void)
{
    while(1 == 1){
    digitalWrite(13,HIGH);// to let me know everything has worked
    DEBUG("test_func");
    }
} 
//...
volatile void *programcounter;
//...
programcounter = (void *)(&test_func);
asm volatile(
"lds  r26, programcounter      \n\t" \
"lds  r27, programcounter+1    \n\t" \
"ld   r28, x+                  \n\t" \
"out  __SP_L__, r28            \n\t" \
"ld   r29, x+                  \n\t" \
"out  __SP_H__, r29            \n\t" \
"ret");

Это было сделано в соответствии с примерами из руководства проекта FreeRTOS, расположенного здесь (pdf). Я пишу это в Arduino IDE как файл C. Большое спасибо за любой вклад, который у вас есть.

EDIT:

Попытка другого, более простого примера. Я смотрю на реализацию Bertos: http://dev.bertos.org/wiki/ArduinoHowto. Я начинаю со свежего эскиза:

    #include <avr/interrupt.h>
    #include <avr/io.h>

    void test_func()
    {
      while(true){
            Serial.write("Testing ...");
            digitalWrite(13, HIGH);
      }
    }

    volatile void (*tempcounter)(void);
    volatile void (**programcounter)(void);

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(13, OUTPUT);
      digitalWrite(13, LOW);

      tempcounter = (volatile void (*)())(&test_func);
      programcounter = &tempcounter;

      Serial.println("Setting up ...");

      asm volatile (
      "cli\n\t"\
    "lds  r24, programcounter      \n\t" \
    "lds  r25, programcounter+1    \n\t" \
    "movw  r26,r24\n\t"\
    "ld  r18,X+\n\t"\
    "ld  r19,X\n\t"\
    "out  __SP_L__,r18\n\t"\
    "out  __SP_H__,r19\n\t"\
    "sei\n\t"\
    "ret");
      Serial.println("This should never appear");
    }

    void loop() {
      // put your main code here, to run repeatedly: 
      Serial.println("looping");
    }

1 Ответ

2 голосов
/ 30 марта 2011

Согласно Клоусону на форуме AVR Freaks Forum , проблема заключается в неправильном понимании того, как работает ret. У меня это работает сейчас; его реализация выглядит так:

asm volatile ( 
"cli\n\t"\ 
"lds  r24, programcounter      \n\t" \ 
"lds  r25, programcounter+1    \n\t" \ 
"ldi  r18, 0x00\n\t" \ 
"ldi  r19, 0x03\n\t" \ 
"out  __SP_L__,r18\n\t"\ 
"out  __SP_H__,r19\n\t"\ 
"push r24\n\t"\ 
"push r25\n\t"\ 
"sei\n\t"\ 
"ret\n\t");
...