- UART read support
- PRCM driver
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
fw
|
fw
|
||||||
fw.bin
|
fw.bin
|
||||||
fw.img
|
fw.img
|
||||||
|
*~
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -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
49
main.c
@@ -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
88
omap35x_prcm.c
Normal 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
10
omap35x_prcm.h
Normal 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
|
||||||
@@ -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
127
uart.c
@@ -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
6
uart.h
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user