- UART read support

- PRCM driver
This commit is contained in:
2013-06-22 17:01:05 +02:00
parent 83d7e987b4
commit a3c9a865b1
8 changed files with 250 additions and 38 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
fw fw
fw.bin fw.bin
fw.img fw.img
*~

View File

@@ -5,7 +5,7 @@ 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 CFLAGS=-march=armv7-a -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon --std=gnu99 -ggdb -Wall -Wextra -pedantic -Wno-unused-parameter -O1 -flto
LDFLAGS= LDFLAGS=
C_SRCS=cortexa8.c drv_omap35x_gpt.c main.c omap35x.c omap35x_intc.c uart.c syscall.c C_SRCS=cortexa8.c drv_omap35x_gpt.c main.c omap35x.c omap35x_intc.c omap35x_prcm.c uart.c syscall.c
S_SRCS=cortexa8_asm.s syscall_asm.s S_SRCS=cortexa8_asm.s syscall_asm.s
OBJS=$(addprefix objs/,$(C_SRCS:.c=.o)) $(addprefix objs/,$(S_SRCS:.s=.o)) OBJS=$(addprefix objs/,$(C_SRCS:.c=.o)) $(addprefix objs/,$(S_SRCS:.s=.o))

49
main.c
View File

@@ -7,59 +7,40 @@
#include "drv_omap35x_gpt.h" #include "drv_omap35x_gpt.h"
#include "omap35x.h" #include "omap35x.h"
#include "omap35x_intc.h" #include "omap35x_intc.h"
#include "omap35x_prcm.h"
#include "cortexa8.h" #include "cortexa8.h"
#include "uart.h"
static volatile uint32_t *const prcm_fclken_per = (uint32_t*)0x48005000; static volatile uint32_t *const prcm_wkst_per = (uint32_t*)0x483070b0;
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; static volatile uint32_t tickctr = 0;
void tickfunc(void* data) { void tickfunc(void* data) {
++tickctr; ++tickctr;
*prcm_wkst_per = (1<<3); // Clear GPT2 wake bit
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
omap35x_print_chip_id();
// Enable caches // Enable caches
cortexa8_enable_icache(); cortexa8_enable_icache();
cortexa8_enable_dcache(); cortexa8_enable_dcache();
printf("1\n"); // Configure PRCM
omap35x_prcm_init();
// Configure interrrupt & exception handling // Configure interrrupt & exception handling
cortexa8_init_handlers(); cortexa8_init_handlers();
omap35x_intc_init(); omap35x_intc_init();
printf("2\n");
cortexa8_init_mmu(); cortexa8_init_mmu();
printf("3\n"); omap35x_prcm_enable();
uart_init();
// Enable interrupts // Enable interrupts
cortexa8_ena_int(); cortexa8_ena_int();
printf("4\n"); omap35x_print_chip_id();
// 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"); printf("5\n");
@@ -70,10 +51,14 @@ int main(int argc, char* argv[]) {
printf("6\n"); printf("6\n");
*prcm_clkstctrl_mpu = 0x3; while(1) {
char buf[256];
if(fgets(buf, 256, stdin))
printf("%s", buf);
else
printf("Error\n");
}
printf("7\n");
while(1) { while(1) {
__asm__ __volatile__ ("wfi"); __asm__ __volatile__ ("wfi");
if(tickctr%100 == 0) { if(tickctr%100 == 0) {

88
omap35x_prcm.c Normal file
View File

@@ -0,0 +1,88 @@
#include <stdint.h>
#include <stdio.h>
static volatile uint32_t *const prcm_clkstctrl_iva2 = (uint32_t*)0x48004048;
static volatile uint32_t *const prcm_wkdep_iva2 = (uint32_t*)0x483060c8;
static volatile uint32_t *const prcm_pwstctrl_iva2 = (uint32_t*)0x483060e0;
static volatile uint32_t *const prcm_clkstctrl_core = (uint32_t*)0x48004a48;
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_wken_per = (uint32_t*)0x483070a0;
static volatile uint32_t *const prcm_mpugrpsel_per = (uint32_t*)0x483070a4;
static volatile uint32_t *const prcm_wkst_per = (uint32_t*)0x483070b0;
static volatile uint32_t *const prcm_clkstctrl_mpu = (uint32_t*)0x48004948;
static volatile uint32_t *const prcm_fclken_dss = (uint32_t*)0x48004e00;
static volatile uint32_t *const prcm_iclken_dss = (uint32_t*)0x48004e10;
static volatile uint32_t *const prcm_clkstctrl_dss = (uint32_t*)0x48004e48;
static volatile uint32_t *const prcm_wkdep_dss = (uint32_t*)0x48306ec8;
static volatile uint32_t *const prcm_pwstctrl_dss = (uint32_t*)0x48306ee0;
static volatile uint32_t *const prcm_clkstctrl_cam = (uint32_t*)0x48004f48;
static volatile uint32_t *const prcm_wkdep_cam = (uint32_t*)0x48306fc8;
static volatile uint32_t *const prcm_pwstctrl_cam = (uint32_t*)0x48306fe0;
static volatile uint32_t *const prcm_clkstctrl_neon = (uint32_t*)0x48005348;
static volatile uint32_t *const prcm_clkstctrl_usbhost = (uint32_t*)0x48005448;
static volatile uint32_t *const prcm_wkdep_usbhost = (uint32_t*)0x483074c8;
static volatile uint32_t *const prcm_pwstctrl_usbhost = (uint32_t*)0x483074e0;
void omap35x_prcm_init() {
// Setup IVA2 domain (unused, disable)
*prcm_clkstctrl_iva2 = 0x3;
*prcm_wkdep_iva2 = 0;
*prcm_pwstctrl_iva2 &= ~0x3;
// Setup MPU domain (enable)
*prcm_clkstctrl_mpu = 0x3;
// Setup CORE domain (enable)
*prcm_clkstctrl_core = 0xf; // Autosleep L3&L4
// Setup PER domain (enable)
*prcm_sleepdep_per |= (1<<1); // Enable PER-MPU sleep dep.
*prcm_clkstctrl_per |= 0x3; // Enable autosleep
// Setup DSS domain (unused, disable)
*prcm_fclken_dss = 0;
*prcm_iclken_dss = 0;
*prcm_clkstctrl_dss = 0x3;
*prcm_wkdep_dss = 0;
*prcm_pwstctrl_dss &= ~0x3;
// Setup CAM comain (unused, disable)
*prcm_clkstctrl_cam = 0x3;
*prcm_wkdep_cam = 0;
*prcm_pwstctrl_cam &= ~0x3;
// Setup NEON domain
*prcm_clkstctrl_neon = 0x3;
// Setup USBHOST domain (unused, disable)
*prcm_clkstctrl_usbhost = 0x3;
*prcm_wkdep_usbhost = 0;
*prcm_pwstctrl_usbhost &= ~0x3;
}
void omap35x_prcm_enable() {
// 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_wken_per |= (1<<3); // GPT2 wake up enable
// Prepare UART3
*prcm_autoidle_per |= (1<<11); // Enable UART3 iclk autoidle
*prcm_mpugrpsel_per |= (1<<11); // UART3 wakes up MPU
*prcm_wken_per |= (1<<11); // UART3 wake up enable
}

10
omap35x_prcm.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef _OMAP35X_PRCM_H_
#define _OMAP35x_PRCM_H_
// Initialize the power&clock manager
void omap35x_prcm_init();
// Enable clock&power for all used peripherals
void omap35x_prcm_enable();
#endif

View File

@@ -30,7 +30,10 @@ int _isatty(int file) {
int _read(int file, char *ptr, int len) __attribute__((used)); int _read(int file, char *ptr, int len) __attribute__((used));
int _read(int file, char *ptr, int len) { int _read(int file, char *ptr, int len) {
return 0; /* if(file != 0) */
/* return 0; */
return uart_read(ptr, len);
} }
int _write(int file, char *ptr, int len) __attribute__((used)); int _write(int file, char *ptr, int len) __attribute__((used));

127
uart.c
View File

@@ -1,12 +1,39 @@
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "cortexa8.h"
#include "omap35x_intc.h"
#include "uart.h" #include "uart.h"
static volatile uint32_t *const uart_data = (uint32_t*)0x49020000; static volatile uint8_t *const uart_data = (uint8_t*)0x49020000;
static volatile uint32_t *const uart_status = (uint32_t*)0x49020044; static volatile uint8_t *const uart_dll = (uint8_t*)0x49020000;
static volatile uint8_t *const uart_dlh = (uint8_t*)0x49020004;
static volatile uint8_t *const uart_ier = (uint8_t*)0x49020004;
static volatile uint8_t *const uart_fcr = (uint8_t*)0x49020008;
static volatile uint8_t *const uart_efr = (uint8_t*)0x49020008;
static volatile uint8_t *const uart_lcr = (uint8_t*)0x4902000c;
static volatile uint8_t *const uart_lsr = (uint8_t*)0x49020014;
static volatile uint8_t *const uart_ssr = (uint8_t*)0x49020044;
static volatile uint8_t *const uart_sysc = (uint8_t*)0x49020054;
static volatile uint8_t *const uart_wer = (uint8_t*)0x4902005C;
static volatile uint32_t *const prcm_wkst_per = (uint32_t*)0x483070b0;
#define RECVBUFFERSIZE 128
static volatile char recvbuffer[RECVBUFFERSIZE];
static volatile int recvbuffer_rdptr = (RECVBUFFERSIZE-1), recvbuffer_wrptr = 0;
static volatile bool newdata = false;
static bool echo = true;
static void _uart_wait_txnotfull() { static void _uart_wait_txnotfull() {
while(*uart_status & 0x1) {} while(*uart_ssr & 0x1) {}
}
static void _uart_wait_rxnotempty() {
while(!(*uart_lsr & 0x1)) {}
} }
void uart_sendb(char b) { void uart_sendb(char b) {
@@ -14,7 +41,101 @@ void uart_sendb(char b) {
*uart_data = b; *uart_data = b;
} }
char uart_recvb() {
_uart_wait_rxnotempty();
return *uart_data;
}
void uart_write(const char *data, int len) { void uart_write(const char *data, int len) {
for(int i = 0;i < len;++i) for(int i = 0;i < len;++i)
uart_sendb(*data++); uart_sendb(*data++);
} }
int uart_read(char *buf, int len) {
int pos = 0;
while(true) {
bool oldint = cortexa8_get_int();
cortexa8_dis_int();
// Data available in recvbuffer?
if(((recvbuffer_rdptr+1)%RECVBUFFERSIZE) != recvbuffer_wrptr) {
int avail = recvbuffer_wrptr - recvbuffer_rdptr;
if(avail < 0)
avail = RECVBUFFERSIZE+avail;
avail -= 1;
// Advance to first byte to read
recvbuffer_rdptr = (recvbuffer_rdptr+1)%RECVBUFFERSIZE;
int toread = (avail>len)?len:avail;
if(toread+recvbuffer_rdptr > RECVBUFFERSIZE) {
memcpy(buf+pos, (char*)recvbuffer+recvbuffer_rdptr, RECVBUFFERSIZE-(recvbuffer_rdptr));
toread -= RECVBUFFERSIZE-recvbuffer_rdptr;
pos += RECVBUFFERSIZE-recvbuffer_rdptr;
recvbuffer_rdptr = 0;
}
memcpy(buf+pos, (char*)recvbuffer+recvbuffer_rdptr, toread);
pos += toread;
recvbuffer_rdptr = (recvbuffer_rdptr+toread-1)%RECVBUFFERSIZE;
}
newdata = false;
// Try to read directly from UART if more data req'd than was in buffer
while((pos < len) && (*uart_lsr & 0x1)) {
char rd = *uart_data;
if(rd == '\r')
rd = '\n';
if(echo)
uart_sendb(rd);
buf[pos++] = rd;
}
if(oldint)
cortexa8_ena_int();
if(pos > 0)
return pos;
while(!newdata)
__asm__ __volatile__ ("wfi"); // If we didn't get any data, wait
}
}
void uart_recv_handler(void *unused) {
while(*uart_lsr & 0x1) { // while there are bytes
char rd = *uart_data;
if(rd == '\r')
rd = '\n';
if(echo)
uart_sendb(rd);
if(recvbuffer_wrptr == recvbuffer_rdptr) { // Overflow
} else {
recvbuffer[recvbuffer_wrptr] = rd;
recvbuffer_wrptr = (recvbuffer_wrptr+1)%RECVBUFFERSIZE;
}
}
newdata = true;
*prcm_wkst_per = (1<<11); // Clear UART3 wake bit
}
void uart_init() {
omap35x_intc_register(74, &uart_recv_handler, NULL, 1);
omap35x_intc_ena(74);
*uart_lcr = 0xBF; // Configuration mode B
uint8_t dllsave = *uart_dll, dlhsave = *uart_dlh;
*uart_dll = 0;
*uart_dlh = 0;
*uart_efr |= (1<<4);
*uart_lcr = 0x80; // Configuration mode A
*uart_fcr = 0x21;
*uart_sysc = 0x15;
*uart_wer |= (1<<5);
*uart_dll = dllsave;
*uart_dlh = dlhsave;
*uart_lcr = 0x03; // Operational mode
*uart_ier = 0x11;
}

6
uart.h
View File

@@ -1,7 +1,11 @@
#ifndef _UART_H_ #ifndef _UART_H_
#define _UART_H_ #define _UART_H_
void uart_sendb(char b); void uart_init();
//void uart_sendb(char b);
//char uart_recvb();
void uart_write(const char *data, int len); void uart_write(const char *data, int len);
int uart_read(char *buf, int len);
#endif #endif