diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/blackfin/bf53x/context_vdsp.S | 165 | ||||
| -rw-r--r-- | libcpu/blackfin/bf53x/cpuport.c | 93 | ||||
| -rw-r--r-- | libcpu/blackfin/bf53x/serial.c | 284 | ||||
| -rw-r--r-- | libcpu/blackfin/bf53x/serial.h | 56 |
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
|
