-Initial import

This commit is contained in:
2013-06-21 22:14:11 +02:00
commit 83d7e987b4
21 changed files with 1060 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
fw
fw.bin
fw.img

43
Makefile Normal file
View File

@@ -0,0 +1,43 @@
CC=arm-none-eabi-gcc
AS=arm-none-eabi-as
OBJCOPY=arm-none-eabi-objcopy
OBJDUMP=arm-none-eabi-objdump
CFLAGS=-march=armv7-a -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon --std=gnu99 -ggdb -Wall -Wextra -pedantic -Wno-unused-parameter -O1 -flto
LDFLAGS=
C_SRCS=cortexa8.c drv_omap35x_gpt.c main.c omap35x.c omap35x_intc.c uart.c syscall.c
S_SRCS=cortexa8_asm.s syscall_asm.s
OBJS=$(addprefix objs/,$(C_SRCS:.c=.o)) $(addprefix objs/,$(S_SRCS:.s=.o))
all: fw.img
fw: $(OBJS) fw.ld
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) -lc -T fw.ld
fw.bin: fw
$(OBJCOPY) -O binary $< $@
fw.img: fw.bin
./mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e `$(OBJDUMP) -f fw | grep "start address" | cut -d\ -f 3` -n none -d $< $@
beagle-nand.bin: fw.img
./bb_nandflash.sh $< $@ kernel >/dev/null 2>&1
./bb_nandflash_ecc $@ 0x0 0xe80000 || true
qemu: beagle-nand.bin
qemu-system-arm -M beagle -m 256M -mtdblock beagle-nand.bin -nographic
objs/%.o: %.c
$(CC) $(CFLAGS) -c -MMD -MP -o $@ $<
@cp objs/$*.d objs/$*.P; rm -f objs/$*.d
objs/%.o: %.s
$(AS) $(ASOPTS) -o $@ $<
clean:
rm -f $(OBJS) fw fw.bin fw.img
.PSEUDO=all clean qemu
-include $(addprefix objs/,$(C_SRCS:.c=.P))

147
bb_nandflash.sh Executable file
View File

