AMP with Raspberry Pi: 6502 emulation

This is an example of "Asymmetric Multi Processing (AMP) with Raspberry Pi"
Previous steps involved are datiled in the series of articles
"AMP with Raspberry Pi: Cookbook".

Based on previous work with 6502 emulation an AMP example app was developed:
AMP on Linux GUI (Raspbian)
A remote process (bare-metal) runs a 6502 emulator (fake6502) with a Basic Interpreter (EhBASIC), using two (shared) memory locations for data exchange, one as (keyboard) input for basic interpreter and one for (monitor) output.
One local process (Linux)  send keystrokes to a shared memory location (remote keyboard)
Second local process (Linux)  show Ascii data comming to the other shared memory location (remote monitor)
The process run asyncronously and the IPC (inter process comunication) is imperfect, as no signaling was implemented.



In order to get the example working you need:
AMP framework: (the same as previous posts) Linux on Cores 0,1,2 using lower RAM and Bare Metal on Core 3 using upper RAM (above 0x20000000). See Step 1 for details.

Get example files from git:
git clone https://github.com/telmomoya/AMP

Enough Linux privileges

In a Linux terminal do
cd /bare-metal
./start-metal.sh
cd ..
./monitor6510-char 0x20002ed1

This will start the bare-metal process and the Linux process for monitor basic output.

Keep that terminal open and in another one type:
./keyboard6510-char 0x200058d4

Test the EhBASIC interpeter (answer only "enter" for Memory size)

You can stop emulator with
./stop-metal.sh

And restart it ( again with  ./start-metal.sh) so you have LCM.
If you start ehbasic with Warm option you can list your previous "sesion" basic program, as it remained in memory.

Using bare-metal app via ssh


Under the hood

In bare-metal folder you will find 3 scripts:

start-metal.sh
This script can be used for load the img file (up-metal-6510.img) at 0x2000000 (upper 512Mb) and point Core3 Mailbox3 to that address to start it's execution.

stop-metal.sh
This script stops bare-metal execution

build-up-metal.sh
Used for bare-metal compilation & linking (uses rpi.x linker script)

In root folder you have two files for local (Linux) run.

keyboard6510-char
Waits one text line and sends characters to remote process (bare-metal)

monitor6510-char
Looks to mailbox variable physical address and print if value changes (no signaling implemented, must be improved)


Life control managment
When Linux boots puts all unused cores in a loop, looking for their mailbox 3. When that mailbox is no 0 the core jumps to the address contained there.
The linker script used sets at execution start the code contained in the startup assembler file armc-08-start.S (file listing and comments in this post).
That file prepare the environment (stack and variables initialization) and junps to C code kernel_main function, located at 6510.c in this case.
When kernel_main returns to assembler startup (armc-08-start.S) encounters a loop, similar to Linux one, looking for mailbox3.
So, the restart procedure is identical to initial start: write address execution in mailbox 3.

Now let's see how the stop process was implemented. Take a look to kernel_main function, included at 6510.c

volatile char live=0x1; //LCM flag
volatile char mailbox=0x20; //Emulator OUT (Monitor)
volatile char mailbox2=0x0; //Emulator IN(Keyboard)

#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "6502/6502.h"
#include "io/gpios.h"


void kernel_main( unsigned int r0, unsigned int r1, unsigned int atags )
{
reset6502();
while(live){
step6502();
}
}

Please note: live and mailbox definitions as volatile, in order to avoid compiler optimizations, ensuring variables in memory, accesible for Linux process.

You can see that kernel_main execution depends on "live" value. The idea here is make live=0 from Linux to stop execution (really return Core 3 to the loop looking to mailbox 3 in armc-08-start.S).
In order to determine the physical address for "live" variable we can  lists symbols from object file:

nm up-metal-6510.elf | grep live

In that way the provided script stop-metal.sh does:

lcm_control=0x$(nm up-metal-6510.elf | grep 'D live' | awk '{print $1}')
./devmem $lcm_control b 0x00

First obtain physical address for "live" variable and the writes 0 to it.


IPC
Inter Process Comunication is implemented using shared memory, specifically locations used by mailbox and mailbox2 variables (volatile). Lets list mailbox symbols:

nm up-metal-6510.elf | grep mailbox
20002ed1 D mailbox

200058d4 B mailbox2

On linux you can call
./monitor6510-char 0x20002ed1

that prints on terminal any change to that physicall address, that is mailbox bare-metal variable.

And in another terminal 
./keyboard6510-char 0x200058d4

Sends to mailbox2 the typed chars.

-------------------------------------------------------------
If you want to compile provided sourcefiles do:

Linux keyboard and monitor apps:
cd linux
gcc -o monitor6510-char monitor6510-char.c
gcc -o keyboard6510-char keyboard6510-char.c

Bare-metal emulator:
cd bare-metal
build-up-metal.sh