1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 01:16:43 +03:00
This commit is contained in:
Bas Wijnen 2009-06-01 19:22:11 +02:00
parent aa7263c565
commit b39c710e87
4 changed files with 277 additions and 20 deletions

182
boot-programs/gpio.txt Normal file
View File

@ -0,0 +1,182 @@
GPIO control:
#define GPIO_BASE 0xB0010000
#define IRQ_GPIO3 25
#define IRQ_GPIO2 26
#define IRQ_GPIO1 27
#define IRQ_GPIO0 28
#define GPIO_IRQ_LOLEVEL 0
#define GPIO_IRQ_HILEVEL 1
#define GPIO_IRQ_FALLEDG 2
#define GPIO_IRQ_RAISEDG 3
// GP ... Registers: one set for each port of 32 pins; total 128 pins means 4 groups. Total size: 4 * 0x30 == 0xc0.
#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30)) // D: data
#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) // DI: data in: 1 is input; 0 is output. Disable interrupts on the pin before touching this.
#define GPIO_GPODR(n) (GPIO_BASE + (0x08 + (n)*0x30)) // OD:
#define GPIO_GPPUR(n) (GPIO_BASE + (0x0c + (n)*0x30)) // PU: pull-up (1 is enable)
#define GPIO_GPALR(n) (GPIO_BASE + (0x10 + (n)*0x30)) // AL: alternate lower: per 2 bit; 00 means use as gpio; other values mean use as alternate function
#define GPIO_GPAUR(n) (GPIO_BASE + (0x14 + (n)*0x30)) // AU: alternate upper: same thing, needs 2 registers because it's 2 bits per pin.
#define GPIO_GPIDLR(n) (GPIO_BASE + (0x18 + (n)*0x30)) // IDL: interrupt detect lower: per 2 bit (GPIO_IRQ_*)
#define GPIO_GPIDUR(n) (GPIO_BASE + (0x1c + (n)*0x30)) // IDU: interrupt detect upper: same thing, upper 16 bit
#define GPIO_GPIER(n) (GPIO_BASE + (0x20 + (n)*0x30)) // IE: interrupt enable (0 is disable)
#define GPIO_GPIMR(n) (GPIO_BASE + (0x24 + (n)*0x30)) // IM:
#define GPIO_GPFR(n) (GPIO_BASE + (0x28 + (n)*0x30)) // F: flag: set on interrupt; cleared by user.
#define IRQ_GPIO_0 48
#define NUM_GPIO 128
// Pins for alternate functions:
#define __gpio_as_ssi() \
do { \
REG_GPIO_GPALR(2) &= 0xFC00FFFF; \
REG_GPIO_GPALR(2) |= 0x01550000; \
} while (0)
#define __gpio_as_uart3() \
do { \
REG_GPIO_GPAUR(0) &= 0xFFFF0000; \
REG_GPIO_GPAUR(0) |= 0x00005555; \
} while (0)
#define __gpio_as_uart2() \
do { \
REG_GPIO_GPALR(3) &= 0x3FFFFFFF; \
REG_GPIO_GPALR(3) |= 0x40000000; \
REG_GPIO_GPAUR(3) &= 0xF3FFFFFF; \
REG_GPIO_GPAUR(3) |= 0x04000000; \
} while (0)
#define __gpio_as_uart1() \
do { \
REG_GPIO_GPAUR(0) &= 0xFFF0FFFF; \
REG_GPIO_GPAUR(0) |= 0x00050000; \
} while (0)
#define __gpio_as_uart0() \
do { \
REG_GPIO_GPAUR(3) &= 0x0FFFFFFF; \
REG_GPIO_GPAUR(3) |= 0x50000000; \
} while (0)
#define __gpio_as_scc0() \
do { \
REG_GPIO_GPALR(2) &= 0xFFFFFFCC; \
REG_GPIO_GPALR(2) |= 0x00000011; \
} while (0)
#define __gpio_as_scc1() \
do { \
REG_GPIO_GPALR(2) &= 0xFFFFFF33; \
REG_GPIO_GPALR(2) |= 0x00000044; \
} while (0)
#define __gpio_as_scc() \
do { \
__gpio_as_scc0(); \
__gpio_as_scc1(); \
} while (0)
#define __gpio_as_dma() \
do { \
REG_GPIO_GPALR(0) &= 0x00FFFFFF; \
REG_GPIO_GPALR(0) |= 0x55000000; \
REG_GPIO_GPAUR(0) &= 0xFF0FFFFF; \
REG_GPIO_GPAUR(0) |= 0x00500000; \
} while (0)
#define __gpio_as_msc() \
do { \
REG_GPIO_GPALR(1) &= 0xFFFF000F; \
REG_GPIO_GPALR(1) |= 0x00005550; \
} while (0)
#define __gpio_as_pcmcia() \
do { \
REG_GPIO_GPAUR(2) &= 0xF000FFFF; \
REG_GPIO_GPAUR(2) |= 0x05550000; \
} while (0)
#define __gpio_as_emc(csmask) \
do { \
REG_GPIO_GPALR(2) &= 0x3FFFFFFF; \
REG_GPIO_GPALR(2) |= 0x40000000; \
REG_GPIO_GPAUR(2) &= 0xFFFF0000; \
REG_GPIO_GPAUR(2) |= 0x00005555; \
} while (0)
#define __gpio_as_lcd_slave() \
do { \
REG_GPIO_GPALR(1) &= 0x0000FFFF; \
REG_GPIO_GPALR(1) |= 0x55550000; \
REG_GPIO_GPAUR(1) &= 0x00000000; \
REG_GPIO_GPAUR(1) |= 0x55555555; \
} while (0)
#define __gpio_as_lcd_master() \
do { \
REG_GPIO_GPALR(1) &= 0x0000FFFF; \
REG_GPIO_GPALR(1) |= 0x55550000; \
REG_GPIO_GPAUR(1) &= 0x00000000; \
REG_GPIO_GPAUR(1) |= 0x556A5555; \
} while (0)
#define __gpio_as_usb() \
do { \
REG_GPIO_GPAUR(0) &= 0x00FFFFFF; \
REG_GPIO_GPAUR(0) |= 0x55000000; \
} while (0)
#define __gpio_as_ac97() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF03FF; \
REG_GPIO_GPALR(2) |= 0x24005400; \
} while (0)
#define __gpio_as_i2s_slave() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \
REG_GPIO_GPALR(2) |= 0x14005100; \
} while (0)
#define __gpio_as_i2s_master() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \
REG_GPIO_GPALR(2) |= 0x28005100; \
} while (0)
#define __gpio_as_eth() \
do { \
REG_GPIO_GPAUR(3) &= 0xFC000000; \
REG_GPIO_GPAUR(3) |= 0x01555555; \
} while (0)
#define __gpio_as_pwm() \
do { \
REG_GPIO_GPAUR(2) &= 0x0FFFFFFF; \
REG_GPIO_GPAUR(2) |= 0x50000000; \
} while (0)
#define __gpio_as_ps2() \
do { \
REG_GPIO_GPALR(1) &= 0xFFFFFFF0; \
REG_GPIO_GPALR(1) |= 0x00000005; \
} while (0)
#define __gpio_as_uprt() \
do { \
REG_GPIO_GPALR(1) &= 0x0000000F; \
REG_GPIO_GPALR(1) |= 0x55555550; \
REG_GPIO_GPALR(3) &= 0xC0000000; \
REG_GPIO_GPALR(3) |= 0x15555555; \
} while (0)
#define __gpio_as_cim() \
do { \
REG_GPIO_GPALR(0) &= 0xFF000000; \
REG_GPIO_GPALR(0) |= 0x00555555; \
} while (0)