@@ -0,0 +1,147 @@
#! /bin/sh
# Copyright (C) 2008 yajin (yajin@vm-kernel.org)
#
# Put the xloader,u-boot,kernel and rootfs into nand flash image.
#
#
# bb_nandflash.sh <x-loader-image> <nandflashimage> x-loader
# bb_nandflash.sh <u-boot-image> <nandflashimage> u-boot
# bb_nandflash.sh <kernel-image> <nandflashimage> kernel
# bb_nandflash.sh <rootfs> <nandflashimage> rootfs
# We assume that rootfs image has oob info
# while xloader u-boot and kernel image does not have oob info.
if [ ! -r "$1" ]; then
echo "Usage: $0 <image> <destimage> [<partition>]"
exit -1
fi
if [ 3 -ne "$#" ]; then
echo "Usage: $0 <image> <destimage> [<partition>]"
exit -1
fi
# Nand flash partitions
# 0x00000000-0x00080000 : "X-Loader"
# 0x00080000-0x00260000 : "U-Boot"
# 0x00260000-0x00280000 : "U-Boot Env"
# 0x00280000-0x00680000 : "Kernel"
# 0x00680000-0x10000000 : "File System"
flash_page_size=2048
flash_oob_size=64
flash_image_pages=131072
xloader_page_offset=0
uboot_page_offset=256
kernel_page_offset=1280
rootfs_page_offset=3328
flash_image_name=$2
xloader_image_name=$1
uboot_image_name=$1
kernel_image_name=$1
rootfs_image_name=$1
echo "flash image name:"$flash_image_name
#beagle board's NAND flash is 2G bit(256M bytes)
if [ ! -e "$2" ]; then
echo $flash_image_name" does not exist.Create it!"
echo -en \\0377\\0377\\0377\\0377\\0377\\0377\\0377\\0377 > .8b
cat .8b .8b > .16b
cat .16b .16b >.32b
cat .32b .32b >.64b #OOB is 64 bytes
cat .64b .64b .64b .64b .64b .64b .64b .64b > .512b
cat .512b .512b .512b .512b .64b>.page # A page is 2K bytes of data + 64bytes OOB
cat .page .page .page .page .page .page .page .page >.8page
cat .8page .8page .8page .8page .8page .8page .8page .8page >.block # a block = 64 pages
cat .block .block .block .block .block .block .block .block >.8block
cat .8block .8block .8block .8block .8block .8block .8block .8block >.64block
cat .64block .64block .64block .64block .64block .64block .64block .64block >.512block
cat .512block .512block .512block .512block >$flash_image_name
rm -rf .8b .16b .32b .64b .page .8page .64sec .block .8block .64block .512block
fi
put_no_oob()
{
#echo $1
#echo $2
image_name=$1
image_page_offset=$2
image_len=`du -shb $image_name |awk '{print $1}'`
image_pages=$[$image_len/2048]
if [ 0 -ne $[$image_len%$flash_page_size] ]; then
image_pages=$[$image_pages+1]
fi
#echo $image_len
#echo $image_pages
i=0
while [ $i -lt $image_pages ]
do
#echo $i
out_offset=$[$image_page_offset+$i]
in_offset=$i
#echo "out_offset:"$out_offset
#echo "in_offset:"$in_offset
dd if=$image_name of=$flash_image_name conv=notrunc count=1 obs=$[$flash_page_size+$flash_oob_size] ibs=$flash_page_size seek=$out_offset skip=$in_offset
i=$[$i + 1]
done
}
put_xloader()
{
echo "xloader image name:"$xloader_image_name
put_no_oob $1 $xloader_page_offset
echo "put xloader into flash image done!"
}
put_uboot()
{
echo "uboot image name:"$uboot_image_name
put_no_oob $1 $uboot_page_offset
echo "put u-boot into flash image done!"
}
put_kernel()
{
echo "Linux kernel image name:"$kernel_image_name
put_no_oob $1 $kernel_page_offset
echo "put Linux kernel into flash image done!"
}
put_rootfs()
{
echo "rootfs image name:"$rootfs_image_name
put_no_oob $1 $rootfs_page_offset
echo "put rootfs into flash image done!"
}
case "$3" in
x-loader)
put_xloader $1
;;
u-boot)
put_uboot $1
;;
kernel)
put_kernel $1
;;
rootfs)
put_rootfs $1
;;
*)
echo "Unknown partition $3"
exit -1
esac

BIN
bb_nandflash_ecc Executable file

Binary file not shown.

224
cortexa8.c Normal file
View File

