Refactor README for clarity and formatting

Removed unnecessary formatting and improved clarity in the README.
This commit is contained in:
Jason
2025-12-08 20:50:51 +11:00
committed by GitHub
parent a398fd3ccb
commit 10205596b2
+37 -98
View File
@@ -1,30 +1,28 @@
````markdown
# Colour Maximite 2 - CSUB Example and ARM Cortex-M7 Embedded Code # Colour Maximite 2 - CSUB Example and ARM Cortex-M7 Embedded Code
This document demonstrates how to embed ARM Cortex-M7 machine code directly into your BASIC program on the Colour Maximite 2 using the `CSUB` directive. It covers a minimal example, explains the embedded machine code, and provides detailed instructions on writing, compiling, and embedding ARM Thumb-2 assembly or C routines. This document demonstrates how to embed ARM Cortex-M7 machine code directly into your BASIC program on the Colour Maximite 2 using the CSUB directive. It covers a minimal example, explains the embedded machine code, and provides instructions on writing, compiling, and embedding ARM Thumb-2 assembly or C routines.
--- ---
## What is CSUB? ## What is CSUB?
`CSUB` allows embedding raw ARM machine code or compiled C/assembly routines into Colour Maximite 2 BASIC programs. These embedded routines appear as BASIC commands or functions and run natively on the ARM Cortex-M7 processor, enabling efficient, low-level operations beyond standard BASIC capabilities. CSUB allows embedding raw ARM machine code or compiled C/assembly routines into Colour Maximite 2 BASIC programs. These embedded routines appear as BASIC commands or functions and run natively on the ARM Cortex-M7 processor, enabling efficient, low-level operations beyond standard BASIC capabilities.
According to the Colour Maximite 2 user manual: According to the Colour Maximite 2 user manual:
> `CSUB name [type [, type] …]` > CSUB name [type [, type] …]
> hex [[ hex[…]] > hex [[ hex[…]]
> hex [[ hex[…]] > hex [[ hex[…]]
> `END CSUB` > END CSUB
> >
> Defines the binary code for an embedded machine code program module written in C or ARM assembler. The module will appear in MMBasic as the command `name` and can be used in the same manner as a built-in command. > Defines the binary code for an embedded machine code program module written in C or ARM assembler. The module will appear in MMBasic as the command `name` and can be used in the same manner as a built-in command.
Multiple embedded routines can be used in a program, each defining a different module with a unique name. The first hex word is a 32-bit word representing the offset in bytes from the start of the CSUB to the entry point of the embedded routine (usually the function `main()`). The following hex words are the compiled binary code for the module. The first hex word is a 32-bit word representing the offset in bytes from the start of the CSUB to the entry point of the embedded routine. The following hex words are the compiled binary code for the module.
--- ---
## CSUB Code Example ## CSUB Code Example
```basic
CSUB simple CSUB simple
00000000 00004770 00000000 00004770
END CSUB END CSUB
@@ -32,7 +30,6 @@ END CSUB
simple() simple()
PRINT "Returned successfully" PRINT "Returned successfully"
````
![Description](IMG_0019.JPG) ![Description](IMG_0019.JPG)
@@ -40,120 +37,70 @@ PRINT "Returned successfully"
## What Does This Thumb-2 Machine Code Do? ## What Does This Thumb-2 Machine Code Do?
### `CSUB simple` - **CSUB simple**: Starts a machine-code subroutine named `simple`. Tells BASIC that the following hex words are compiled machine code.
- **00000000**: Entry point offset; 0 indicates execution starts immediately at the next word. Metadata only, not executed.
* Starts the definition of a machine-code subroutine named `simple`. - **00004770**: Thumb instruction BX LR; returns immediately from the subroutine to BASIC.
* Tells the BASIC runtime that the following hex words are compiled machine code to execute when `simple()` is called. - **END CSUB**: Marks the end of the CSUB block. BASIC execution continues normally.
- **simple()**: Calls the subroutine; execution jumps to the CSUB, reads the entry point, executes BX LR, and returns.
### `00000000` - **PRINT "Returned successfully"**: Prints a message indicating the subroutine returned successfully.
* The entry point offset for the CSUB.
* A value of `0` indicates execution starts immediately at the next word.
* This word is metadata only; it is **not executed** as machine code.
### `00004770`
* Encodes the Thumb instruction `BX LR` (Branch to Link Register).
* This instruction **returns immediately** from the subroutine to BASIC.
### `END CSUB`
* Marks the end of the CSUB block.
* Signals that the machine code definition is complete, and BASIC execution continues normally.
### `simple()`
* Calls the subroutine `simple`.
* Execution jumps to the CSUB, reads the entry point offset, executes the `BX LR` instruction, and immediately returns.
### `PRINT "Returned successfully"`
* Prints a message to the BASIC console to indicate the subroutine returned successfully.
--- ---
## ARM Thumb-2 Assembly Example Corresponding to the Machine Code ## ARM Thumb-2 Assembly Example
```asm
.syntax unified .syntax unified
.thumb .thumb
.global simple .global simple
simple: simple:
bx lr @ Return immediately bx lr @ Return immediately
```
### Explanation Explanation:
* `.syntax unified`: Use modern unified ARM assembler syntax. - .syntax unified: Use modern unified ARM assembler syntax.
* `.thumb`: Assemble for the Thumb instruction set used by Cortex-M7. - .thumb: Assemble for the Thumb instruction set used by Cortex-M7.
* `.global simple`: Declare the `simple` symbol as global (entry point). - .global simple: Declare the `simple` symbol as global.
* `bx lr`: Branch to the address stored in the Link Register (`LR`), returning control to the caller. - bx lr: Branch to the address stored in the Link Register, returning control to the caller.
> Note: In this minimal example, no values are returned to BASIC.
--- ---
## How to Compile, Link, and Extract Binary ## How to Compile, Link, and Extract Binary
### Step 1: Save Assembly Code 1. **Save Assembly Code** as main.s
2. **Assemble to Object File**
Save the code above as `main.s`.
### Step 2: Assemble to Object File
```bash
arm-none-eabi-as -mcpu=cortex-m7 -mthumb main.s -o main.o arm-none-eabi-as -mcpu=cortex-m7 -mthumb main.s -o main.o
```
* `-mcpu=cortex-m7`: Target Cortex-M7 CPU. 3. **Link to ELF Executable**
* `-mthumb`: Use Thumb instruction set.
### Step 3: Link to ELF Executable
```bash
arm-none-eabi-ld main.o -Ttext=0x0 -o main.elf arm-none-eabi-ld main.o -Ttext=0x0 -o main.elf
```
Or combine compiling and linking with GCC: Or using GCC:
```bash
arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb -nostartfiles -Wl,-Ttext=0x0 -o main.elf main.s arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb -nostartfiles -Wl,-Ttext=0x0 -o main.elf main.s
```
* `-nostartfiles`: Avoid linking standard startup code. 4. **Extract Raw Binary**
* `-Ttext=0x0`: Set load address to 0.
### Step 4: Extract Raw Binary
```bash
arm-none-eabi-objcopy -O binary main.elf main.bin arm-none-eabi-objcopy -O binary main.elf main.bin
```
### Step 5: View Machine Code as Hex 5. **View Machine Code as Hex**
```bash
xxd -e main.bin xxd -e main.bin
```
Sample output: Sample output:
```
00000000: 20420047 00000000: 20420047
```
* `20420047` is the machine code word representing `movs r0, #42` and `bx lr`. 20420047 represents `movs r0, #42` and `bx lr`.
--- ---
## Preparing the CSUB Block ## Preparing the CSUB Block
* The **first 32-bit word** is the entry point offset (usually `00000000`). - First 32-bit word is the entry point offset (usually 00000000).
* Following words are your compiled machine code in 32-bit hex words. - Following words are the compiled machine code in 32-bit hex words.
Example: Example:
```basic
CSUB myfunc CSUB myfunc
00000000 20420047 00000000 20420047
END CSUB END CSUB
@@ -161,40 +108,32 @@ END CSUB
myfunc() myfunc()
PRINT "Returned value in R0 was 42" PRINT "Returned value in R0 was 42"
```
--- ---
## Passing Arguments and Returning Data ## Passing Arguments and Returning Data
* You can specify argument types in the CSUB definition, e.g., - Specify argument types in the CSUB definition:
```basic
CSUB MySub integer, integer, string CSUB MySub integer, integer, string
```
* Up to 10 arguments are supported. - Up to 10 arguments supported.
* Variables or arrays passed are pointers to their data, allowing embedded routines to modify passed data directly. - Variables or arrays are passed as pointers, allowing routines to modify data directly.
* Constants and expressions are passed as pointers to temporary memory containing their values. - Constants and expressions are passed as pointers to temporary memory.
* For longer-running routines, call `routinechecks()` regularly to keep USB and watchdog timers active, or keep routine execution under a few milliseconds. - For longer routines, call routinechecks() regularly to keep USB and watchdog timers active, or keep execution under a few milliseconds.
--- ---
## Additional Tips and Verification ## Additional Tips
* Use `arm-none-eabi-objdump -d main.elf` to disassemble and verify your machine code. - Use arm-none-eabi-objdump -d main.elf to disassemble and verify machine code.
* Compile C routines similarly, specifying `-mcpu=cortex-m7 -mthumb` in compiler flags. - Compile C routines similarly with -mcpu=cortex-m7 -mthumb.
* Place CSUB blocks anywhere in your BASIC code; MMBasic will skip over them during execution. - CSUB blocks can be placed anywhere; BASIC skips over them during execution.
* Each hex word must be exactly eight hex digits and separated by spaces or new lines. - Each hex word must be exactly eight hex digits, separated by spaces or new lines.
* Formatting errors or incorrect hex data will cause runtime errors in MMBasic. - Incorrect formatting or hex data causes runtime errors.
--- ---
## License ## License
This document and any accompanying code are released under the MIT License. This document and any accompanying code are released under the MIT License.
```
```