summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
author[email protected] <[email protected]>2012-05-30 11:29:34 +0000
committer[email protected] <[email protected]>2012-05-30 11:29:34 +0000
commit5684d159162ace6c354a3faa578c3fb6503f6b0e (patch)
treef4e3e826be502dad802de8b326f5ed0a79629b1d /libcpu
parent3ad6f43ff3ba436eeac0c945c0fd6cc276acbaa6 (diff)
add bf533 bsp and cpu files.
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2138 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/blackfin/bf53x/context_vdsp.S165
-rw-r--r--libcpu/blackfin/bf53x/cpuport.c93
-rw-r--r--libcpu/blackfin/bf53x/serial.c284
-rw-r--r--libcpu/blackfin/bf53x/serial.h56
4 files changed, 598 insertions, 0 deletions
diff --git a/libcpu/blackfin/bf53x/context_vdsp.S b/libcpu/blackfin/bf53x/context_vdsp.S
new file mode 100644
index 0000000000..b955d9ded7
--- /dev/null
+++ b/libcpu/blackfin/bf53x/context_vdsp.S
@@ -0,0 +1,165 @@
+/*
+ * File : context_vdsp.S
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2009 - 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-02-13 mojingxian First version
+ */
+
+.global _rt_hw_interrupt_disable;
+.global _rt_hw_interrupt_enable;
+.global _interrupt_thread_switch;
+
+.extern _rt_interrupt_from_thread;
+.extern _rt_interrupt_to_thread;
+.extern _rt_thread_switch_interrupt_flag;
+
+.section/DOUBLE64 program;
+
+/*
+ * rt_base_t rt_hw_interrupt_disable();
+ * return value in R0.
+ */
+_rt_hw_interrupt_disable:
+ CLI R0;
+
+_rt_hw_interrupt_disable.end:
+ NOP;
+ NOP;
+ NOP;
+ RTS;
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ * R0->level
+ */
+_rt_hw_interrupt_enable:
+ STI R0;
+
+_rt_hw_interrupt_enable.end:
+ NOP;
+ NOP;
+ NOP;
+ RTS;
+
+_interrupt_thread_switch:
+ /* Save context, interrupts disabled by IPEND[4] bit */
+ [ -- SP ] = R0;
+ [ -- SP ] = P1;
+ [ -- SP ] = RETS;
+ [ -- SP ] = R1;
+ [ -- SP ] = R2;
+ [ -- SP ] = P0;
+ [ -- SP ] = P2;
+ [ -- SP ] = ASTAT;
+ R1 = RETI; /* IPEND[4] is currently set, globally disabling interrupts */
+ /* IPEND[4] will stay set when RETI is saved through R1 */
+
+ [ -- SP ] = R1;
+ [ -- SP ] = (R7:3, P5:3);
+ [ -- SP ] = FP;
+ [ -- SP ] = I0;
+ [ -- SP ] = I1;
+ [ -- SP ] = I2;
+ [ -- SP ] = I3;
+ [ -- SP ] = B0;
+ [ -- SP ] = B1;
+ [ -- SP ] = B2;
+ [ -- SP ] = B3;
+ [ -- SP ] = L0;
+ [ -- SP ] = L1;
+ [ -- SP ] = L2;
+ [ -- SP ] = L3;
+ [ -- SP ] = M0;
+ [ -- SP ] = M1;
+ [ -- SP ] = M2;
+ [ -- SP ] = M3;
+ R1.L = A0.x;
+ [ -- SP ] = R1;
+ R1 = A0.w;
+ [ -- SP ] = R1;
+ R1.L = A1.x;
+ [ -- SP ] = R1;
+ R1 = A1.w;
+ [ -- SP ] = R1;
+ [ -- SP ] = LC0;
+ R3 = 0;
+ LC0 = R3;
+ [ -- SP ] = LC1;
+ R3 = 0;
+ LC1 = R3;
+ [ -- SP ] = LT0;
+ [ -- SP ] = LT1;
+ [ -- SP ] = LB0;
+ [ -- SP ] = LB1;
+
+ /* Context save done so save SP in the TCB */
+ P1.h = _rt_interrupt_from_thread;
+ P1.l = _rt_interrupt_from_thread;
+ P2 = [ P1 ];
+ [ P2 ] = SP;
+
+ /* clear rt_thread_switch_interrupt_flag to 0 */
+ P1.h = _rt_thread_switch_interrupt_flag;
+ P1.l = _rt_thread_switch_interrupt_flag;
+ R0 = 0;
+ [ P1 ] = R0;
+
+ /* Get a pointer to the high ready task's TCB */
+ P1.h = _rt_interrupt_to_thread;
+ P1.l = _rt_interrupt_to_thread;
+ P2 = [ P1 ];
+ SP = [ P2 ];
+
+ /* Restoring CPU context and return to task */
+ LB1 = [ SP ++ ];
+ LB0 = [ SP ++ ];
+ LT1 = [ SP ++ ];
+ LT0 = [ SP ++ ];
+ LC1 = [ SP ++ ];
+ LC0 = [ SP ++ ];
+ R0 = [ SP ++ ];
+ A1 = R0;
+ R0 = [ SP ++ ];
+ A1.x = R0.L;
+ R0 = [ SP ++ ];
+ A0 = R0;
+ R0 = [ SP ++ ];
+ A0.x = R0.L;
+ M3 = [ SP ++ ];
+ M2 = [ SP ++ ];
+ M1 = [ SP ++ ];
+ M0 = [ SP ++ ];
+ L3 = [ SP ++ ];
+ L2 = [ SP ++ ];
+ L1 = [ SP ++ ];
+ L0 = [ SP ++ ];
+ B3 = [ SP ++ ];
+ B2 = [ SP ++ ];
+ B1 = [ SP ++ ];
+ B0 = [ SP ++ ];
+ I3 = [ SP ++ ];
+ I2 = [ SP ++ ];
+ I1 = [ SP ++ ];
+ I0 = [ SP ++ ];
+ FP = [ SP ++ ];
+ (R7:3, P5:3) = [ SP ++ ];
+ RETI = [ SP ++ ]; /* IPEND[4] will stay set when RETI popped from stack */
+ ASTAT = [ SP ++ ];
+ P2 = [ SP ++ ];
+ P0 = [ SP ++ ];
+ R2 = [ SP ++ ];
+ R1 = [ SP ++ ];
+ RETS = [ SP ++ ];
+ P1 = [ SP ++ ];
+ R0 = [ SP ++ ];
+
+_interrupt_thread_switch.end:
+ RTI;
+
diff --git a/libcpu/blackfin/bf53x/cpuport.c b/libcpu/blackfin/bf53x/cpuport.c
new file mode 100644
index 0000000000..91cfaeb403
--- /dev/null
+++ b/libcpu/blackfin/bf53x/cpuport.c
@@ -0,0 +1,93 @@
+/*
+ * File : cpuport.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-02-13 mojingxian first version
+ */
+
+#include <rtthread.h>
+
+/* flag in interrupt handling */
+rt_uint32_t rt_interrupt_from_thread;
+rt_uint32_t rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+
+/**
+ * initializes stack of thread
+ */
+rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
+ rt_uint8_t *stack_addr, void *texit)
+{
+ unsigned char i;
+ unsigned long *stk;
+
+ stk = (unsigned long *)stack_addr; /* Load stack pointer */
+
+ /* Simulate a function call to the task with an argument */
+ stk -= 3; /* 3 words assigned for incoming args (R0, R1, R2) */
+
+ /* Now simulating vectoring to an ISR */
+ *--stk = (unsigned long)parameter; /* R0 value - caller's incoming argument #1 */
+ *--stk = (unsigned long)0; /* P1 value - value irrelevant */
+
+ *--stk = (unsigned long)texit; /* RETS value - NO task should return with RTS. */
+ /* however OS_CPU_Invalid_Task_Return is a safety */
+ /* catch-allfor tasks that return with an RTS */
+
+ *--stk = (unsigned long)parameter; /* R1 value - caller's incoming argument #2 */
+ /* (not relevant in current test example) */
+ *--stk = (unsigned long)parameter; /* R2 value - caller's incoming argument #3 */
+ /* (not relevant in current test example) */
+ *--stk = (unsigned long)0; /* P0 value - value irrelevant */
+ *--stk = (unsigned long)0; /* P2 value - value irrelevant */
+ *--stk = (unsigned long)0; /* ASTAT value - caller's ASTAT value - value */
+ /* irrelevant */
+
+ *--stk = (unsigned long)tentry; /* RETI value- pushing the start address of the task */
+
+ for (i = 0; i < 35; i++) /* remaining reg values - R7:3, P5:3, */
+ { /* 4 words of A1:0(.W,.X), LT0, LT1, */
+ *--stk = (unsigned long)0; /* LC0, LC1, LB0, LB1,I3:0, M3:0, L3:0, B3:0, */
+ } /* All values irrelevant */
+
+ return (rt_uint8_t *)stk; /* Return top-of-stack */
+}
+
+void rt_hw_context_switch(rt_uint32_t from, rt_uint32_t to)
+{
+ if (rt_thread_switch_interrupt_flag != 1)
+ {
+ rt_thread_switch_interrupt_flag = 1;
+ rt_interrupt_from_thread = from;
+ }
+
+ rt_interrupt_to_thread = to;
+ asm("raise 14;"); // Raise Interrupt 14 (trap)
+}
+
+void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to)
+{
+ if (rt_thread_switch_interrupt_flag != 1)
+ {
+ rt_thread_switch_interrupt_flag = 1;
+ rt_interrupt_from_thread = from;
+ }
+
+ rt_interrupt_to_thread = to;
+ asm("raise 14;"); // Raise Interrupt 14 (trap)
+}
+
+void rt_hw_context_switch_to(rt_uint32_t to)
+{
+ rt_thread_switch_interrupt_flag = 1;
+ rt_interrupt_from_thread = 0;
+ rt_interrupt_to_thread = to;
+ asm("raise 14;"); // Raise Interrupt 14 (trap)
+}
diff --git a/libcpu/blackfin/bf53x/serial.c b/libcpu/blackfin/bf53x/serial.c
new file mode 100644
index 0000000000..e5547fb887
--- /dev/null
+++ b/libcpu/blackfin/bf53x/serial.c
@@ -0,0 +1,284 @@
+/*
+ * File : serial.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-03-13 Bernard first version
+ * 2009-04-20 yi.qiu modified according bernard's stm32 version
+ * 2012-02-17 mojingxian modified for bf53x
+ */
+
+#include <rtthread.h>
+
+#include "serial.h"
+
+/**
+ * @addtogroup BF53X
+ */
+/*@{*/
+
+/* RT-Thread Device Interface */
+/**
+ * This function initializes serial
+ */
+static rt_err_t rt_serial_init (rt_device_t dev)
+{
+ struct serial_device* uart = (struct serial_device*) dev->user_data;
+
+ if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
+ {
+
+ if (dev->flag & RT_DEVICE_FLAG_INT_RX)
+ {
+ rt_memset(uart->int_rx->rx_buffer, 0,
+ sizeof(uart->int_rx->rx_buffer));
+ uart->int_rx->read_index = uart->int_rx->save_index = 0;
+ }
+
+ if (dev->flag & RT_DEVICE_FLAG_INT_TX)
+ {
+ rt_memset(uart->int_tx->tx_buffer, 0,
+ sizeof(uart->int_tx->tx_buffer));
+ uart->int_tx->write_index = uart->int_tx->save_index = 0;
+ }
+
+ dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
+ }
+
+ return RT_EOK;
+}
+
+/* save a char to serial buffer */
+static void rt_serial_savechar(struct serial_device* uart, char ch)
+{
+ rt_base_t level;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ uart->int_rx->rx_buffer[uart->int_rx->save_index] = ch;
+ uart->int_rx->save_index ++;
+ if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE)
+ uart->int_rx->save_index = 0;
+
+ /* if the next position is read index, discard this 'read char' */
+ if (uart->int_rx->save_index == uart->int_rx->read_index)
+ {
+ uart->int_rx->read_index ++;
+ if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
+ uart->int_rx->read_index = 0;
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+}
+
+static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ RT_ASSERT(dev != RT_NULL);
+
+ return RT_EOK;
+}
+
+static rt_err_t rt_serial_close(rt_device_t dev)
+{
+ RT_ASSERT(dev != RT_NULL);
+
+ return RT_EOK;
+}
+
+static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+ rt_uint8_t* ptr;
+ rt_err_t err_code;
+ struct serial_device* uart;
+
+ ptr = buffer;
+ err_code = RT_EOK;
+ uart = (struct serial_device*)dev->user_data;
+
+ if (dev->flag & RT_DEVICE_FLAG_INT_RX)
+ {
+ rt_base_t level;
+
+ /* interrupt mode Rx */
+ while (size)
+ {
+ if (uart->int_rx->read_index != uart->int_rx->save_index)
+ {
+ *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index];
+ size --;
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ uart->int_rx->read_index ++;
+ if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
+ uart->int_rx->read_index = 0;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+ }
+ else
+ {
+ /* set error code */
+ err_code = -RT_EEMPTY;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* polling mode */
+ while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
+ {
+ //while (uart->uart_device->ustat & USTAT_RCV_READY)
+ {
+ *ptr = uart->uart_device->rbr_thr & 0xff;
+ ptr ++;
+ }
+ }
+ }
+
+ /* set error code */
+ rt_set_errno(err_code);
+ return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
+}
+
+static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
+{
+ rt_uint8_t* ptr;
+ rt_err_t err_code;
+ struct serial_device* uart;
+
+ err_code = RT_EOK;
+ ptr = (rt_uint8_t*)buffer;
+ uart = (struct serial_device*)dev->user_data;
+
+ if (dev->flag & RT_DEVICE_FLAG_INT_TX)
+ {
+ /* interrupt mode Tx */
+ while (uart->int_tx->save_index != uart->int_tx->write_index)
+ {
+ /* save on tx buffer */
+ uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++;
+
+ -- size;
+
+ /* move to next position */
+ uart->int_tx->save_index ++;
+
+ /* wrap save index */
+ if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE)
+ uart->int_tx->save_index = 0;
+ }
+
+ /* set error code */
+ if (size > 0)
+ err_code = -RT_EFULL;
+ }
+ else
+ {
+ /* polling mode */
+ while (size)
+ {
+ /*
+ * to be polite with serial console add a line feed
+ * to the carriage return character
+ */
+ if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))
+ {
+ while (!(uart->uart_device->lsr & 0x20));
+ uart->uart_device->rbr_thr = '\r';
+ }
+
+ while (!(uart->uart_device->lsr & 0x20));
+ uart->uart_device->rbr_thr = (*ptr & 0xFF);
+
+ ++ptr; --size;
+ }
+ }
+
+ /* set error code */
+ rt_set_errno(err_code);
+
+ return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
+}
+
+static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+ RT_ASSERT(dev != RT_NULL);
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_SUSPEND:
+ /* suspend device */
+ dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
+ break;
+
+ case RT_DEVICE_CTRL_RESUME:
+ /* resume device */
+ dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
+ break;
+ }
+
+ return RT_EOK;
+}
+
+/*
+ * serial register
+ */
+rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial)
+{
+ RT_ASSERT(device != RT_NULL);
+
+ device->type = RT_Device_Class_Char;
+ device->rx_indicate = RT_NULL;
+ device->tx_complete = RT_NULL;
+ device->init = rt_serial_init;
+ device->open = rt_serial_open;
+ device->close = rt_serial_close;
+ device->read = rt_serial_read;
+ device->write = rt_serial_write;
+ device->control = rt_serial_control;
+ device->user_data = serial;
+
+ /* register a character device */
+ return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
+}
+
+/* ISR for serial interrupt */
+void rt_hw_serial_isr(rt_device_t device)
+{
+ struct serial_device* uart = (struct serial_device*) device->user_data;
+
+ /* interrupt mode receive */
+ RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);
+
+ /* save on rx buffer */
+ //while (uart->uart_device->ustat & USTAT_RCV_READY)
+ {
+ rt_serial_savechar(uart, uart->uart_device->rbr_thr & 0xff);
+ }
+
+ /* invoke callback */
+ if (device->rx_indicate != RT_NULL)
+ {
+ rt_size_t rx_length;
+
+ /* get rx length */
+ rx_length = uart->int_rx->read_index > uart->int_rx->save_index ?
+ UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index :
+ uart->int_rx->save_index - uart->int_rx->read_index;
+
+ device->rx_indicate(device, rx_length);
+ }
+}
+
+/*@}*/
diff --git a/libcpu/blackfin/bf53x/serial.h b/libcpu/blackfin/bf53x/serial.h
new file mode 100644
index 0000000000..8eef14546b
--- /dev/null
+++ b/libcpu/blackfin/bf53x/serial.h
@@ -0,0 +1,56 @@
+#ifndef __RT_HW_SERIAL_H__
+#define __RT_HW_SERIAL_H__
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#define USTAT_RCV_READY 0x01 /* receive data ready */
+#define USTAT_TXB_EMPTY 0x02 /* tx buffer empty */
+#define BPS 115200 /* serial baudrate */
+
+#define UART_RX_BUFFER_SIZE 64
+#define UART_TX_BUFFER_SIZE 64
+
+struct serial_int_rx
+{
+ rt_uint8_t rx_buffer[UART_RX_BUFFER_SIZE];
+ rt_uint32_t read_index, save_index;
+};
+
+struct serial_int_tx
+{
+ rt_uint8_t tx_buffer[UART_TX_BUFFER_SIZE];
+ rt_uint32_t write_index, save_index;
+};
+
+typedef struct uartport
+{
+ volatile rt_uint16_t rbr_thr; //receive buffer register and transmit hold register
+ volatile rt_uint16_t reserved0;
+ volatile rt_uint16_t reserved1;
+ volatile rt_uint16_t reserved2;
+ volatile rt_uint16_t reserved3;
+ volatile rt_uint16_t reserved4;
+ volatile rt_uint16_t reserved5;
+ volatile rt_uint16_t reserved6;
+ volatile rt_uint16_t reserved7;
+ volatile rt_uint16_t reserved8;
+ volatile rt_uint16_t lsr; //line status register
+}uartport;
+
+struct serial_device
+{
+ uartport* uart_device;
+
+ /* rx structure */
+ struct serial_int_rx* int_rx;
+
+ /* tx structure */
+ struct serial_int_tx* int_tx;
+};
+
+rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial);
+
+void rt_hw_serial_isr(rt_device_t device);
+
+#endif