@@ -0,0 +1,224 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "uart.h"
#include "cortexa8.h"
uint32_t cortexa8_read_cpuid(int reg) {
uint32_t rval;
switch(reg) {
case CORTEXA8_CPUID_MAINID:
__asm__ __volatile__ ("mrc 15, 0, %[res], c0, c0, 0"
: [res] "=r"(rval));
break;
case CORTEXA8_CPUID_CACHETYPE:
__asm__ __volatile__ ("mrc 15, 0, %[res], c0, c0, 1"
: [res] "=r"(rval));
break;
case CORTEXA8_CPUID_TLBTYPE:
__asm__ __volatile__ ("mrc 15, 0, %[res], c0, c0, 3"
: [res] "=r"(rval));
break;
case CORTEXA8_CPUID_PFR0:
__asm__ __volatile__ ("mrc 15, 0, %[res], c0, c1, 0"
: [res] "=r"(rval));
break;
case CORTEXA8_CPUID_PFR1:
__asm__ __volatile__ ("mrc 15, 0, %[res], c0, c1, 1"
: [res] "=r"(rval));
break;
default:
rval = 0xdeadbeef;
break;
}
return rval;
}
void cortexa8_enable_icache() {
uint32_t reg;
__asm__ __volatile__ ("mrc 15, 0, %[reg], c1, c0, 0; orr %[reg], %[reg], #0x1000; mcr 15, 0, %[reg], c1, c0, 0; isb"
: [reg] "=r"(reg));
}
void cortexa8_enable_dcache() {
uint32_t reg;
__asm__ __volatile__ ("mrc 15, 0, %[reg], c1, c0, 0; orr %[reg], %[reg], #0x4; mcr 15, 0, %[reg], c1, c0, 0"
: [reg] "=r"(reg));
}
void cortexa8_disable_icache() {
uint32_t reg;
__asm__ __volatile__ ("mrc 15, 0, %[reg], c1, c0, 0; bic %[reg], %[reg], #0x1000; mcr 15, 0, %[reg], c1, c0, 0; isb"
: [reg] "=r"(reg));
}
void cortexa8_disable_dcache() {
uint32_t reg;
__asm__ __volatile__ ("mrc 15, 0, %[reg], c1, c0, 0; bic %[reg], %[reg], #0x4; mcr 15, 0, %[reg], c1, c0, 0"
: [reg] "=r"(reg));
}
typedef struct {
unsigned :1;
unsigned one:1;
unsigned b:1;
unsigned c:1;
unsigned xn:1;
unsigned domain:4;
unsigned :1;
unsigned ap:2;
unsigned tex:3;
unsigned ap2:1;
unsigned s:1;
unsigned ng:1;
unsigned :1;
unsigned ns:1;
unsigned baseadr:12;
} ptentry_section_t;
static ptentry_section_t ttable1[4096] __attribute__((aligned(16384)));
void cortexa8_init_ttable() {
// Create 1:1 translation table for entire address space with appropriate memory types
memset((void*)ttable1, 0, 16384);
// 0x00000000..0x7fffffff MMIO (Non-cacheable)
for(int i = 0;i < 2048;++i) {
ttable1[i].baseadr = i;
ttable1[i].one = 1;
// Read/write at any privilege
ttable1[i].ap2 = 0;
ttable1[i].ap = 0x3;
// Shareable device
ttable1[i].tex = 0;
ttable1[i].c = 0;
ttable1[1].b = 1;
};
// 0x80000000..0x8fffffff RAM (Cacheable)
for(int i = 2048;i < 2304;++i) {
ttable1[i].baseadr = i;
ttable1[i].one = 1;
// Read/write at any privilege
ttable1[i].ap2 = 0;
ttable1[i].ap = 0x3;
// Cacheable
ttable1[i].tex = 0x5;
ttable1[i].c = 0;
ttable1[i].b = 1;
ttable1[i].s = 1;
};
// 0x90000000..0xffffffff ??? (Non-cacheable)
for(int i = 2304;i < 4095;++i) {
ttable1[i].baseadr = i;
ttable1[i].one = 1;
// Read/write at any privilege
ttable1[i].ap2 = 0;
ttable1[i].ap = 0x3;
// Shareable device
ttable1[i].tex = 0;
ttable1[i].c = 0;
ttable1[1].b = 1;
};
}
void cortexa8_init_mmu() {
cortexa8_init_ttable();
// Set Translation Table base Ptr 0
uint32_t reg = ((uint32_t)ttable1) & 0xffffc000u;
reg |= 0xb;
__asm__ __volatile__ ("mcr 15, 0, %[val], c2, c0, 0"
: : [val] "r"(reg));
// Set domains register
__asm__ __volatile__ ("mcr 15, 0, %[val], c3, c0, 0"
: : [val] "r"(0x1));
// Flush trans. table from L1$
for(int i = 0;i < 256;++i) {
reg = ((uint32_t)ttable1)+i*64;
__asm__ __volatile__ ("mcr 15, 0, %[val], c7, c11, 1"
: : [val] "r"(reg));
}
__asm__ __volatile__ ("dsb");
// Invalidate TLBs
__asm__ __volatile__ ("mcr 15, 0, r0, c8, c5, 0 ; mcr 15, 0, r0, c8, c6, 0; isb");
// Enable MMU
__asm__ __volatile__ ("mrc 15, 0, %[reg], c1, c0, 0; orr %[reg], %[reg], #0x1; mcr 15, 0, %[reg], c1, c0, 0; isb"
: [reg] "=r"(reg));
}
extern uint32_t __stack_excp;
extern uint32_t __stack_int;
extern void _vect_table;
void cortexa8_init_handlers() {
// Set stack pointers
cortexa8_set_und_sp(&__stack_excp);
cortexa8_set_abt_sp(&__stack_excp);
cortexa8_set_irq_sp(&__stack_int);
cortexa8_set_fiq_sp(&__stack_int);
// Set VBAR
__asm__ __volatile__("mcr 15, 0, %[reg], c12, c0, 0"
: : [reg] "r"(&_vect_table));
}
void cortexa8_excp_data_abt() __attribute__((interrupt ("ABORT")));
void cortexa8_excp_data_abt() {
uint32_t lr, dfar, dfsr;
__asm__ ("mov %[lr], lr; mrc 15, 0, %[dfsr], c5, c0, 0; mrc 15, 0, %[dfar], c6, c0, 0"
: [lr] "=r"(lr), [dfsr] "=r"(dfsr), [dfar] "=r"(dfar));
printf("ERROR: Data abort\n");
printf("PC: %.8lx Fault Address: %.8lx Fault code: %.lx\n",
lr-8, dfar, dfsr&0x4);
while(1) {}
}
void cortexa8_excp_pf_abt() __attribute__((interrupt ("ABORT")));
void cortexa8_excp_pf_abt() {
uint32_t lr, ifar, ifsr;
__asm__ ("mov %[lr], lr; mrc 15, 0, %[ifsr], c5, c0, 1; mrc 15, 0, %[ifar], c6, c0, 2"
: [lr] "=r"(lr), [ifsr] "=r"(ifsr), [ifar] "=r"(ifar));
printf("ERROR: Prefetch abort\n");
printf("PC: %.8lx Fault Address: %.8lx Fault code: %.lx\n",
lr-4, ifar, ifsr&0x4);
while(1) {}
}
void cortexa8_excp_undef() __attribute__((interrupt ("UNDEF")));
void cortexa8_excp_undef() {
uint32_t lr, spsr;
__asm__ ("mov %[lr], lr"
: [lr] "=r"(lr));
spsr = cortexa8_get_spsr();
printf("ERROR: Undefined instruction\n");
printf("PC: %.8lx\n",
lr-((spsr&0x20)?2:4));
while(1) {}
}
void cortexa8_syscall() __attribute__((interrupt ("SWI")));
void cortexa8_syscall() {
uart_write("Syscall NYI\n", 12);
}
void cortexa8_unhandled_fiq() __attribute__((interrupt ("FIQ")));
void cortexa8_unhandled_fiq() {
uart_write("UNHANDLED FINTERRUPT\n", 21);
}

