Interrupts, IPC, moar stuff

This commit is contained in:
marcan 2009-01-08 23:27:22 +01:00
parent 599839a7f9
commit b80e7b74dd
16 changed files with 359 additions and 73 deletions

View File

@ -1,6 +1,6 @@
include ../toolchain.rules
CFLAGS = -mbig-endian -fomit-frame-pointer -Os -Wall -I.
CFLAGS = -mbig-endian -fomit-frame-pointer -Os -Wall -I.
ASFLAGS = -mbig-endian
LDFLAGS = -nostartfiles -nodefaultlibs -mbig-endian -Wl,-T,miniios.ld,-Map,miniios.map -n
LIBS = -lgcc
@ -10,8 +10,8 @@ MAKEBIN = python ../makebin.py
TARGET = miniios.bin
ELF = miniios.elf
OBJECTS = start.o main.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o
OBJECTS = start.o ipcstruct.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o irq.o irq_asm.o
$(TARGET) : $(ELF) $(ELFLOADER)
@echo "MAKEBIN $@"
@ -23,7 +23,7 @@ $(ELF) : miniios.ld $(OBJECTS)
%.o : %.S
@echo "AS $@"
@$(AS) $(ASFLAGS) -o $@ $<
@$(CC) $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c -x assembler-with-cpp -o $@ $<
%.o : %.c
@echo "CC $@"

View File

@ -10,7 +10,7 @@
#include <string.h>
static sdhci_t sdhci;
static u8 *buffer[512] __attribute__((aligned(32)));
static u8 buffer[512] MEM2_BSS ALIGNED(32);
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */

View File

@ -131,6 +131,8 @@
// maybe a GPIO???
#define HW_RESETS (HW_REG_BASE + 0x194)
#define HW_CLOCKS (HW_REG_BASE + 0x1b4)
#define HW_GPIO2OUT (HW_REG_BASE + 0x1c8)
#define HW_GPIO2DIR (HW_REG_BASE + 0x1cc)
#define HW_GPIO2IN (HW_REG_BASE + 0x1d0)

0
ipc.c Normal file
View File

29
ipcstruct.S Normal file
View File

@ -0,0 +1,29 @@
#include "ipcstruct.h"
.section .rodata.ipc,"a",%progbits
.globl ipc_header
.type ipc_header, %object
.size ipc_header, 32
.align 5
ipc_header:
.ascii "IPC1"
.long 0
.long ipc_in
.long 32
.long ipc_out
.long 32
.section .bss.ipc,"aw",%nobits
.globl ipc_in
.type ipc_in, %object
.size ipc_in, 32 * IPC_IN_SIZE
.align 5
ipc_in:
.space 32 * IPC_IN_SIZE
.globl ipc_out
.type ipc_out, %object
.size ipc_out, 32 * IPC_OUT_SIZE
.align 5
ipc_out:
.space 32 * IPC_IN_SIZE

11
ipcstruct.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef __IPCSTRUCT_H__
#define __IPCSTRUCT_H__
#define IPC_IN_SIZE 32
#define IPC_OUT_SIZE 32
#ifndef _LANGUAGE_ASSEMBLY
#endif
#endif

81
irq.c Normal file
View File

