You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/source/os.rst
+82-68Lines changed: 82 additions & 68 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,15 +7,15 @@ RP6502 - Operating System
7
7
Introduction
8
8
============
9
9
10
-
The :doc:`ria` runs a protected 32-bit protected operating system that
10
+
The :doc:`ria` runs a 32-bit protected operating system that
11
11
you can call from the 6502. The :doc:`os` does not use any 6502 RAM
12
12
and will not interfere with developing a native 6502 OS.
13
13
14
14
The :doc:`os` is loosely based on POSIX with an ABI similar to
15
-
CC65's fastcall. It provides stdio.h services to both CC65 and
16
-
LLVM-MOS compilers. There are also calls access Picocomputer features
17
-
and manage FAT32 filesystems. ExFAT is ready to go and will be enabled
18
-
when the patents expire.
15
+
CC65's fastcall. It provides stdio.h and unistd.h services to both
16
+
CC65 and LLVM-MOS compilers. There are also calls access RP6502
17
+
features and manage FAT32 filesystems. ExFAT is ready to go and will
18
+
be enabled when the patents expire.
19
19
20
20
21
21
Memory Map
@@ -43,40 +43,33 @@ registers of the RIA.
43
43
* - FFE0-FFFF
44
44
- RIA, see the :doc:`RP6502-RIA datasheet <ria>`
45
45
* - 10000-1FFFF
46
-
- XRAM, 64K for :doc:`RP6502-RIA <ria>` and
47
-
:doc:`RP6502-VGA <vga>`
46
+
- XRAM, 64K for :doc:`ria` and :doc:`vga`
48
47
49
48
The unassigned space is available for hardware experimenters. You will
50
49
need to design your own address decoder logic hardware to use this
51
50
address space. It is recommended that additional VIAs be added "down"
52
51
and other hardware added "up". For example: VIA0 at $FFD0, VIA1 at
53
52
$FFC0, SID0 at $FF00, and SID1 at $FF20.
54
53
55
-
I use "Picocomputer 6502" to refer to the reference design with the
56
-
above memory map. Please use a differentiating name if you change the
57
-
hardware. For example, "Picocomputer VERA" or "Ulf's Dream Computer".
58
-
Think about what people asking for help should call the device and go
59
-
with that.
60
54
61
-
62
-
Calling with fastcall
63
-
=====================
55
+
Application Binary Interface (ABI)
56
+
==================================
64
57
65
58
The binary interface for calling the operating system is based on
66
59
fastcall from the `CC65 Internals
67
-
<https://cc65.github.io/doc/cc65-intern.html>`_. The RP6502-OS fastcall
68
-
does not use or require anything from CC65 and is easy for assembly
69
-
programmers to use. At its core, the API ABI is based on a C ABI with
70
-
four simple rules.
60
+
<https://cc65.github.io/doc/cc65-intern.html>`_. The RP6502-OS
61
+
fastcall does not use or require anything from CC65 and is easy for
62
+
assembly programmers to use. At its core, the OS API ABI is based on
63
+
a C ABI with four simple rules.
71
64
72
65
* Stack arguments are pushed left to right.
73
66
* Last argument passed by register A, AX, or AXSREG.
74
67
* Return value in register AX or AXSREG.
75
-
* Returned structures on the stack.
68
+
* May return data on the stack.
76
69
77
70
A and X are the 6502 registers. The pseudo register AX combines them
78
71
for 16 bits. AXSREG is 32 bits with 16 SREG bits. Let's look at how
79
-
to make an OS call through the RIA registers. All kernel calls are
72
+
to make an OS call through the RIA registers. All OS calls are
80
73
specified as a C declaration like so:
81
74
82
75
.. c:function::intdoit(int arg0, int arg1);
@@ -118,22 +111,22 @@ absolute instructions.
118
111
wait:
119
112
BIT RIA_BUSY
120
113
BMI wait
121
-
LDA RIA_A
122
-
LDX RIA_X
114
+
LDA #RIA_A
115
+
LDX #RIA_X
123
116
124
117
All operations returning RIA_A will also return RIA_X to assist with
125
-
CC65's integer promotion requirements. RIA_SREG is only updated for
118
+
C integer promotion. RIA_SREG is only updated for
126
119
32-bit returns. RIA_ERRNO is only updated if there is an error.
127
120
128
-
Some operations return data structures on the stack. You must pull the
129
-
entire stack before the next call. However, tail call optimizations are
130
-
possible. For example, you can chain read_xstack() and write_xstack()
131
-
to copy a file without using any RAM or XRAM.
121
+
Some operations return strings or structures on the stack. You must
122
+
pull the entire stack before the next call. However, tail call
123
+
optimizations are possible. For example, you can chain read_xstack()
124
+
and write_xstack() to copy a file without using any RAM or XRAM.
132
125
133
126
Short Stacking
134
127
---------------
135
128
136
-
In the never ending pursuit of saving all the clocks, it is possible to
129
+
In the never ending pursuit of saving all the cycles, it is possible to
137
130
save a few on the stack push if you don't need all the range. This only
138
131
works on the stack argument that gets pushed first. For example:
139
132
@@ -148,7 +141,7 @@ bits, push only three bytes. The significant bytes will be implicit.
148
141
Shorter Integers
149
142
-----------------
150
143
151
-
Many operations can save a few clocks by ignoring REG_X. All integers
144
+
Many operations can save a few cycles by ignoring REG_X. All integers
152
145
are always available as 16 bits to assist with C integer promotion.
153
146
However, many operations will ignore REG_X on the register parameter
154
147
and limit their return to fit in REG_A. This will be documented below
@@ -158,8 +151,8 @@ Bulk Data
158
151
---------
159
152
160
153
Functions that move bulk data may come in two flavors. These are any
161
-
function with a pointer parameter. This pointer is meaningless to the
162
-
kernel because it can not change 6502 RAM. Instead, we use the XSTACK
154
+
function with a pointer parameter. A RAM pointer is meaningless to the
155
+
RIA because it can not change 6502 RAM. Instead, we use the XSTACK
163
156
or XRAM for data buffers.
164
157
165
158
Bulk XSTACK Operations
@@ -174,31 +167,33 @@ examples.
174
167
175
168
int open(const char *path, int oflag);
176
169
177
-
Send `oflag` in AX. Send the path on XSTACK by pushing the string
178
-
starting with the last character. You may omit pushing the terminating
179
-
zero, but strings are limited to a length of 255. Calling this from the
180
-
C SDK will "just work" because there's an implementation that pushes
181
-
the string for you.
170
+
Send `oflag` in RIA_A and RIA_X. Send the path on XSTACK by pushing the
171
+
string starting with the last character. You may omit pushing the
172
+
terminating zero, but strings are limited to a length of 255. Calling
173
+
this from the C SDK will "just work" because there's an implementation
174
+
that pushes the string for you.
182
175
183
176
.. code-block:: C
184
177
185
178
int read_xstack(void *buf, unsigned count, int fildes)
186
179
187
-
Send `count` as a short stack and `fildes` in AX. The returned value in
188
-
AX indicates how many values must be pulled from the stack. If you call
180
+
Send `count` as a short stack and `fildes` in RIA_A. RIA_X doesn't need
181
+
to be set according the to docs below. The returned value in AX
182
+
indicates how many values must be pulled from the stack. If you call
189
183
this from the C SDK then it will copy XSTACK to buf[] for you.
190
184
191
185
.. code-block:: C
192
186
193
187
int write_xstack(const void *buf, unsigned count, int fildes)
194
188
195
-
Send `fildes` in AX. Push the data to XSTACK. Do not send `count`, the
196
-
kernel knows this from its internal stack pointer. If you call this from
197
-
the C SDK then it will copy count bytes of buf[] to XSTACK for you.
189
+
Send `fildes` in RIA_A. Push the buf data to XSTACK. Do not send
190
+
`count`, the OS knows this from its internal stack pointer. If you call
191
+
this from the C SDK then it will copy count bytes of buf[] to XSTACK
192
+
for you.
198
193
199
-
Note that read() and write() are part of the C SDK, not a kernel
200
-
operation. CC65 requires them to support more than 512 bytes, so they
201
-
have wrapper logic to make multiple kernel calls when necessary.
194
+
Note that read() and write() are part of the C SDK, not an OS
195
+
operation. C requires these to support a count larger than the XSTACK
196
+
can return so the implementation makes multiple OS calls as necessary.
202
197
203
198
Bulk XRAM Operations
204
199
~~~~~~~~~~~~~~~~~~~~
@@ -211,31 +206,49 @@ going through 6502 RAM or capture a screenshot with ease.
211
206
int read_xram(xram_addr buf, unsigned count, int fildes)
212
207
int write_xram(xram_addr buf, unsigned count, int fildes)
213
208
214
-
The kernel expects `buf` and `count` on the XSTACK as integers with
215
-
`filedes` in AX. The buffer is effectively &XRAM[buf] here. There's
216
-
nothing special about these calls in regards to how the binary interface
217
-
rules are applied. They are interesting because of their high
218
-
performance for loading assets.
209
+
The OS expects `buf` and `count` on the XSTACK as integers with
210
+
`filedes` in RIA_A. The buffer is effectively &XRAM[buf] here.
211
+
212
+
These operations are interesting because of their high performance and
213
+
ability to work in the background while the 6502 is doing something
214
+
else. You can expect close to 64KB/sec, which means loading a game
215
+
level's worth of assets will take less than a second.
216
+
217
+
Bulk XRAM operations are why the Picocomputer 6502 was designed
218
+
without paged memory.
219
219
220
220
Function Reference
221
221
===================
222
222
223
-
Much of this API is based on CC65 and POSIX. In particular, filesystem
224
-
access should feel extremely modern. However, some operations will have
225
-
different argument orders or bitfield values than what you're used to.
226
-
The reason for this becomes apparent when you start to work in assembly
227
-
and fine tune short stacking and integer demotions. You might not notice
228
-
the differences if you only work in C because the standard library has
229
-
wrapper functions and familiar prototypes. For example, the f_lseek()
230
-
described below has reorderd arguments that are optimized for short
231
-
stacking the long argument. But you don't have to call f_lseek() from C,
232
-
you call the usual lseek() which has the traditional argument order.
223
+
Much of this API is based on POSIX and FatFs. In particular, filesystem
224
+
and console access should feel extremely familiar. However, some
225
+
operations will have different argument orders or bitfield values than
226
+
what you're used to. The reason for this becomes apparent when you start
227
+
to work in assembly and fine tune short stacking and integer demotions.
228
+
You might not notice the differences if you only work in C because the
229
+
standard library has wrapper functions and familiar prototypes. For
230
+
example, the f_lseek() described below has reordered arguments that are
231
+
optimized for short stacking the long argument. But you don't have to
232
+
call f_lseek() from C, you can call the usual lseek() which has the
233
+
traditional argument order.
234
+
235
+
The RP6502 is built around FAT filesystems, which is the defacto standard
236
+
for USB storage devices. POSIX filesystems are not fully compatible with
237
+
FAT but there is a solid intersection of basic IO that is 100% compatible.
238
+
You will see some familiar POSIX functions like open() and others like
239
+
f_stat() which are similar to the POSIX function but tailored to FAT.
240
+
Should it ever become necessary to have a POSIX stat(), it can be
241
+
implemented in the C standard library or in an application by translating
242
+
f_stat() data.
233
243
234
244
zxstack
235
245
-------
236
246
.. c:function::voidzxstack(void);
237
247
238
-
Abandon the xstack by resetting the xstack pointer. This is the only operation that doesn't require waiting for completion. You do not need to call this for failed operations. It can be useful if you want to quickly ignore part of a returned structure.
248
+
Abandon the xstack by resetting the xstack pointer. This is the only
249
+
operation that doesn't require waiting for completion. You do not need
250
+
to call this for failed operations. It can be useful if you want to
251
+
quickly ignore part of a returned structure.
239
252
240
253
xreg
241
254
----
@@ -274,7 +287,7 @@ phi2
274
287
Retrieves the PHI2 setting from the RIA. Applications can use this
275
288
for adjusting to or rejecting different clock speeds.
276
289
277
-
:returns: The 6502 clock speed in kHz. Typically 750 <= x <= 8000.
290
+
:returns: The 6502 clock speed in kHz. Typically 800 <= x <= 8000.
278
291
:errno: will not fail
279
292
280
293
@@ -317,6 +330,8 @@ stdin_opt
317
330
318
331
.. c:function:: int stdin_opt(unsigned long ctrl_bits, unsigned char str_length)
319
332
333
+
*** Experimental *** (likely to be replaced with stty-like something)
334
+
320
335
Additional options for the STDIN line editor. Set the str_length to
321
336
your buffer size - 1 to make gets() safe. This can also guarantee no
322
337
split lines when using fgets() on STDIN.
@@ -629,10 +644,9 @@ exit
629
644
630
645
.. c:function:: void exit(int status)
631
646
632
-
Halt the 6502 and return to the kernel command interface. This is the
633
-
only operation that does not return. RESB will be pulled down before
634
-
the next instruction can execute. Status is currently ignored but will
635
-
be used in the future.
647
+
Halt the 6502 and return the console to RP6502 monitor control. This
648
+
is the only operation that does not return. RESB will be pulled down
649
+
before the next instruction can execute. Status is currently ignored
0 commit comments