37
cortexa8.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef _CORTEXA8_H_
#define _CORTEXA8_H_
#include <stdint.h>
#include <stdbool.h>
#define CORTEXA8_CPUID_MAINID 0
#define CORTEXA8_CPUID_CACHETYPE 1
#define CORTEXA8_CPUID_TLBTYPE 2
#define CORTEXA8_CPUID_PFR0 3
#define CORTEXA8_CPUID_PFR1 4
uint32_t cortexa8_read_cpuid(int reg);
void cortexa8_enable_icache();
void cortexa8_enable_dcache();
void cortexa8_disable_icache();
void cortexa8_disable_dcache();
void cortexa8_init_mmu();
void cortexa8_init_handlers();
// Implemented in cortexa8_asm.s
void cortexa8_ena_int();
void cortexa8_dis_int();
bool cortexa8_get_int();
void cortexa8_set_usr_sp(uint32_t *sp);
void cortexa8_set_abt_sp(uint32_t *sp);
void cortexa8_set_und_sp(uint32_t *sp);
void cortexa8_set_irq_sp(uint32_t *sp);
void cortexa8_set_fiq_sp(uint32_t *sp);
uint32_t cortexa8_get_spsr();
#endif

131
cortexa8_asm.s Normal file
View File

@@ -0,0 +1,131 @@
.global cortexa8_ena_int
cortexa8_ena_int:
mrs r0, cpsr
bic r0, r0, #0x80
msr cpsr, r0
bx lr
.global cortexa8_dis_int
cortexa8_dis_int:
mrs r0, cpsr
orr r0, r0, #0x80
msr cpsr, r0
bx lr
.global cortexa8_get_int
cortexa8_get_int:
mrs r0, cpsr
ands r0, r0, #0x80
moveq r0, #1
movne r0, #0
bx lr
.global cortexa8_set_usr_sp
cortexa8_set_usr_sp:
/* Read and save CPSR */
mrs r1, cpsr
mov r2, r1
/* Set mode to USR */
bfc r1, #0, #5
orr r1, r1, #0x10
/* Write CPSR */
msr cpsr, r1
/* Set SP in USR mode */
mov sp, r0
/* Restore original CPSR */
msr cpsr, r2
/* Return */
bx lr
.global cortexa8_set_abt_sp
cortexa8_set_abt_sp:
/* Read and save CPSR */
mrs r1, cpsr
mov r2, r1
/* Set mode to ABT */
bfc r1, #0, #5
orr r1, r1, #0x17
/* Write CPSR */
msr cpsr, r1
/* Set SP in ABT mode */
mov sp, r0
/* Restore original CPSR */
msr cpsr, r2
/* Return */
bx lr
.global cortexa8_set_und_sp
cortexa8_set_und_sp:
/* Read and save CPSR */
mrs r1, cpsr
mov r2, r1
/* Set mode to UND */
bfc r1, #0, #5
orr r1, r1, #0x1b
/* Write CPSR */
msr cpsr, r1
/* Set SP in UND mode */
mov sp, r0
/* Restore original CPSR */
msr cpsr, r2
/* Return */
bx lr
.global cortexa8_set_irq_sp
cortexa8_set_irq_sp:
/* Read and save CPSR */
mrs r1, cpsr
mov r2, r1
/* Set mode to IRQ */
bfc r1, #0, #5
orr r1, r1, #0x12
/* Write CPSR */
msr cpsr, r1
/* Set SP in IRQ mode */
mov sp, r0
/* Restore original CPSR */
msr cpsr, r2
/* Return */
bx lr
.global cortexa8_set_fiq_sp
cortexa8_set_fiq_sp:
/* Read and save CPSR */
mrs r1, cpsr
mov r2, r1
/* Set mode to FIQ */
bfc r1, #0, #5
orr r1, r1, #0x11
/* Write CPSR */
msr cpsr, r1
/* Set SP in FIQ mode */
mov sp, r0
/* Restore original CPSR */
msr cpsr, r2
/* Return */
bx lr
.global cortexa8_get_spsr
cortexa8_get_spsr:
mrs r0, spsr
bx lr
.global _vect_table
.align 5
_vect_table:
/* Reset / unused */
nop
/* Undefined instruction */
b cortexa8_excp_undef
/* Supervisor call */
b cortexa8_syscall
/* Prefetch abort */
b cortexa8_excp_pf_abt
/* Data abort */
b cortexa8_excp_data_abt
/* Unused */
nop
/* IRQ */
b omap35x_intc_handler
/* FIQ */
b cortexa8_unhandled_fiq