@ -0,0 +1,81 @@
#include "irq.h"
#include "hollywood.h"
#include "gecko.h"
#include "utils.h"
void irq_setup_stack(void);
void irq_initialize(void)
{
irq_setup_stack();
write32(HW_IRQENABLE, 0);
write32(HW_IRQFLAG, 0xffffffff);
irq_restore(CPSR_FIQDIS);
//???
write32(HW_IRQENABLE+0x04, 0);
write32(HW_IRQENABLE+0x20, 0);
}
void irq_shutdown(void)
{
write32(HW_IRQENABLE, 0);
write32(HW_IRQFLAG, 0xffffffff);
irq_kill();
}
void irq_handler(void)
{
u32 enabled = read32(HW_IRQENABLE);
u32 flags = read32(HW_IRQFLAG);
gecko_printf("In IRQ handler: 0x%08x 0x%08x 0x%08x\n", enabled, flags, flags & enabled);
flags = flags & enabled;
if(flags & IRQF_TIMER) {
gecko_printf("IRQ: timer\n");
gecko_printf("Timer: %08x\n", read32(HW_TIMER));
gecko_printf("Alarm: %08x\n", read32(HW_ALARM));
write32(HW_ALARM, 0); // shut it up
write32(HW_IRQFLAG, IRQF_TIMER);
}
if(flags & IRQF_NAND) {
gecko_printf("IRQ: NAND\n");
write32(NAND_CMD, 0x7fffffff); // shut it up
write32(HW_IRQFLAG, IRQF_NAND);
}
if(flags & IRQF_GPIO1B) {
gecko_printf("IRQ: GPIO1B\n");
write32(HW_GPIO1BINTFLAG, 0xFFFFFF); // shut it up
write32(HW_IRQFLAG, IRQF_GPIO1B);
}
if(flags & IRQF_GPIO1) {
gecko_printf("IRQ: GPIO1\n");
write32(HW_GPIO1INTFLAG, 0xFFFFFF); // shut it up
write32(HW_IRQFLAG, IRQF_GPIO1);
}
if(flags & IRQF_RESET) {
gecko_printf("IRQ: RESET\n");
write32(HW_IRQFLAG, IRQF_RESET);
}
if(flags & IRQF_IPC) {
gecko_printf("IRQ: IPC\n");
write32(HW_IRQFLAG, IRQF_IPC);
}
flags &= ~IRQF_ALL;
if(flags) {
gecko_printf("IRQ: unknown 0x%08x\n");
write32(HW_IRQFLAG, flags);
}
}
void irq_enable(u32 irq)
{
set32(HW_IRQENABLE, 1<<irq);
}
void irq_disable(u32 irq)
{
clear32(HW_IRQENABLE, 1<<irq);
}

40
irq.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __IRQ_H__
#define __IRQ_H__
#define IRQ_TIMER 0
#define IRQ_NAND 1
#define IRQ_GPIO1B 10
#define IRQ_GPIO1 11
#define IRQ_RESET 17
#define IRQ_IPC 31
#define IRQF_TIMER (1<<IRQ_TIMER)
#define IRQF_NAND (1<<IRQ_NAND)
#define IRQF_GPIO1B (1<<IRQ_GPIO1B)
#define IRQF_GPIO1 (1<<IRQ_GPIO1)
#define IRQF_RESET (1<<IRQ_RESET)
#define IRQF_IPC (1<<IRQ_IPC)
#define IRQF_ALL ( \
IRQF_TIMER|IRQF_NAND|IRQF_GPIO1B|IRQF_GPIO1| \
IRQF_RESET|IRQF_IPC \
)
#define CPSR_IRQDIS 0x80
#define CPSR_FIQDIS 0x40
#ifndef _LANGUAGE_ASSEMBLY
#include "types.h"
void irq_initialize(void);
void irq_shutdown(void);
void irq_enable(u32 irq);
void irq_disable(u32 irq);
u32 irq_kill(void);
void irq_restore(u32 cookie);
#endif
#endif

46
irq_asm.S Normal file
View File

@ -0,0 +1,46 @@
#include "hollywood.h"
#include "irq.h"
.globl v_irq
.globl irq_setup_stack
.globl irq_kill
.globl irq_restore
.extern __irqstack_addr
.extern irq_handler
irq_setup_stack:
@ Switch to IRQ mode
mrs r0, cpsr
bic r1, r0, #0x1f
orr r1, #0x12
msr cpsr, r1
@ Setup interrupt stack
ldr sp, =__stack_addr
add sp, r4
@ Restore mode
msr cpsr, r0
bx lr
v_irq:
push {r0-r3, r9, r12, lr}
blx irq_handler
pop {r0-r3, r9, r12, lr}
subs pc, lr, #4
irq_kill:
mrs r1, cpsr
and r0, r1, #(CPSR_IRQDIS|CPSR_FIQDIS)
orr r1, r1, #(CPSR_IRQDIS|CPSR_FIQDIS)
msr cpsr, r1
bx lr
irq_restore:
mrs r1, cpsr
bic r1, r1, #(CPSR_IRQDIS|CPSR_FIQDIS)
orr r1, r1, r0
msr cpsr, r1
bx lr

18
main.c
View File