View File

@ -18,6 +18,63 @@
#include "iris.h"
// GPIO pins for the keyboard: Rows =
// Rows = 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 125
// Cols = 0, 1, 2, 3, 4, 5, 6, 7
// Rows: 60...6f; 7d
// Nicely aligned to a port: use cols as output; rows as input.
// Map memory from b0010000, which is really 10010000 in kseg1.
#define D(n) (*(volatile unsigned *)(0x00 + 0x30 * n + address))
#define DI(n) (*(volatile unsigned *)(0x04 + 0x30 * n + address))
#define AL(n) (*(volatile unsigned *)(0x10 + 0x30 * n + address))
#define AU(n) (*(volatile unsigned *)(0x14 + 0x30 * n + address))
#define IE(n) (*(volatile unsigned *)(0x20 + 0x30 * n + address))
void event (bool release, unsigned col, unsigned row):
debug_set_led ((col & 1) | (row & 2) | (release ? 4 : 0))
int main ():
// map memory
Capability page = memory_create_page (__my_memory)
alloc_physical (page, 0x10010000, 0)
unsigned const address = 0x00010000
memory_map (__my_memory, page, address)
// Disable all interrupts.
IE (3) &= ~0x2000ffff
IE (0) &= ~0x000000ff
// Set all to GPIO
AL (3) = 0
AU (3) &= ~0x0c000000
AL (0) &= ~0x0000ffff
// Set all to input
DI (3) |= 0x2000ffff
DI (0) |= 0x000000ff
unsigned keys[2][8]
for unsigned i = 0; i < 8; ++i:
keys[1][i] = 0x2000ffff
while true:
__asm__ volatile ("move $v0, $zero; move $a0, $zero ; move $a1, $zero ; move $a2, $zero ; syscall")
// read keyboard
for unsigned col = 0; col < 8; ++col:
// set col to output, all others to input
DI (0) = (DI (0) & ~0x000000ff) | (1 << col)
// read input
keys[0][col] = D (3) & ~0x2000ffff
// Generate events
if keys[0][col] == keys[1][col]:
continue
unsigned bit, b
for bit = 1, b = 0; bit < 0x10000; bit <<= 1, ++b:
if (keys[0][col] ^ keys[1][col]) & bit:
event (keys[0][col] & bit, col, b)
if (keys[0][col] ^ keys[1][col]) & 0x20000000:
// Not really bit 16, but it's easier to handle.
event (keys[0][col] & 0x20000000, col, 16)
schedule ()