60
drv_omap35x_gpt.c Normal file
View File

@@ -0,0 +1,60 @@
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "drv_omap35x_gpt.h"
#include "omap35x_intc.h"
#define TIOCP_CFG 4
#define TISR 6
#define TIER 7
#define TWER 8
#define TCLR 9
#define TCRR 10
#define TLDR 11
#define TPIR 18
#define TNIR 19
int omap35x_gpt_init(omap35x_gpt_handle* handle, uint32_t base, int irq) {
assert(handle != NULL);
handle->base = (uint32_t*)base;
handle->irq = irq;
handle->handler = NULL;
handle->handler_data = NULL;
return 0;
}
void _omap35x_gpt_irqhandler(void *data);
int omap35x_gpt_ticktimer(omap35x_gpt_handle* handle, omap35x_intc_hfunc handler, void *data) {
assert(handle != NULL);
handle->base[TIOCP_CFG] = 0x215; // Clockactiviy = 2, emufree = 0, idlemode = 2 (smartidle), wakeup = ena, autoidle = 1
handle->base[TLDR] = -327;
handle->base[TCRR] = -327;
handle->base[TPIR] = 320000;
handle->base[TNIR] = -680000;
handle->handler = handler;
handle->handler_data = data;
omap35x_intc_register(handle->irq, &_omap35x_gpt_irqhandler, (void*)handle, 0);
handle->base[TCLR] = 0x3; // autoreload = 1, start = 1
handle->base[TIER] = 0x2; // Overflow int = enable
handle->base[TWER] = 0x2; // Overflow wakeup = enable
omap35x_intc_ena(handle->irq);
return 0;
}
void _omap35x_gpt_irqhandler(void *data) {
omap35x_gpt_handle *handle = (omap35x_gpt_handle*)data;
if(handle->handler != NULL)
handle->handler(handle->handler_data);
handle->base[TISR] = 0x2;
}

