Init rtc and pic in kernel
This commit is contained in:
32
sw/kernel/devices/interrupt_controller.h
Normal file
32
sw/kernel/devices/interrupt_controller.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef _INTERRUPT_CONTROLLER_H
|
||||||
|
#define _INTERRUPT_CONTROLLER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// These need to be copied in interrupt_controller.s
|
||||||
|
|
||||||
|
#define IRQ_CMD_ADDR 0xeffc
|
||||||
|
#define IRQ_DAT_ADDR 0xeffd
|
||||||
|
|
||||||
|
#define IRQ_CMD_MASK 0xe0
|
||||||
|
#define IRQ_REG_MASK 0x1f
|
||||||
|
|
||||||
|
#define IRQ_CMD_READIRQ 0x00
|
||||||
|
#define IRQ_CMD_ENABLE 0x20
|
||||||
|
#define IRQ_CMD_TYPE 0x40
|
||||||
|
#define IRQ_CMD_EOI 0xff
|
||||||
|
|
||||||
|
#define IRQ_EDGE 0
|
||||||
|
#define IRQ_LEVEL 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void init_interrupt_controller();
|
||||||
|
|
||||||
|
void enable_irq(uint8_t type, uint8_t irqnum);
|
||||||
|
void disable_irq(uint8_t irqnum);
|
||||||
|
|
||||||
|
// This should accept irqnum later.
|
||||||
|
void send_eoi();
|
||||||
|
|
||||||
|
#endif
|
||||||
136
sw/kernel/devices/interrupt_controller.s
Normal file
136
sw/kernel/devices/interrupt_controller.s
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
.MACPACK generic
|
||||||
|
|
||||||
|
.autoimport
|
||||||
|
|
||||||
|
.importzp tmp1, tmp2
|
||||||
|
|
||||||
|
.export _init_interrupt_controller
|
||||||
|
.export _enable_irq
|
||||||
|
.export _disable_irq
|
||||||
|
.export _send_eoi
|
||||||
|
|
||||||
|
IRQ_CMD_ADDR = $effc
|
||||||
|
IRQ_DAT_ADDR = $effd
|
||||||
|
|
||||||
|
IRQ_CMD_MASK = $e0
|
||||||
|
IRQ_REG_MASK = $1f
|
||||||
|
IRQ_CMD_READIRQ = $00
|
||||||
|
IRQ_CMD_ENABLE = $20
|
||||||
|
IRQ_CMD_TYPE = $40
|
||||||
|
IRQ_CMD_EOI = $ff
|
||||||
|
|
||||||
|
.code
|
||||||
|
|
||||||
|
; void init_irq();
|
||||||
|
; mask all IRQs, set all type to edge.
|
||||||
|
.proc _init_interrupt_controller
|
||||||
|
ldx #$20 ; enable
|
||||||
|
ldy #$ff
|
||||||
|
jsr cmd_all
|
||||||
|
ldx #$40 ; edge type
|
||||||
|
ldy #$00
|
||||||
|
jsr cmd_all
|
||||||
|
rts
|
||||||
|
|
||||||
|
cmd_all: ; Send the same value to all 32 bytes
|
||||||
|
txa
|
||||||
|
add #$20
|
||||||
|
sta tmp1
|
||||||
|
loop:
|
||||||
|
txa
|
||||||
|
sta IRQ_CMD_ADDR
|
||||||
|
tya
|
||||||
|
sta IRQ_DAT_ADDR
|
||||||
|
inx
|
||||||
|
cpx tmp1
|
||||||
|
blt loop
|
||||||
|
rts
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
; void enable_irq(uint8_t type, uint8_t irqnum);
|
||||||
|
; in A:
|
||||||
|
.proc _enable_irq
|
||||||
|
; Decide which byte we need to modify by dividing by 32 (>> 5)
|
||||||
|
pha
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr ; A is now bytesel
|
||||||
|
sta tmp2 ; tmp2 is now bytesel
|
||||||
|
add #IRQ_CMD_ENABLE
|
||||||
|
sta IRQ_CMD_ADDR
|
||||||
|
lda IRQ_DAT_ADDR
|
||||||
|
sta tmp1
|
||||||
|
pla
|
||||||
|
and $07 ; A is now 0-7
|
||||||
|
tax
|
||||||
|
inx ; X is now 1-8
|
||||||
|
lda #$01
|
||||||
|
L1: dex
|
||||||
|
beq L2
|
||||||
|
asl
|
||||||
|
bra L1
|
||||||
|
L2: pha ; Push bit mask to stack
|
||||||
|
ora tmp1 ; A is now 1 << (0-7) | enable
|
||||||
|
sta IRQ_DAT_ADDR
|
||||||
|
|
||||||
|
|
||||||
|
lda tmp2
|
||||||
|
add #IRQ_CMD_TYPE
|
||||||
|
sta IRQ_CMD_ADDR
|
||||||
|
lda IRQ_DAT_ADDR
|
||||||
|
sta tmp1
|
||||||
|
jsr popa ; A is now type
|
||||||
|
beq bit0
|
||||||
|
bit1: ; set `bit` to 1
|
||||||
|
pla
|
||||||
|
ora tmp1
|
||||||
|
bra L3
|
||||||
|
bit0: ; set `bit` to 0
|
||||||
|
pla
|
||||||
|
eor #$ff
|
||||||
|
and tmp1
|
||||||
|
L3: sta IRQ_DAT_ADDR
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
.proc _disable_irq
|
||||||
|
; Decide which byte we need to modify by dividing by 32 (>> 5)
|
||||||
|
pha
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
lsr ; A is now bytesel
|
||||||
|
add #IRQ_CMD_ENABLE
|
||||||
|
sta IRQ_CMD_ADDR
|
||||||
|
lda IRQ_DAT_ADDR
|
||||||
|
sta tmp1
|
||||||
|
pla
|
||||||
|
and $07 ; A is now 0-7
|
||||||
|
tax
|
||||||
|
inx ; X is now 1-8
|
||||||
|
lda #$01
|
||||||
|
L1: dex
|
||||||
|
beq L2
|
||||||
|
asl
|
||||||
|
bra L1
|
||||||
|
L2: eor #$ff ; Invert to set enable to 0
|
||||||
|
and tmp1 ; a is now ~(1 << (0-7)) & enable
|
||||||
|
sta IRQ_DAT_ADDR
|
||||||
|
rts
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
; This should accept irqnum later.
|
||||||
|
; void send_eoi();
|
||||||
|
.proc _send_eoi
|
||||||
|
lda #IRQ_CMD_EOI
|
||||||
|
sta IRQ_CMD_ADDR
|
||||||
|
lda #$1
|
||||||
|
sta IRQ_DAT_ADDR
|
||||||
|
rts
|
||||||
|
.endproc
|
||||||
|
|
||||||
16
sw/kernel/devices/rtc.h
Normal file
16
sw/kernel/devices/rtc.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _RTC_H
|
||||||
|
#define _RTC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define RTC_CMD_ADDR 0xeffe
|
||||||
|
#define RTC_DAT_ADDR 0xefff
|
||||||
|
|
||||||
|
/* initialize RTC with default values */
|
||||||
|
void init_rtc(void);
|
||||||
|
|
||||||
|
/* handle RTC interrupts */
|
||||||
|
void handle_rtc(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
78
sw/kernel/devices/rtc.s
Normal file
78
sw/kernel/devices/rtc.s
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
.MACPACK generic
|
||||||
|
|
||||||
|
.importzp tmp1
|
||||||
|
|
||||||
|
.export _init_rtc
|
||||||
|
.export _handle_rtc
|
||||||
|
|
||||||
|
RTC_CMD = $effe
|
||||||
|
RTC_DAT = $efff
|
||||||
|
|
||||||
|
RTC_THRESHOLD = $00
|
||||||
|
RTC_INCREMENT = $10
|
||||||
|
RTC_IRQ_THRESHOLD = $20
|
||||||
|
RTC_OUTPUT = $30
|
||||||
|
RTC_CONTROL = $30
|
||||||
|
|
||||||
|
; void init_rtc(void);
|
||||||
|
; Initialize rtc and generate 50ms interrupts
|
||||||
|
.proc _init_rtc
|
||||||
|
lda #RTC_INCREMENT+0 ; Set increment to 1
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$01
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_INCREMENT+1
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_INCREMENT+2
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_INCREMENT+3
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
|
||||||
|
lda #RTC_THRESHOLD+0 ; Set threshold to 4000 ($fa0)
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$a0
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_THRESHOLD+1
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$0f
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_THRESHOLD+2
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_THRESHOLD+3
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
|
||||||
|
lda #RTC_THRESHOLD+0 ; Set irq threshold to 50 ($32)
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$32
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_THRESHOLD+1
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_THRESHOLD+2
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
lda #RTC_THRESHOLD+3
|
||||||
|
sta RTC_CMD
|
||||||
|
lda #$00
|
||||||
|
sta RTC_DAT
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
.proc _handle_rtc
|
||||||
|
nop
|
||||||
|
rti
|
||||||
|
.endproc
|
||||||
@@ -1,25 +1,27 @@
|
|||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
#include "devices/interrupt_controller.h"
|
||||||
char* longstring = \
|
#include "devices/rtc.h"
|
||||||
"This is a very long string that is meant to test the loader.\
|
|
||||||
We can only load one cluster so far, which means 8 sectors of\
|
|
||||||
512bytes, or a total of 4k. If there was any more data than this,\
|
|
||||||
then we would have to traverse the fat to find the next cluster number.\
|
|
||||||
This may not be that difficult, but the file will need to be large\
|
|
||||||
enough to actually stretch that far. The kernel will probably be\
|
|
||||||
that big in the future, but for now when it doesnt really do anything\
|
|
||||||
then it can't really be tested.";
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
char* string = "this is a shorter string";
|
|
||||||
int val = 42;
|
|
||||||
cputs("Kernel\n");
|
|
||||||
cprintf("Kernel printf\n");
|
|
||||||
cprintf("Val: %d\n", val);
|
|
||||||
cprintf("%s", string);
|
|
||||||
|
|
||||||
cprintf("Here is a long string: %s\n", longstring);
|
cputs("Kernel\n");
|
||||||
|
|
||||||
|
// cputs("Init Paging")
|
||||||
|
// init_paging()
|
||||||
|
|
||||||
|
// cputs("Initialize Interrupts");
|
||||||
|
// init_interrupts();
|
||||||
|
|
||||||
|
cputs("Initialize Interrupt Controller");
|
||||||
|
init_interrupt_controller();
|
||||||
|
|
||||||
|
cputs("Initialize RTC");
|
||||||
|
init_rtc();
|
||||||
|
|
||||||
|
// cputs("Initialize Serial");
|
||||||
|
// // init_serial();
|
||||||
|
// enable_irq(2, IRQ_EDGE);
|
||||||
|
|
||||||
while(1);
|
while(1);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user