View File

@ -320,6 +320,9 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability
case CAP_THREAD_SCHEDULE:
schedule ()
break
case CAP_THREAD_DEBUG:
dbg_leds (data[1] & 1, data[1] & 2, data[1] & 4)
break
case CAP_THREAD_REGISTER_INTERRUPT:
// Threads with access to this call are trusted, so no sanity checking is done.
arch_register_interrupt (data[1], cap ? (Receiver *)cap->protected_data : NULL)
@ -334,6 +337,9 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability
((Thread *)cap->protected_data)->flags |= THREAD_FLAG_PRIV
reply_cap (CAPTYPE_THREAD | (data[1] & CAP_THREAD_ALL_PRIV_RIGHTS), cap->protected_data)
break
case CAP_THREAD_ALLOC_PHYSICAL:
// TODO
break
default:
break

50
iris.h
View File

@ -63,11 +63,13 @@ extern "C" {
#define CAP_THREAD_INFO 1 /* Details of this are arch-specific. */
#define CAP_THREAD_SCHEDULE 2
#define CAP_THREAD_DEBUG 3
#define CAP_THREAD_ALLOC_PHYSICAL 5
#define CAP_THREAD_MAKE_PRIV 6
#define CAP_THREAD_GET_TOP_MEMORY 7
#define CAP_THREAD_REGISTER_INTERRUPT 8
#define CAP_THREAD_ALL_RIGHTS 0x3f
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV))
#define CAP_THREAD_ALL_RIGHTS 0x1f
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV) | (1 << CAP_THREAD_ALLOC_PHYSICAL))
/* These get/set_info are not arch-specific. */
#define CAP_THREAD_INFO_PC ~0
@ -114,10 +116,10 @@ extern "C" {
#ifndef __KERNEL
typedef unsigned Capability;
extern Capability my_receiver;
extern Capability my_thread;
extern Capability my_memory;
extern Capability my_call;
extern Capability __my_receiver;
extern Capability __my_thread;
extern Capability __my_memory;
extern Capability __my_call;
Capability cap_copy (Capability src)
{
@ -223,7 +225,7 @@ static Capability call_c01 (Capability c, unsigned d)
int ret;
msg.cap[0] = c;
msg.data[0] = d;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.cap[0] : 0;
}
@ -234,7 +236,7 @@ static Capability call_c02 (Capability c, unsigned d0, unsigned d1)
msg.cap[0] = c;
msg.data[0] = d0;
msg.data[1] = d1;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.cap[0] : 0;
}
@ -246,7 +248,7 @@ static Capability call_c12 (Capability c, Capability c1, unsigned d0, unsigned d
msg.cap[1] = c1;
msg.data[0] = d0;
msg.data[1] = d1;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.cap[0] : 0;
}
@ -256,7 +258,7 @@ static unsigned call_n01 (Capability c, unsigned d)
int ret;
msg.cap[0] = c;
msg.data[0] = d;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.data[0] : 0;
}
@ -267,7 +269,7 @@ static unsigned call_n02 (Capability c, unsigned d0, unsigned d1)
msg.cap[0] = c;
msg.data[0] = d0;
msg.data[1] = d1;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.data[0] : 0;
}
@ -279,7 +281,7 @@ static unsigned call_n03 (Capability c, unsigned d0, unsigned d1, unsigned d2)
msg.data[0] = d0;
msg.data[1] = d1;
msg.data[2] = d2;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.data[0] : 0;
}
@ -292,7 +294,7 @@ static unsigned call_n04 (Capability c, unsigned d0, unsigned d1, unsigned d2, u
msg.data[1] = d1;
msg.data[2] = d2;
msg.data[3] = d3;
ret = call (my_call, &msg);
ret = call (__my_call, &msg);
return ret ? msg.data[0] : 0;
}
@ -301,24 +303,34 @@ static Capability degrade (Capability src, unsigned mask)
return call_c02 (src, CAP_DEGRADE, mask);
}
static void debug_set_led (unsigned leds)
{
invoke_02 (__my_thread, CAP_THREAD_DEBUG, leds);
}
static void schedule ()
{
invoke_01 (my_thread, CAP_THREAD_SCHEDULE);
invoke_01 (__my_thread, CAP_THREAD_SCHEDULE);
}
static void register_interrupt (unsigned num)
{
invoke_12 (my_thread, my_receiver, CAP_THREAD_REGISTER_INTERRUPT, num);
invoke_12 (__my_thread, __my_receiver, CAP_THREAD_REGISTER_INTERRUPT, num);
}
static Capability get_top_memory ()
{
return call_c01 (my_thread, CAP_THREAD_GET_TOP_MEMORY);
return call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY);
}
static void unregister_interrupt (unsigned num)
{
invoke_02 (my_thread, CAP_THREAD_REGISTER_INTERRUPT, num);
invoke_02 (__my_thread, CAP_THREAD_REGISTER_INTERRUPT, num);
}
static void alloc_physical (Capability page, unsigned address, int cachable)
{
invoke_12 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, address | (cachable ? 1 : 0));
}
static int receiver_set_owner (Capability receiver, Capability owner)
@ -400,12 +412,12 @@ static Capability memory_mapping (Capability memory, unsigned address)
static void drop (Capability cap)
{
invoke_11 (my_memory, cap, CAP_MEMORY_DROP);
invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
}
static Capability thread_make_priv (Capability thread)
{
return call_c12 (my_thread, thread, CAP_THREAD_MAKE_PRIV, ~0);
return call_c12 (__my_thread, thread, CAP_THREAD_MAKE_PRIV, ~0);
}
static unsigned thread_info (Capability thread, unsigned info, unsigned value, unsigned mask)