Машинное кодирование Arduino / Atmel328 по последовательной линии с привязанного (главного) ПК - PullRequest
0 голосов
/ 17 июня 2020

Я пытаюсь написать программу для микросхемы AVR Atmel 328 , которая позволит мне отправлять инструкции машинного кода на микросхему по последовательной линии, запускать / выполнять их на микросхеме и опрашивать результаты путем чтения памяти микросхемы и отправки содержимого обратно по последовательной линии. Это зарождение идеи: 3-инструкция Forth от Фрэнка Сержанта .

Инструкции удаленного хранения и удаленной выборки работают нормально, но у меня не удалось заставить работать инструкцию удаленного вызова (XCALL() функция). Подход, который я использовал, состоит в том, чтобы принудить 16-битный адрес к подпрограмме, преобразовав его как указатель функции.

Ниже приведен код, работающий на Arduino Nano (скомпилированный в среде Arduino IDE и загруженный с помощью кабеля USB через загрузчик).

Любое понимание будет очень признательно! (Я могу добавить дизассемблированный код, мои удаленные инструкции и c, если это поможет).

Заранее спасибо!

// Remote serial development platform for machine coding ArduinoNano/ATmel328, AKE, Jun 9, 2020

// global variables
unsigned char byt;                  // command token from host
unsigned char mem[255];             // memory window under programmatic control
unsigned char dat;                  // data byte from host
unsigned char adr_lo;               // address from host, low byte first
unsigned char adr_hi;           
unsigned short adr;                 // combined 16-bit address
typedef void (*GeneralFunction)();  // template to call memory address (as a subroutine)

void setup() {
  Serial.begin(9600);              // Turn UART serial protocol ON for comms with host PC
  Serial.write(0xFF);              // magic number to verify transmission
  Serial.write(0xFE);
  Serial.write((int) mem);         // Informs you of the writeable address space available (LSB, MSB) for tethered memory access
  Serial.write((int) mem>>8);      
}

char get_byte(void) {
    while (!(Serial.available()>0)) { delay(50); }
    return Serial.read();
}
short get_adr(void) {
    adr_lo=get_byte();
    adr_hi=get_byte();
    return ( (short)adr_hi<<8 )   |   (short)adr_lo;
}
void xstore() {             // Instruction 1 = xstore(data,adr_lo,adr_hi).  Store byte from host at indicated address in target.
    dat=get_byte();
    adr=get_adr();
    *(char *)adr=dat;
}
void xfetch() {             //  Instruction 2 = xfetch(adr_lo,adr_hi).  Read byte from target memory and return to host.
        adr=get_adr();
        dat=*(char *)adr;
        Serial.write(dat);
}
void xcall() {              //  Instruction 3 = xcall(adr_lo,adr_hi).  Execute subroutine in target memory from indicated address.
                            //  WARNING!  User must have stored RET instruction to send control back to serial monitor.
        adr=get_adr();
        GeneralFunction fGf=adr;
        fGf();
}

void loop() {
    byt = get_byte();               // user specified instruction token (1,2,3)
    if(byt == 0x01 )      { xstore(); } 
    else if (byt == 0x02) { xfetch(); } 
    else if (byt == 0x3 ) { xcall(); } // else ignore any other serial inputs
}

1 Ответ

2 голосов
/ 17 июня 2020

Вы не сообщили нам точное название вашего чипа, но я подозреваю, что вы используете ATmega328P.

ATmega328P не может выполнять инструкции из ОЗУ. Вам нужно будет выяснить, как написать код для fla sh, прежде чем вы сможете его выполнить. Вы можете использовать загрузчик, например Optiboot , чтобы написать программу для fla sh, или вы можете изучить Optiboot, чтобы увидеть, как это работает. Обратите внимание, что fla sh рассчитан только на ограниченное количество циклов стирания / записи (обычно 10000).

Кроме того, ваш синтаксис C ++ неверен. Для вызова функции всегда нужно использовать круглые скобки. Так что вы должны написать fGf(). вместо fGf.

...