@ -10,6 +10,7 @@
#include "ff.h"
#include "panic.h"
#include "powerpc_elf.h"
#include "irq.h"
typedef struct {
u32 hdrsize;
@ -152,6 +153,15 @@ void *_main(void *base)
gecko_printf("Error %d while trying to mount SD\n", fres);
panic2(0, PANIC_MOUNT);
}
irq_initialize();
irq_enable(IRQ_TIMER);
irq_enable(IRQ_NAND);
irq_enable(IRQ_GPIO1B);
irq_enable(IRQ_GPIO1);
irq_enable(IRQ_RESET);
irq_enable(IRQ_IPC);
gecko_puts("Interrupts initialized\n");
gecko_puts("Trying to boot:" PPC_BOOT_FILE "\n");
@ -180,7 +190,11 @@ void *_main(void *base)
}
}
void *bootmii = patch_boot2(base, (((u64)tidh)<<32) | tidl);
gecko_puts("Shutting down interrupts\n");
irq_shutdown();
gecko_puts("Returning to BootMii...\n");
return patch_boot2(base, (((u64)tidh)<<32) | tidl);
return bootmii;
}

View File

@ -3,35 +3,65 @@ OUTPUT_ARCH(arm)
EXTERN(_start)
ENTRY(_start)
__base_addr = 0xffff0000;
__stack_size = 0x800;
__irqstack_size = 0x100;
__data_addr = 0x11000000;
__stack_area = 0xfffe0000;
MEMORY {
sram : ORIGIN = 0xffff0000, LENGTH = 64K
sram2 : ORIGIN = 0xfffe0000, LENGTH = 32K
mem2 : ORIGIN = 0x13f00000, LENGTH = 1M
}
SECTIONS
{
. = __base_addr;
.rodata.ipc :
{
*(.rodata.ipc)
. = ALIGN(4);
} >mem2
.bss.ipc :
{
*(.bss.ipc)
. = ALIGN(4);
} >mem2
.rodata.mem2 :
{
*(.rodata.mem2)
. = ALIGN(4);
} >mem2
.data.mem2 :
{
*(.data.mem2)
. = ALIGN(4);
} >mem2
.bss.mem2 :
{
__bss2_start = . ;
*(.bss.mem2)
. = ALIGN(4);
__bss2_end = . ;
} >mem2
.init :
{
*(.init)
. = ALIGN(4);
}
} >sram
.text :
{
*(.text*)
*(.text.*)
*(.gnu.warning)
*(.gnu.linkonce.t*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
}
__text_end = . ;
. = __data_addr;
} >sram
.rodata :
{
@ -41,7 +71,7 @@ SECTIONS
*(.rodata.*)
*(.gnu.linkonce.r*)
. = ALIGN(4);
}
} >sram2
.data :
{
@ -49,7 +79,7 @@ SECTIONS
*(.data.*)
*(.gnu.linkonce.d*)
. = ALIGN(4);
}
} >sram2
.bss :
{
@ -61,23 +91,27 @@ SECTIONS
*(COMMON)
. = ALIGN(4);
__bss_end = . ;
}
} >sram2
. = __stack_area;
.stack :
{
__stack_end = .;
. += 0x800;
LONG(0);
. = . +__stack_size;
. = ALIGN(64);
__stack_addr = .;
}
__end = .;
__irqstack_end = .;
. = . +__irqstack_size;
. = ALIGN(64);
__irqstack_addr = .;
} >sram2
}
PROVIDE (__stack_end = __stack_end);
PROVIDE (__stack_addr = __stack_addr);
PROVIDE (__irqstack_end = __irqstack_end);
PROVIDE (__irqstack_addr = __irqstack_addr);
PROVIDE (__bss_start = __bss_start);
PROVIDE (__bss_end = __bss_end);
PROVIDE (__bss2_start = __bss2_start);
PROVIDE (__bss2_end = __bss2_end);

52
start.S
View File

