user56616: I'm trying to write a program for AVR Atmel 328 chip on Arduino Nano board that will allow me to send machine code instructions to the chip over a serial line, run/execute them on the chip, and interrogate the results by reading chip memory and sending the contents back over the serial line.  This is the genesis of the idea: 3-instruction Forth by Frank Sergeant.
The remote-store and remote-fetch instructions appear to be working fine, but I've not been able to get the remote-call instruction (XCALL() function) to work. The approach I've taken is to coerce a 16-bit address into a subroutine by casting it as a function pointer.
Below is the code that is running on the Arduino Nano (compiled in the Arduino IDE and uploaded using the USB cable via the bootloader)
Any insight would be greatly appreciated!  (I can add diassembled code, my remote instructions etc, if that helps).
Thanks in advance!
// 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
}


user4143: The AVR CPU cannot execute instructions from RAM. It's not a question of what the compiler can do or should be able to do, the physical chip itself cannot do it. There is simply no physical pathway between the RAM and the instruction decoder in the CPU.
Instructions can only be executed directly from Flash memory. That is how the chip works. You can only execute code that you send over serial if you first erase a page (or more) of Flash memory then burn the incoming code into that page. You can then call the start of that page's address and your code will execute.
But there is another caveat there: only code running in the bootloader flash area is allowed to modify the flash memory. That means your code can't do it, only the bootloader. That doesn't mean that the bootloader has to be running, but the code that you execute has to reside there.
There is an alternative version of the Optiboot bootloader that can provide flash writing facilities to a user program, but I have no experience using it so can't assist with that.

56616: <p>I'm trying to write a program for AVR Atmel 328 chip on Arduino Nano board that will allow me to send machine code instructions to the chip over a serial line, run/execute them on the chip, and interrogate the results by reading chip memory and sending the contents back over the serial line.  This is the genesis of the idea: <a href="http://pygmy.utoh.org/3ins4th.html" rel="nofollow noreferrer">3-instruction Forth by Frank Sergeant</a>.</p>
<p>The remote-store and remote-fetch instructions appear to be working fine, but <strong>I've not been able to get the remote-call instruction (<code>XCALL()</code> function) to work.</strong> The approach I've taken is to coerce a 16-bit address into a subroutine by casting it as a function pointer.</p>
<p>Below is the code that is running on the Arduino Nano (compiled in the Arduino IDE and uploaded using the USB cable via the bootloader)</p>
<p>Any insight would be greatly appreciated!  (I can add diassembled code, my remote instructions etc, if that helps).</p>
<p>Thanks in advance!</p>
<pre><code>// 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&gt;&gt;8);      
}

char get_byte(void) {
    while (!(Serial.available()&gt;0)) { delay(50); }
    return Serial.read();
}
short get_adr(void) {
    adr_lo=get_byte();
    adr_hi=get_byte();
    return ( (short)adr_hi&lt;&lt;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
}
</code></pre>
 4143: <p>The AVR CPU cannot execute instructions from RAM. It's not a question of what the compiler can do or should be able to do, the physical chip itself cannot do it. There is simply no physical pathway between the RAM and the instruction decoder in the CPU.</p>
<p>Instructions can <em>only</em> be executed directly from Flash memory. That is how the chip works. You can only execute code that you send over serial if you first erase a page (or more) of Flash memory then burn the incoming code into that page. You can then call the start of that page's address and your code will execute.</p>
<p>But there is another caveat there: only code running in the bootloader flash area is allowed to modify the flash memory. That means your code can't do it, only the bootloader. That doesn't mean that the bootloader has to be running, but the code that you execute has to reside there.</p>
<p>There is an alternative version of the Optiboot bootloader that can provide flash writing facilities to a user program, but I have no experience using it so can't assist with that.</p>