22
drv_omap35x_gpt.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef _DRV_OMAP35X_GPT_H_
#define _DRV_OMAP35X_GPT_H_
#include <stdint.h>
#include "omap35x_intc.h"
typedef struct {
uint32_t* base;
int irq;
omap35x_intc_hfunc handler;
void *handler_data;
} omap35x_gpt_handle;
// Initialize a General-Purpose Timer
int omap35x_gpt_init(omap35x_gpt_handle* handle, uint32_t base, int irq);
// Configure the GPT 'handle' as the system tick timer (10 ms)
// The GPT must be GPTIMER1, GPTIMER2 or GPTIMER10 because the 1ms-Tick functionality is needed
int omap35x_gpt_ticktimer(omap35x_gpt_handle* handle, omap35x_intc_hfunc handler, void *data);
#endif

39
fw.ld Normal file
View File

@@ -0,0 +1,39 @@
SECTIONS
{
. = 0x80008000;
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) }
.iplt : { *(.iplt) }
.text : {
/* startup.o (.text) */
*(.text)
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
.data : {
*(.rodata)
*(.data)
*(COMMON)
}
.bss (NOLOAD) : {
. = ALIGN(32 / 8);
__bss_start__ = .;
*(.bss)
__bss_end__ = . ;
}
. = ALIGN(64);
. = . + 0x200000; /* 2MiB stack should be enough... */
__stack = .;
. = . + 0x10000; /* 64KiB exception stack */
__stack_excp = .;
. = . + 0x10000; /* 64KiB interrupt stack */
__stack_int = .;
__heap_start = .; /* for _sbrk */
/* Rest until end of RAM is heap */
__heap_end = 0x90000000;
}

89
main.c Normal file
View File

@@ -0,0 +1,89 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "drv_omap35x_gpt.h"
#include "omap35x.h"
#include "omap35x_intc.h"
#include "cortexa8.h"
static volatile uint32_t *const prcm_fclken_per = (uint32_t*)0x48005000;
static volatile uint32_t *const prcm_iclken_per = (uint32_t*)0x48005010;
static volatile uint32_t *const prcm_autoidle_per = (uint32_t*)0x48005030;
static volatile uint32_t *const prcm_clksel_per = (uint32_t*)0x48005040;
static volatile uint32_t *const prcm_sleepdep_per = (uint32_t*)0x48005044;
static volatile uint32_t *const prcm_clkstctrl_per = (uint32_t*)0x48005048;
static volatile uint32_t *const prcm_mpugrpsel_per = (uint32_t*)0x483070a4;
static volatile uint32_t *const prcm_clkstctrl_mpu = (uint32_t*)0x48004948;
static volatile uint32_t tickctr = 0;
void tickfunc(void* data) {
++tickctr;
}
int main(int argc, char* argv[]) {
omap35x_print_chip_id();
// Enable caches
cortexa8_enable_icache();
cortexa8_enable_dcache();
printf("1\n");
// Configure interrrupt & exception handling
cortexa8_init_handlers();
omap35x_intc_init();
printf("2\n");
cortexa8_init_mmu();
printf("3\n");
// Enable interrupts
cortexa8_ena_int();
printf("4\n");
// Prepare GPTIMER2
*prcm_fclken_per |= (1<<3); // Enable GPT2 fclk
*prcm_iclken_per |= (1<<3); // Enable GPT2 iclk
*prcm_autoidle_per |= (1<<3); // Enable GPT2 iclk autoidle
*prcm_clksel_per &= ~(1<<0); // GPT2 fclk = 32.768kHz
*prcm_mpugrpsel_per |= (1<<3); // GPT2 wakes up MPU
//*prcm_mpugrpsel_per |= (1<<11); // UART3 wakes up MPU
*prcm_sleepdep_per |= (1<<1); // Enable PER-MPU sleep dep.
*prcm_clkstctrl_per |= 0x3; // Enable autosleep
printf("5\n");
omap35x_gpt_handle gpt2;
omap35x_gpt_init(&gpt2, 0x49032000, 38);
omap35x_gpt_ticktimer(&gpt2, &tickfunc, NULL);
printf("6\n");
*prcm_clkstctrl_mpu = 0x3;
printf("7\n");
while(1) {
__asm__ __volatile__ ("wfi");
if(tickctr%100 == 0) {
printf(".");
fflush(stdout);
}
}
malloc_stats();
return 0;
}