@ -5,11 +5,13 @@
.extern __got_end
.extern __bss_start
.extern __bss_end
.extern __bss2_start
.extern __bss2_end
.extern __stack_addr
.globl _start
.globl debug_output
.globl panic
.globl delay
.extern v_irq
.section .init
@ -54,6 +56,22 @@ bss_loop:
b bss_loop
done_bss:
@ clear BSS2
ldr r1, =__bss2_start
add r1, r4
ldr r2, =__bss2_end
add r2, r4
mov r3, #0
bss2_loop:
@ check for the end
cmp r1, r2
beq done_bss2
@ clear the word and move on
str r3, [r1]
add r1, r1, #4
b bss2_loop
done_bss2:
mov r0, #0x84
bl debug_output
@ take the plunge
@ -79,8 +97,8 @@ v_data_abrt:
v_reserved:
b v_reserved
v_irq:
b v_irq
#v_irq:
# b v_irq
v_fiq:
b v_fiq
@ -97,30 +115,6 @@ debug_output:
orr r2, r2, r0, LSL #16
@ store back
str r2, [r3, #0xe0]
mov pc, lr
panic:
mov r4, r0
_panic:
mov r0, r4
bl debug_output
ldr r0, =6175000
bl delay
mov r0, #0x00
bl debug_output
ldr r0, =6175000
bl delay
b _panic
@ the speed of this seems to decrease wildly with certain (non-)alignments
@ probably some prefetch buffer / cache / DRAM junk
.balign 64
delay:
cmp r0, #0
moveq pc, lr
1:
subs r0, r0, #1
bne 1b
mov pc, lr
bx lr
.pool

View File

@ -3,11 +3,6 @@
#include "types.h"
void delay(u32 delay);
#define udelay(d) delay(247*(d)/10)
void debug_output(u8 byte);
void panic(u8 code);
#endif

16
types.h
View File

@ -23,6 +23,20 @@ typedef volatile signed long long vs64;
typedef s32 size_t;
#define NULL ((void *)0)
#define NULL ((void *)0)
#define MEM2_BSS __attribute__ ((section (".bss.mem2")))
#define MEM2_DATA __attribute__ ((section (".data.mem2")))
#define MEM2_RODATA __attribute__ ((section (".rodata.mem2")))
#define ALIGNED(x) __attribute__((aligned(x)))
#define STACK_ALIGN(type, name, cnt, alignment) \
u8 _al__##name[((sizeof(type)*(cnt)) + (alignment) + \
(((sizeof(type)*(cnt))%(alignment)) > 0 ? ((alignment) - \
((sizeof(type)*(cnt))%(alignment))) : 0))]; \
type *name = (type*)(((u32)(_al__##name)) + ((alignment) - (( \
(u32)(_al__##name))&((alignment)-1))))
#endif

34
utils.c
View File

@ -2,6 +2,8 @@
#include "utils.h"
#include "gecko.h"
#include "vsprintf.h"
#include "start.h"
#include "hollywood.h"
static char ascii(char s) {
if(s < 0x20) return '.';
@ -38,3 +40,35 @@ int sprintf(char *str, const char *fmt, ...)
return i;
}
void udelay(u32 d)
{
// should be good to max .2% error
u32 ticks = d * 19 / 10;
if(ticks < 2)
ticks = 2;
u32 now = read32(HW_TIMER);
u32 then = now + ticks;
if(then < now) {
while(read32(HW_TIMER) >= now);
now = read32(HW_TIMER);
}
while(now < then) {
now = read32(HW_TIMER);
}
}
void panic(u8 v)
{
while(1) {
debug_output(v);
udelay(500000);
debug_output(0);
udelay(500000);
}
}

12
utils.h
View File

@ -160,16 +160,6 @@ static inline u8 mask8(u32 addr, u8 clear, u8 set)
return data;
}
#define STACK_ALIGN(type, name, cnt, alignment) \
u8 _al__##name[((sizeof(type)*(cnt)) + (alignment) + \
(((sizeof(type)*(cnt))%(alignment)) > 0 ? ((alignment) - \
((sizeof(type)*(cnt))%(alignment))) : 0))]; \
type *name = (type*)(((u32)(_al__##name)) + ((alignment) - (( \
(u32)(_al__##name))&((alignment)-1))))
#define ATTRIBUTE_ALIGN(v) __attribute__((aligned(v)))
/*
* These functions are guaranteed to copy by reading from src and writing to dst in <n>-bit units
* If size is not aligned, the remaining bytes are not copied
@ -183,5 +173,7 @@ void memcpy8(void *dst, void *src, u32 size);
void hexdump(void *d, int len);
int sprintf(char *str, const char *fmt, ...);
void udelay(u32 d);
void panic(u8 v);
#endif