mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-21 17:50:40 +00:00
Updating docs
This commit is contained in:
parent
787e6ec8cb
commit
dfc89a4449
4 changed files with 15 additions and 36 deletions
|
@ -40,9 +40,16 @@ Let's start by looking at how we implement SPI communication.
|
|||
|
||||
I'm not going to write a long paper on how SPI works and why we need it, because it's [very well documented elsewhere](https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/). It's recommended background reading, but not essential if all you want to do is get something working.
|
||||
|
||||
Look at _lib/spi.c_. It uses some of existing functions in _lib/io.c_ that you'll remember from earlier tutorials. Specifically, _spi_init()_ sets GPIO 7, 9, 10, and 11 to use the ALT0 function. Cross-referencing with the [BCM2711 ARM Peripherals document](https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf), page 77, you'll see that this maps SPI0 to the GPIO header. GPIO 8 is mapped as an output pin, since we'll use this to signal to the ENC28J60 that we want to talk. In fact, the _spi_chip_select()_ function takes a true/false (boolean) parameter which either sets or clears this pin.
|
||||
Look at _lib/spi.c_. It uses some of existing functions in _lib/io.c_ that you'll remember from earlier tutorials. In fact, I've added two functions to the _include/io.h_ header file so we can call them from our SPI library:
|
||||
|
||||
Looking at the SPI0 register map on page 134, we see this reflected in the _REGS_SPI0_ structure. This gives us handy access to the SPI0 peripheral's memory map.
|
||||
```c
|
||||
void gpio_setPinOutputBool(unsigned int pin_number, unsigned int onOrOff);
|
||||
void gpio_initOutputPinWithPullNone(unsigned int pin_number);
|
||||
```
|
||||
|
||||
Specifically, _spi_init()_ sets GPIO 7, 9, 10, and 11 to use the ALT0 function. Cross-referencing with the [BCM2711 ARM Peripherals document](https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf), page 77, you'll see that this maps SPI0 to the GPIO header. GPIO 8 is mapped as an output pin, since we'll use this to signal to the ENC28J60 that we want to talk. In fact, the _spi_chip_select()_ function takes a true/false (boolean) parameter which either sets or clears this pin.
|
||||
|
||||
Looking at the SPI0 register map on page 134, we see this reflected in our _REGS_SPI0_ structure. This gives us handy access to the SPI0 peripheral's memory-mapped registers.
|
||||
|
||||
Our _spi_send_recv()_ function then sets us up for some communcation:
|
||||
|
||||
|
@ -54,4 +61,4 @@ Then, whilst there's either data to write or data to read (and we haven't writte
|
|||
|
||||
Finally, to be absolutely sure, we clear the TA flag.
|
||||
|
||||
I've then set up two convenient functions _spi_send()_ and _spi_recv()_ which exercise _spi_send_recv(), mainly to make future code more readable.
|
||||
I've then set up two convenient functions - _spi_send()_ and _spi_recv()_ - which exercise _spi_send_recv(), mainly to make future code more readable.
|
||||
|
|
|
@ -2,5 +2,4 @@ void spi_init();
|
|||
void spi_send_recv(unsigned char *sbuffer, unsigned char *rbuffer, unsigned int size);
|
||||
void spi_send(unsigned char *data, unsigned int size);
|
||||
void spi_recv(unsigned char *data, unsigned int size);
|
||||
void spi_send_no_selection(unsigned char command);
|
||||
void spi_chip_select(unsigned char chip_select);
|
||||
|
|
|
@ -1,27 +1,4 @@
|
|||
#include "kernel.h"
|
||||
#include "../include/fb.h"
|
||||
|
||||
char *entry_error_messages[] = {
|
||||
"SYNC_INVALID_EL1t",
|
||||
"IRQ_INVALID_EL1t",
|
||||
"FIQ_INVALID_EL1t",
|
||||
"ERROR_INVALID_EL1T",
|
||||
|
||||
"SYNC_INVALID_EL1h",
|
||||
"IRQ_INVALID_EL1h",
|
||||
"FIQ_INVALID_EL1h",
|
||||
"ERROR_INVALID_EL1h",
|
||||
|
||||
"SYNC_INVALID_EL0_64",
|
||||
"IRQ_INVALID_EL0_64",
|
||||
"FIQ_INVALID_EL0_64",
|
||||
"ERROR_INVALID_EL0_64",
|
||||
|
||||
"SYNC_INVALID_EL0_32",
|
||||
"IRQ_INVALID_EL0_32",
|
||||
"FIQ_INVALID_EL0_32",
|
||||
"ERROR_INVALID_EL0_32"
|
||||
};
|
||||
|
||||
void enable_interrupt_controller() {
|
||||
REGS_IRQ->irq0_enable_0 = SYS_TIMER_IRQ_1 | SYS_TIMER_IRQ_3;
|
||||
|
@ -31,14 +8,6 @@ void disable_interrupt_controller() {
|
|||
REGS_IRQ->irq0_enable_0 = 0;
|
||||
}
|
||||
|
||||
void show_invalid_entry_message(int type, unsigned long esr, unsigned long address) {
|
||||
debugstr(entry_error_messages[type]);
|
||||
debugstr(" ESR: ");
|
||||
debughex(esr);
|
||||
debugstr("Addr: ");
|
||||
debughex(address);
|
||||
}
|
||||
|
||||
void handle_irq() {
|
||||
unsigned int irq = REGS_IRQ->irq0_pending_0;
|
||||
|
||||
|
|
|
@ -67,7 +67,11 @@
|
|||
mov x0, #\type
|
||||
mrs x1, esr_el1
|
||||
mrs x2, elr_el1
|
||||
bl show_invalid_entry_message
|
||||
|
||||
// We could pass this to a function to print an error here
|
||||
// e.g. bl show_invalid_entry_message
|
||||
//
|
||||
// For now we'll just hang
|
||||
|
||||
b err_hang
|
||||
.endm
|
||||
|
|
Loading…
Reference in a new issue