BIN
mkimage Executable file

Binary file not shown.

2
objs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.o
*.P

52
omap35x.c Normal file
View File

@@ -0,0 +1,52 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "omap35x.h"
static volatile uint32_t *const omap35x_omap_sr = (uint32_t*)0x4800244c; // 1 word
static volatile uint32_t *const omap35x_idcode = (uint32_t*)0x4830a204; // 1 dword
static volatile uint32_t *const omap35x_die_id = (uint32_t*)0x4830a218; // 4 dwords
static volatile uint32_t *const omap35x_skuid = (uint32_t*)0x4830a20c; // 1 dword
static const char *const omap_names[] = {"OMAP3530", "OMAP3525", "OMAP3515", "OMAP3503", "UNKNOWN"};
static const char *const omap_ver[] = {"ES 1.0", "ES 2.0", "ES 2.1", "ES 3.0", "ES 3.1", "UNKNOWN", "UNKNOWN", "ES 3.1.2"};
void omap35x_print_chip_id() {
uint16_t omapsr = *omap35x_omap_sr&0xffffu;
int omapsr_idx;
switch(omapsr) {
case 0x0c00:
omapsr_idx = 0;
break;
case 0x4c00:
omapsr_idx = 1;
break;
case 0x1c00:
omapsr_idx = 2;
break;
case 0x5c00:
omapsr_idx = 3;
break;
default:
printf("Warning: Unknown OMAP35x type (%.8lx)\n", *omap35x_omap_sr);
omapsr_idx = 4;
break;
}
uint32_t idcode = *omap35x_idcode;
int id_idx = (idcode&0xf0000000u)>>28;
if(id_idx > 7) // Versions 8..15 are unknown
id_idx = 6;
if(id_idx == 5 || id_idx == 6)
printf("Warning: Unknown OMAP35x version (%.8lx)\n", idcode);
bool highfreq = false;
if((*omap35x_skuid&0xf) == 0x8)
highfreq = true;
printf("%s %s %s Serial# %.8lx%.8lx%.8lx%.8lx\n",
omap_names[omapsr_idx], omap_ver[id_idx],
highfreq?"720 MHz":"600 MHz",
omap35x_die_id[3], omap35x_die_id[2], omap35x_die_id[1], omap35x_die_id[0]);
}

6
omap35x.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _OMAP35X_H_
#define _OMAP35X_H_
void omap35x_print_chip_id();
#endif

87
omap35x_intc.c Normal file
View File

@@ -0,0 +1,87 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "omap35x_intc.h"
#include "cortexa8.h"
static volatile uint32_t *const intc_sysconfig = (uint32_t*)0x48200010;
static volatile uint32_t *const intc_idle = (uint32_t*)0x48200050;
static volatile uint32_t *const intc_mir_clear0 = (uint32_t*)0x48200088;
static volatile uint32_t *const intc_mir_clear1 = (uint32_t*)0x482000a8;
static volatile uint32_t *const intc_mir_clear2 = (uint32_t*)0x482000c8;
static volatile uint32_t *const intc_mir_set0 = (uint32_t*)0x4820008c;
static volatile uint32_t *const intc_mir_set1 = (uint32_t*)0x482000ac;
static volatile uint32_t *const intc_mir_set2 = (uint32_t*)0x482000cc;
static volatile uint32_t *const intc_sir_irq = (uint32_t*)0x48200040;
static volatile uint32_t *const intc_control = (uint32_t*)0x48200048;
static volatile uint32_t *const intc_ilr = (uint32_t*)0x48200100; // 96 words
static omap35x_intc_hfunc handler_tbl[96];
static void* handler_data[96];
void omap35x_intc_init() {
// Interrupts should (still) be disabled from boot
assert(!cortexa8_get_int());
memset(handler_tbl, 0, sizeof(omap35x_intc_hfunc)*96);
*intc_sysconfig = 0x1; // Autoidle = 1
*intc_idle = 0x2; // Turbo = 1, Funcidle = 0
// Disable all ints
*intc_mir_set0 = 0xffffffff;
*intc_mir_set1 = 0xffffffff;
*intc_mir_set2 = 0xffffffff;
}
void omap35x_intc_register(int irq, omap35x_intc_hfunc handler, void *data, int prio) {
assert(irq >= 0 && irq <= 95);
assert(prio >= 0 && prio <= 63);
handler_tbl[irq] = handler;
handler_data[irq] = data;
intc_ilr[irq] = prio<<2;
}
void omap35x_intc_ena(int irq) {
assert(irq >= 0 && irq <= 95);
assert(handler_tbl[irq] != NULL);
int i = irq/32, j = irq%32;
if(i == 0)
*intc_mir_clear0 = (1<<j);
else if(i == 1)
*intc_mir_clear1 = (1<<j);
else //if(i == 2)
*intc_mir_clear2 = (1<<j);
}
void omap35x_intc_dis(int irq) {
assert(irq >= 0 && irq <= 95);
int i = irq/32, j = irq%32;
if(i == 0)
*intc_mir_set0 = (1<<j);
else if(i == 1)
*intc_mir_set1 = (1<<j);
else //if(i == 2)
*intc_mir_set2 = (1<<j);
}
void omap35x_intc_handler() __attribute__((interrupt ("IRQ")));
void omap35x_intc_handler() {
uint32_t sir = *intc_sir_irq;
int irq = sir&0x7f;
if(sir&0xffffff80) {
printf("WARNING: Spurious interrupt (%.8lx)\n", sir);
return;
}
assert(irq >= 0 && irq <= 95);
assert(handler_tbl[irq] != NULL);
handler_tbl[irq](handler_data[irq]);
*intc_control = 0x1;
__asm__ __volatile__ ("dsb");
}

