Introduction
The following notes apply to all versions of Astrobe for Cortex-M0, M3, M4, M7 and Astrobe for RP2040 (Cortex-M0+) and RP2350 (Cortex-M33) unless specifically noted.
Astrobe is supported on Microsoft Windows 10 and Windows 11 with the Microsoft .NET Framework 4.x or later.
The Installation and Uninstall executables are digitally
signed to validate authenticity and integrity.
Code Generation
The following details are of particular interest if you are using the Module and Application Disassemblers:
Instruction Sets
There are two instruction sets, called Thumb-1 and Thumb-2, used in Cortex-M processors Thumb-1 instructions are 16-bit and most can only access the low general purpose registers r0 .. r7 The equivalent 32-bit Thumb-2 instructions can be used to access additional general purpose registers r8 .. r11. In general Thumb-1 results in smaller code size and Thumb-2 results in better performance.
Most Thumb-1, but only a few Thumb-2, instructions can be used in Cortex-M0. All Thumb-1 and most Thumb-2 instructions can be used in Cortex-M3, M4, M7 and RP2350.
Additional instructions are used in Cortex-M4, M7 and RP2350 for the hardware floating point operations: add, multiply, divide and square root. These are implemented in software (the FPU library module) in Cortex-M0, M3 and RP2040.
Register Usage
Cortex-M0 and RP2040:
- The compiler allocates registers in sequence from r0 up to r7.
- Local variables in leaf procedures are not stored in registers due to the limited availabity of general purpose registers.
- The absolute maximum number of parameters that can be passed to a procedure is eight. Some types of parameters use more than one register so the limit can be less. The compiler will display an Alert, no free registers, if that is the case.
Cortex-M3, M4, M7 and RP2350:
- The compiler now allocates registers from r0 up to r11 instead of from r11 down to r0.
- A configuration option allows more use of 16-bit Thumb-1 instructions with an associated reduction in executable code size of about 30%.
- The maximum number of parameters that can be passed to a procedure is eleven. Some parameters, e.g. arrays and records, require two registers.
Frame Pointer
The frame pointer (FP = r12) is no longer required resulting in less overhead on procedure entry code. The register is reserved for future use.
Numeric Case Statements
Cortex-M0 and RP2040:
- The Thumb-1 Branch and Exchange (BX) instruction is used. The size limit of the CASE statement is 32KB.
Cortex-M3, M4, M7 and RP2350:
- The Thumb-2 Table Branch (TBH) instruction is used resulting in more compact code. The size limit of the CASE statement is 64KB.
Miscellaneous Optimisations
- Strings now immediately follow the code that accesses them.
- Shifts involving two constants are evaluated at compile time.
Built-in Procedures
CLEAR
The built-in procedure CLEAR initialises every word in a record or an array variable v to zero.
CLEAR(VAR v: <record or array type>)
It is designed to be used to simplify and optimise the code required to initialise complex data structures. Its use can be seen in the Performance example and procedure InitHeader in the HCFiler library module HCDir.
ORD
The expression which is passed as a parameter to ORD can be a BYTE expression as well as a CHAR, BOOLEAN or SET.
BITS
BITS will report an error if its actual parameter is a BYTE expression. However, ORD can be used to convert the expression to an INTEGER e.g.
setvar := BITS(ORD(bytevar))
SYSTEM Procedures
SYSTEM.ALIGN
PROCEDURE ALIGN()
ALIGN can be used to ensure that the instruction that follows it is aligned on a word boundary. It inserts a NOP instruction at the current code location if necessary.
SYSTEM.EMITH
PROCEDURE EMITH(instruction: INTEGER)
EMITH (EMIT Halfword) inserts the constant value instruction, which represents a 16-bit Arm Thumb instruction, at the current code location. A compilation error results if the value is not a valid 16-bit positive integer.
SYSTEM.VAL
SYSTEM.VAL no longer generates compiler warnings and the read-only restriction has been removed e.g. the following (where x is a word-length variable of any type) is a valid statement :
INC(SYSTEM.VAL(INTEGER, x))
SYSTEM Variables
SYSTEM.FP, SYSTEM.SP, SYSTEM.LNK and SYSTEM.PC have been removed. SYSTEM.LDREG and SYSTEM.REG with values 13 (SP), 14 (LNK) and 15 (PC), should be used instead. Register 12 (FP) is no longer used as a frame pointer.
Oberon Language Extensions
ARRAY OF BYTE
An existing Oberon language extension allows a procedure with a formal parameter which is an array of bytes with a fixed size to accept actual parameters of any type whose size is the same number of bytes.
The converse situation is now also catered for i.e. a procedure with a formal parameter of any type can accept an actual parameter which is an array of bytes of the same size.
These extensions are primarily designed to simplify and optimise the code required for tasks such as de-serialising / serialising complex data structures for Input / Output operations. An example of its use, ByteArrays.mod, is included with the General examples supplied with Astrobe. The following compiler warnings are generated:
Warning: type cast to byte array
Warning: type cast from byte array
NOTE: You can use SYSTEM.VAL for type casting if you would prefer not to use an Oberon Language extension. Examples of its use can be seen in VALByteArrays.mod in the General examples supplied with Astrobe.
Dynamic Local Array Variables
Eliminating the frame pointer resulted in the removal of support for dynamic local array variables. These can be replaced by local array variables with a fixed size.
Oberon Language Clarifications and Restrictions
The format of symbol files and the way they are processed have changed. Consequently, the related sections of Chapter 5 of the Oberon Programmers Guide now read:
Exports
- String constants cannot be exported. They can be assigned to exported variables which are read-only in modules that import them.
- Anonymous record and array variables can be exported.
Pointer Types
- Pointer types can only point to named record types e.g.
Item = POINTER TO ItemDesc;
ItemDesc = RECORD value: INTEGER; next: Item END;instead of:
Item = POINTER TO RECORD value: INTEGER; next: Item END;
- Pointer types can only point to global record types.
- A warning is reported at compile-time when a pointer type, whose base type is a private record, is exported.
TYPE
Item* = POINTER TO ItemDesc;
ItemDesc = RECORD value: INTEGER; next: Item END;This is referred to as an opaque pointer.
- An error is reported at compile time if a type test is performed on an imported opaque pointer variable, or it is passed as the parameter to the built-in function NEW.
Record Extensions
All identifiers declared in an extended record must be different from the identifiers declared in its base type record(s). An exception to this is that an identifier declared in an extended record may be the same as the identifier of a private field declared in an imported base type record.
Configuration
Thumb Code is a new configuration option which directs the compiler to make more use of 16-bit Thumb-1 instructions instead of equivalent 32-bit Thumb-2 instructions when generating code. The typical result is a reduction in code size of about 30%. It is permanently checked on for Cortex-M0.
Configuration ID is a new configuration option which can be used for any purpose by the programmer. It is an INTEGER value that can be accessed within an application by reading the value of the variable LinkOptions.ConfigID.
The Line Numbers configuration option has been renamed to Stack Trace to avoid confusion with the Tools > Preferences > Line Numbers option.
The obsolete Crystal Frequency configuration option has been removed.
File Menu
If a new folder is specified when using the Save As command, the folder name is used as the default folder the next time Save As is used.
Project Menu
Disassemble Module
- The Module Disassembler has been rewritten to disassemble the code after it has been generated not while it is being generated. The resulting disassembly is more accurate as it can show resolved internal backward and forward references.
- The 16-bit SEV, WFE, WFI, and YIELD instructions are supported by the disassemblers.
Compile, Build and Rebuild
- If, during a build or rebuild, a symbol file using a different format is found, the related module is recompiled and the symbol file is regenerated using the current format.
- The summaries include the number of lines compiled and the compilation time in milliseconds for each module and totals for all modules.
- The compiler reports an error if a constant parameter has a value which is out of range for the built-in functions LSL, LSR, ASR, ROR, INCL, EXCL, BFI, BFX and the SYSTEM functions LDREG, REG and BIT.
- The syntax diagram for the Type CASE statement has been added to the Oberon Quick Reference Help file.
Link
The options shown in the linker map for each module now include t+ or t- corresponding to whether the Thumb Code configuration option was checked on or off when that module was last compiled.
Run
Astrobe Terminal displays error messages instead of exceptions in the following situations:
- A serial port is not specified when Reset is pressed.
- A serial port is already in use when Reset is pressed.
- An attempt is made to write in the input area before Reset has been pressed.
Alerts
Alerts are a new type of compiler message like Warnings and Errors. An Alert is the same as an Error except that an object file and executable is still produced. This is to allow the disassemblers to be used to help diagnose the cause of the problem. Alerts must not be ignored as the behaviour of the executable will be unpredictable until all alerts have been eliminated.
Preferences
The default Editor Font is Consolas, Size: 9.
Library Modules
GPIO
Additional procedures Set and Reset are more efficient substitutes for Put with a constant state parameter equal to TRUE or FALSE respectively.
Examples
Info
Info (Cortex-M) includes additional information related to the status of the various clocks and PLL.
ByteArrays
ByteArrays is a new example which shows how structured variable parameters can be interpreted as arrays of bytes and vice versa.
VALByteArrays
VALByteArrays is a new example which shows how structured variables can be type cast to arrays of bytes and vice versa using SYSTEM.VAL.
Performance
Performance is a new example which uses the instruction counting feature of Cortex-M3, M4 and M7 to measure the performance of sections of code.
Supported Development Boards
Library modules, example source code and configuration files are included for use with the currently supported development boards.
Problems Fixed
v9.3
- Global record fields and array elements cannot be used as the address parameter to SYSTEM.GET and PUT with a non-zero increment / decrement value. A read-only compilation error is reported.
- Removed the Tools Help reference to the non-existent %FilePath% variable.
- A compiler warning, not an error, is reported if the type of a parameter of an exported procedure is private.
- Correct code is generated when a SET expression containing variable elements is passed as a parameter to a procedure.
- The compiler reports an error when a record has duplicate field names.
- The number of registers allocated when passing some types of parameters to procedures has been reduced. This helps to avoid the no free registers compiler alert.
- Intermittent problems with the synchronisation of instructions and source code lines in the module disassembly output have been fixed.
- The accuracy of the Math.Ln procedure has been improved.
- The compiler displays an error message instead of raising an exception when the number of imports (direct and indirect) in a module exceeds 32.
- Revised the Clarifications and Restrictions and the Implementation Size Limits sections of the Oberon Programmers Guide.
v9.2
- Line numbers displayed on the stack trace report match the corresponding source line numbers more accurately.
- If the "$" character is found anywhere in a module, other than in a comment or a string constant, the compiler reports an error: "bad character".
- Compilation now continues after an integer overflow exception occurs in a constant expression.
- Correct code is generated when a procedure call is separated by a significant amount of code from the global record type declaration of one of its parameters.
v9.1
- SYSTEM.BIT now generates correct code when the bit number is 31.
- Corrected several errors in the Traps library module. The Stack Trace now includes the stacked r12 (not r11) and PSR values, and calls to procedure variables. Corrected the module/procedure returned by GetName when a trap is reported in the initialisation of a module.
- stackLimit is now initialised to the same value as heapLimit in the Storage library module.
- Correct code is now generated when SYSTEM.REG(x) is passed as a parameter to both normal and built-in procedures.
- Removed the obsolete NXP checksum from the target executable (.bin) file.
- Only save / restore the registers if necessary when entering / exiting interrupt handlers.
- Removed unnecessary NOP instructions e.g. associated with PUSH and POP.
- Cortex-M0: Corrected SYSTEM.COPY when the number of words is a constant equal to 2.
- Corrected CLEAR when used with BYTE arrays.
- SYSTEM.ALIGN can be called without parentheses and is implemented for Cortex-M0.