A common use case is
Code: Select all
Out.String("this is a test")
With a serial device driver API procedure like so... [2]
Code: Select all
PROCEDURE PrintString*(chan: INTEGER; s: ARRAY OF CHAR; nc: INTEGER);
But -- how can 'PrintString' determine the address of 's'?
I see two solutions, both work,[3] but neither "looks nice".
Code: Select all
(* 1 *)
PROCEDURE PrintString*(chan: INTEGER; s: ARRAY OF CHAR; nc: INTEGER);
BEGIN
DMA.SetMemAddr(chan, SYSTEM.ADR(s[0])); (* set memory address for DMA channel *)
DMA.SetNumData(chan, nc); (* set number of data items for DMA channel *)
(* ... *)
END PrintString;
(* 2 *)
PROCEDURE PrintString*(chan: INTEGER; s: ARRAY OF CHAR; nc: INTEGER);
BEGIN
DMA.SetMemAddr(chan, SYSTEM.REG(1));
DMA.SetNumData(chan, nc);
(* ... *)
END PrintString;
***
[1] The determination of the string length could also be delegated to 'PrintString', but output procedures such as 'Out.Hex' already have this data available due to how the corresponding output strings are constructed.
[2] I could also implement a more "raw" device driver procedure like this:
Code: Select all
PROCEDURE PrintStringBuffer(chan: INTEGER; bufAddr: INTEGER; nc: INTEGER);
[3] Evidenced by checking the generated code, as well as via test programs.
Variant (* 1 *)
Code: Select all
PROCEDURE PutString*(chan: INTEGER; s: ARRAY OF CHAR; nc: INTEGER);
BEGIN
. 4 04H 0B50FH push { r0, r1, r2, r3, lr }
DMA.SetMemAddr(chan, SYSTEM.ADR(s[0]));
. 6 06H 09800H ldr r0,[sp]
. 8 08H 02100H movs r1,#0
. 10 0AH 09A02H ldr r2,[sp,#8]
. 12 0CH 04291H cmp r1,r2
. 14 0EH 0D301H bcc.n 2 -> 20
. 16 010H 0DF01H svc 1
. 18 <LineNo: 13>
. 20 014H 09A01H ldr r2,[sp,#4]
. 22 016H 01851H adds r1,r2,r1
. 24 018H 004050000H bl.w Ext Proc #5
Code: Select all
PROCEDURE PutString*(chan: INTEGER; s: ARRAY OF CHAR; nc: INTEGER);
BEGIN
. 4 04H 0B50FH push { r0, r1, r2, r3, lr }
DMA.SetMemAddr(chan, SYSTEM.REG(1));
. 6 06H 09800H ldr r0,[sp]
. 8 08H 004050000H bl.w Ext Proc #5