13
omap35x_intc.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef OMAP35X_INTC_H
#define OMAP35X_INTC_H
typedef void (*omap35x_intc_hfunc)(void*);
void omap35x_intc_init();
void omap35x_intc_register(int irq, omap35x_intc_hfunc handler, void* data, int prio);
void omap35x_intc_ena(int irq);
void omap35x_intc_dis(int irq);
#endif

72
syscall.c Normal file
View File

@@ -0,0 +1,72 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#undef errno
extern int errno;
#include "uart.h"
int _close(int file) __attribute__((used));
int _close(int file) {
return -1;
}
int _lseek(int file, int ptr, int dir) __attribute__((used));
int _lseek(int file, int ptr, int dir) {
return 0;
}
int _fstat(int file, struct stat *st) __attribute__((used));
int _fstat(int file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int file) __attribute__((used));
int _isatty(int file) {
return 1;
}
int _read(int file, char *ptr, int len) __attribute__((used));
int _read(int file, char *ptr, int len) {
return 0;
}
int _write(int file, char *ptr, int len) __attribute__((used));
int _write(int file, char *ptr, int len) {
// if(file != 1 && file != 2) // Only stdout supported
//return 0;
uart_write(ptr, len);
return len;
}
extern char __heap_end, __heap_start;
caddr_t _sbrk(int incr) __attribute__((used));
caddr_t _sbrk(int incr) {
static caddr_t heap_end = 0;
if(heap_end == 0)
heap_end = &__heap_start;
caddr_t prev_heap_end = heap_end;
if(heap_end + incr > &__heap_end) {
_write(1, "Out of memory\n", 14);
abort();
}
heap_end += incr;
return prev_heap_end;
}
int _kill(int pid, int sig) __attribute__((used));
int _kill(int pid, int sig) {
errno = EINVAL;
return -1;
}
int _getpid(void) __attribute__((used));
int _getpid(void) {
return 1;
}

6
syscall_asm.s Normal file
View File

@@ -0,0 +1,6 @@
.global _exit
_exit:
mrs r1, CPSR
wfi
b _exit

20
uart.c Normal file
View File

@@ -0,0 +1,20 @@
#include <stdint.h>
#include "uart.h"
static volatile uint32_t *const uart_data = (uint32_t*)0x49020000;
static volatile uint32_t *const uart_status = (uint32_t*)0x49020044;
static void _uart_wait_txnotfull() {
while(*uart_status & 0x1) {}
}
void uart_sendb(char b) {
_uart_wait_txnotfull();
*uart_data = b;
}
void uart_write(const char *data, int len) {
for(int i = 0;i < len;++i)
uart_sendb(*data++);
}

7
uart.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _UART_H_
#define _UART_H_
void uart_sendb(char b);
void uart_write(const char *data, int len);
#endif