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
- All interrupt stuff now in one place (Link / main.asm)
- Consolidate interrupt explanation in the Link section
- Explain interrupts too much and too little
Copy file name to clipboardExpand all lines: src/part2/serial-link.md
+59-39Lines changed: 59 additions & 39 deletions
Original file line number
Diff line number
Diff line change
@@ -224,20 +224,6 @@ The received value is copied from the serial port (`rSB`) to Sio's buffer (`wSio
224
224
If there are still bytes to transfer (transfer counter is greater than zero) the next value is loaded from `wSioBufferTx` and the transfer is started by `SioPortStart`.
225
225
Otherwise, if the transfer counter is zero, enter the `SIO_DONE` state.
226
226
227
-
`SioPortEnd` must be called once after each byte transfer.
This is an interrupt handler -- a special piece of code that gets called by the CPU under certain conditions.
235
-
The serial interrupt occurs when the serial port completes a transfer.
236
-
237
-
All this code does is invoke `SioPortEnd` safely.
238
-
The state of the CPU registers that `SioPortEnd` modifies are preserved by *pushing* them to the stack before the `call`, then restored by *popping* them off the stack afterwards.
239
-
If we didn't do this, the interrupted code would likely break when the registers are suddenly modified out of nowhere.
240
-
241
227
242
228
## Interval
243
229
@@ -376,45 +362,31 @@ It's probably worth looking into better solutions for real-world projects.
376
362
:::
377
363
378
364
379
-
## /// Using Sio
380
-
381
-
/// Because we have an extra file (sio.asm) to compile now, the build commands will look a little different:
382
-
```console
383
-
$ rgbasm -o sio.o sio.asm
384
-
$ rgbasm -o main.o main.asm
385
-
$ rgblink -o unbricked.gb main.o sio.o
386
-
$ rgbfix -v -p 0xFF unbricked.gb
387
-
```
365
+
## Connecting it all together
388
366
389
367
<!-- "Link" -->
390
-
/// serial link features: *Link*
368
+
It's time to build the application-level link features.
369
+
We're going to
370
+
- implement the protocol logic
371
+
- implement the handshake
372
+
- build a demo/test program
391
373
392
374
/// tiles
393
375
394
376
/// defs
395
377
378
+
396
379
<!-- LinkInit -->
397
-
/// one function to initialise basic serial link state.
A proper and complete explanation of this is beyond the scope of this lesson.
412
+
You can continue the lesson understanding that:
413
+
- This is the serial interrupt handler. It gets called automatically after each serial transfer.
414
+
- The relevant stuff is in `SioPortEnd` but it's necessary to jump through some hoops to call it.
415
+
416
+
A detailed and rather dense explanation is included for completeness.
417
+
418
+
:::tip
419
+
420
+
*You can just use the code as explained above and skip past this box.*
421
+
422
+
An interrupt handler is a piece of code at a specific address that gets called automatically under certain conditions.
423
+
The serial interrupt handler begins at address `$58` so a section just for this function is defined at that location using `ROM0[$58]`.
424
+
Note that the function is labelled by convention and for debugging purposes -- it isn't technically meaningful and the function isn't intended to be called manually.
425
+
426
+
Whatever code was running when an interrupt occurs literally gets paused until the interrupt handler returns.
427
+
The registers used by `SioPortEnd` need to be preserved so the code that got interrupted doesn't break.
428
+
We use the stack to do this -- using `push` before the call and `pop` afterwards.
429
+
Note that the order of the registers when pushing is the opposite of the order when popping, due to the stack being a LIFO (last-in, first-out) container.
430
+
431
+
`reti` returns from the function (like `ret`) and enables interrupts (like `ei`) which is necessary because interrupts are disabled automatically when calling an interrupt handler.
432
+
433
+
If you would like to continue digging, have a look at [evie's interrupts tutorial](https://evie.gbdev.io/resources/interrupts) and [on pandocs](https://gbdev.io/pandocs/Interrupts.html).
434
+
435
+
:::
436
+
437
+
429
438
/// `LinkTx`, alternate between sending the two types of packet:
0 commit comments