From 08f25161d9f988eaefd37e4d06fe244bed381418 Mon Sep 17 00:00:00 2001 From: "nongli1031@gmail.com" Date: Sat, 17 Dec 2011 04:14:22 +0000 Subject: [PATCH] porting for microblaze. nl1031 git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1843 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- bsp/microblaze/application.c | 26 ++ bsp/microblaze/board.c | 232 ++++++++++++++++++ bsp/microblaze/board.h | 22 ++ bsp/microblaze/rtconfig.h | 190 +++++++++++++++ bsp/microblaze/startup.c | 120 +++++++++ libcpu/xilinx/microblaze/context_gcc.S | 224 +++++++++++++++++ libcpu/xilinx/microblaze/cpu.c | 35 +++ libcpu/xilinx/microblaze/microbalze.inc | 116 +++++++++ libcpu/xilinx/microblaze/serial.c | 310 ++++++++++++++++++++++++ libcpu/xilinx/microblaze/serial.h | 6 + libcpu/xilinx/microblaze/stack.c | 71 ++++++ libcpu/xilinx/microblaze/trap.c | 211 ++++++++++++++++ 12 files changed, 1563 insertions(+) create mode 100755 bsp/microblaze/application.c create mode 100755 bsp/microblaze/board.c create mode 100755 bsp/microblaze/board.h create mode 100755 bsp/microblaze/rtconfig.h create mode 100755 bsp/microblaze/startup.c create mode 100755 libcpu/xilinx/microblaze/context_gcc.S create mode 100755 libcpu/xilinx/microblaze/cpu.c create mode 100755 libcpu/xilinx/microblaze/microbalze.inc create mode 100755 libcpu/xilinx/microblaze/serial.c create mode 100755 libcpu/xilinx/microblaze/serial.h create mode 100755 libcpu/xilinx/microblaze/stack.c create mode 100755 libcpu/xilinx/microblaze/trap.c diff --git a/bsp/microblaze/application.c b/bsp/microblaze/application.c new file mode 100755 index 000000000..46e5ef623 --- /dev/null +++ b/bsp/microblaze/application.c @@ -0,0 +1,26 @@ +/* + * File : app.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://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2006-06-05 Bernard the first version + */ + +/** + * @addtogroup sam7s + */ +/*@{*/ +#include + +int rt_application_init() +{ + return 0; +} + +/*@}*/ diff --git a/bsp/microblaze/board.c b/bsp/microblaze/board.c new file mode 100755 index 000000000..d0f54e001 --- /dev/null +++ b/bsp/microblaze/board.c @@ -0,0 +1,232 @@ +/* + * File : board.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop 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-08-23 Bernard first implementation + * + * 2011-12-17 nl1031 for MacroBlaze + * + */ + +#include +#include + +#include "xbasic_types.h" +#include "board.h" +#include "xgpio.h" +#include "xparameters.h" +#include "xuartlite.h" +#include "xtmrctr.h" +#include "xintc.h" +#include "xstatus.h" +#include "xuartlite_l.h" +#include "xintc_l.h" + +#ifdef RT_USING_UART1 +#include "serial.h" +#endif + +#define TIMER_CNTR_0 0 +#define PIV (XPAR_PROC_BUS_0_FREQ_HZ / RT_TICK_PER_SECOND) +#define LEDS_DEVICE_ID XPAR_LEDS_4BITS_DEVICE_ID +#define RS232_DEVICE_ID XPAR_USB_UART_DEVICE_ID + +#ifdef RT_USING_UART1 +#define USB_UART_BASE ((struct uartport *)XPAR_USB_UART_BASEADDR) +#endif + +/* Global Variables: */ +XTmrCtr timer; /* The instance of the timer */ +XGpio gpio_output; /* The driver instance for GPIO Device configured as O/P */ +XUartLite uart_lite; /* Instance of the UartLite device */ +XIntc int_ctl; /* The instance of the Interrupt Controller */ +static rt_uint32_t led_data; + + + +static void rt_hw_board_led_init(void); + +/** + * This function will init led on the board + */ +static void rt_hw_board_led_init() +{ + rt_uint32_t status; + led_data = 0; + status = XGpio_Initialize(&gpio_output, LEDS_DEVICE_ID); + if (status != XST_SUCCESS) + { + return; + } + + /* + * Set the direction for all signals to be outputs + */ + XGpio_SetDataDirection(&gpio_output, 1, 0x0); + /* + * Set the GPIO outputs to high + */ + XGpio_DiscreteWrite(&gpio_output, 1, 3); +} + +/** + * This function will take the led on board on. + * + * @param n the number nth led + */ +void rt_hw_board_led_on(rt_uint32_t led) +{ + led_data |= led; + XGpio_DiscreteWrite(&gpio_output, 1, led_data); +} + +/** + * This function will take the led on board off. + * + * @param n the number nth led + */ +void rt_hw_board_led_off(rt_uint32_t led) +{ + led_data &= ~led; + XGpio_DiscreteWrite(&gpio_output, 1, led_data); +} + + +void rt_hw_led_flash(void) +{ + rt_uint32_t i; + + rt_hw_board_led_off(1); + for (i = 0; i < 20000; i ++); + + rt_hw_board_led_on(1); + for (i = 0; i < 20000; i ++); +} + + +#ifdef RT_USING_CONSOLE + +/* + * RT-Thread Console Interface, used by rt_kprintf + */ +/** + * This function is used to display a string on console, normally, it's + * invoked by rt_kprintf + * + * @param str the displayed string + */ +void rt_hw_console_output(const char* str) +{ + while (*str) + { + + /* Transmit Character */ + XUartLite_SendByte(STDOUT_BASEADDRESS, *str); + if (*str == '\n') + XUartLite_SendByte(STDOUT_BASEADDRESS, '\r'); + str++; + } +} + +static void rt_hw_console_init() +{ + rt_uint32_t status; + + /* + * Initialize the UartLite driver so that it is ready to use. + */ + status = XUartLite_Initialize(&uart_lite, RS232_DEVICE_ID); + if (status != XST_SUCCESS) + { + return; + } + +} +#endif + + +void rt_hw_timer_handler(void) +{ + rt_uint32_t csr; + csr = XTmrCtr_ReadReg(timer.BaseAddress, TIMER_CNTR_0, XTC_TCSR_OFFSET); + /* + * Check if timer expired and interrupt occured + */ + if (csr & XTC_CSR_INT_OCCURED_MASK) + { + rt_tick_increase(); + XTmrCtr_WriteReg(timer.BaseAddress, TIMER_CNTR_0, XTC_TCSR_OFFSET, csr | XTC_CSR_INT_OCCURED_MASK); + } + +} + + +/* +********************************************************************************************************* +* rt_intc_init() +* +* Description: This function intializes the interrupt controller by registering the appropriate handler +* functions and enabling interrupts. +* +* Arguments : None +* +* Returns : None +********************************************************************************************************* +*/ + +void rt_intc_init (void) +{ + XStatus status; + + XIntc_MasterDisable(XPAR_INTC_0_BASEADDR); + + status = XIntc_Initialize(&int_ctl, XPAR_INTC_0_DEVICE_ID); + + /* install interrupt handler */ + rt_hw_interrupt_install(XPAR_INTC_0_TMRCTR_0_VEC_ID, (rt_isr_handler_t)rt_hw_timer_handler, RT_NULL); + rt_hw_interrupt_umask(XPAR_INTC_0_TMRCTR_0_VEC_ID); + + XIntc_Start(&int_ctl, XIN_REAL_MODE); + +} + + +void rt_tmr_init (void) +{ + rt_uint32_t ctl; + XStatus status; + + status = XTmrCtr_Initialize(&timer,XPAR_AXI_TIMER_0_DEVICE_ID); + XTmrCtr_WriteReg(timer.BaseAddress, TIMER_CNTR_0, XTC_TLR_OFFSET, PIV); + ctl = XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK; + XTmrCtr_WriteReg(timer.BaseAddress, TIMER_CNTR_0, XTC_TCSR_OFFSET, ctl); +} + + + +/** + * This function will initial SPARTAN 6 LX9 board. + */ +void rt_hw_board_init() +{ + /* init hardware console */ + rt_hw_console_init(); + + /* init led */ + rt_hw_board_led_init(); + + /* init intc */ + rt_intc_init(); + + /* timer init */ + rt_tmr_init(); + + +} diff --git a/bsp/microblaze/board.h b/bsp/microblaze/board.h new file mode 100755 index 000000000..9e542c17c --- /dev/null +++ b/bsp/microblaze/board.h @@ -0,0 +1,22 @@ +/* + * File : board.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop 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 + * + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + + +#define MCK 50000000 + +void rt_hw_board_led_on(rt_uint32_t); +void rt_hw_board_led_off(rt_uint32_t); +void rt_hw_board_init(void); + +#endif diff --git a/bsp/microblaze/rtconfig.h b/bsp/microblaze/rtconfig.h new file mode 100755 index 000000000..674de50c4 --- /dev/null +++ b/bsp/microblaze/rtconfig.h @@ -0,0 +1,190 @@ +/* RT-Thread config file */ +#ifndef __RTTHREAD_CFG_H__ +#define __RTTHREAD_CFG_H__ + +#define IDLE_THREAD_STACK_SIZE 2048 + +/* RT_NAME_MAX*/ +#define RT_NAME_MAX 32 + +/* RT_ALIGN_SIZE*/ +#define RT_ALIGN_SIZE 4 + +/* PRIORITY_MAX*/ +#define RT_THREAD_PRIORITY_MAX 32 + +/* Tick per Second*/ +#define RT_TICK_PER_SECOND 100 + + +/* SECTION: RT_DEBUG */ +/* Thread Debug*/ +/* #define RT_THREAD_DEBUG */ + +/* Using Hook*/ +#define RT_USING_HOOK + +/* SECTION: IPC */ +/* Using Semaphore*/ +#define RT_USING_SEMAPHORE + +/* Using Mutex*/ +#define RT_USING_MUTEX + +/* Using Event*/ +#define RT_USING_EVENT + +/* Using Faset Event*/ +/* #define RT_USING_FASTEVENT */ + +/* Using MailBox*/ +#define RT_USING_MAILBOX + +/* Using Message Queue*/ +#define RT_USING_MESSAGEQUEUE + +/* SECTION: Memory Management */ +/* Using Memory Pool Management*/ +#define RT_USING_MEMPOOL + +/* Using Dynamic Heap Management*/ +#define RT_USING_HEAP + +/* Using Small MM*/ +#define RT_USING_SMALL_MEM + +/* Using SLAB Allocator*/ +/* #define RT_USING_SLAB */ + +/* SECTION: Device System */ +/* Using Device System*/ +#define RT_USING_DEVICE + +/* buffer size for UART reception*/ +#define RT_UART_RX_BUFFER_SIZE 64 + +/* buffer size for UART transmission*/ +#define RT_UART_TX_BUFFER_SIZE 64 + +/* Using UART1*/ +#define RT_USING_UART1 + +/* Using UART1*/ +/* #define RT_USING_UART2 */ + +/* Using UART1*/ +/* #define RT_USING_UART3 */ + +/* SECTION: Console options */ +#define RT_USING_CONSOLE +/* the buffer size of console*/ +#define RT_CONSOLEBUF_SIZE 256 + +/* SECTION: FinSH shell options */ +/* Using FinSH as Shell*/ +#define RT_USING_FINSH +/* use symbol table */ +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_STACK_SIZE 8192 +#define RT_USING_TC + + +/* SECTION: a runtime libc library */ +/* a runtime libc library*/ +/* #define RT_USING_NEWLIB */ +#define RT_USING_MINILIBC + +/* SECTION: C++ support */ +/* Using C++ support*/ +/* #define RT_USING_CPLUSPLUS */ + +/* SECTION: RTGUI support */ +/* using RTGUI support*/ +/* #define RT_USING_RTGUI */ + +/* SECTION: Device filesystem support */ +/* using DFS support*/ +/* #define RT_USING_DFS */ + +/* SECTION: EFSL filesystem support */ +/* using EFSL filesystem support*/ +/* #define RT_USING_EFSL */ + +/* SECTION: lwip, a lighwight TCP/IP protocol stack */ +/* Using lighweight TCP/IP protocol stack*/ +/* #define RT_USING_LWIP */ + +/* Using webserver goahead support*/ +/* #define RT_USING_WEBSERVER */ + +/* Using ftpserver support*/ +/* #define RT_USING_FTPSERVER */ + +/* Trace LwIP protocol*/ +/* #define RT_LWIP_DEBUG */ + +/* Enable ICMP protocol*/ +#define RT_LWIP_ICMP + +/* Enable IGMP protocol*/ +#define RT_LWIP_IGMP + +/* Enable UDP protocol*/ +#define RT_LWIP_UDP + +/* Enable TCP protocol*/ +#define RT_LWIP_TCP + +/* the number of simulatenously active TCP connections*/ +#define RT_LWIP_TCP_PCB_NUM 5 + +/* TCP sender buffer space*/ +#define RT_LWIP_TCP_SND_BUF 10240 + +/* Enable SNMP protocol*/ +/* #define RT_LWIP_SNMP */ + +/* Using DHCP*/ +/* #define RT_LWIP_DHCP */ + +/* ip address of target*/ +#define RT_LWIP_IPADDR0 192 +#define RT_LWIP_IPADDR1 168 +#define RT_LWIP_IPADDR2 0 +#define RT_LWIP_IPADDR3 30 + +/* gateway address of target*/ +#define RT_LWIP_GWADDR0 192 +#define RT_LWIP_GWADDR1 168 +#define RT_LWIP_GWADDR2 0 +#define RT_LWIP_GWADDR3 1 + +/* mask address of target*/ +#define RT_LWIP_MSKADDR0 255 +#define RT_LWIP_MSKADDR1 255 +#define RT_LWIP_MSKADDR2 255 +#define RT_LWIP_MSKADDR3 0 + +/* the number of blocks for pbuf*/ +#define RT_LWIP_PBUF_NUM 16 + +/* thread priority of tcpip thread*/ +#define RT_LWIP_TCPTHREAD_PRIORITY 128 + +/* mail box size of tcpip thread to wait for*/ +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 + +/* thread stack size of tcpip thread*/ +#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 + +/* thread priority of ethnetif thread*/ +#define RT_LWIP_ETHTHREAD_PRIORITY 144 + +/* mail box size of ethnetif thread to wait for*/ +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 32 + +/* thread stack size of ethnetif thread*/ +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 + +#endif diff --git a/bsp/microblaze/startup.c b/bsp/microblaze/startup.c new file mode 100755 index 000000000..16a23394b --- /dev/null +++ b/bsp/microblaze/startup.c @@ -0,0 +1,120 @@ +/* + * File : startup.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop 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 + * 2006-08-31 Bernard first implementation + * 2011-12-17 nl1031 for MicroBlaze + */ + +#include +#include + +//#include +#include "board.h" + +#ifdef RT_USING_FINSH +#include +extern void finsh_system_init(void); +#endif + +extern void rt_hw_led_flash(void); + + +/*@{*/ +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#endif + +#ifdef __GNUC__ +extern unsigned char __bss_start; +extern unsigned char __bss_end; +#endif + +extern void rt_hw_interrupt_init(void); +extern int rt_application_init(void); +#ifdef RT_USING_DEVICE +extern rt_err_t rt_hw_serial_init(void); +#endif + +/** + * This function will startup RT-Thread RTOS. + */ +void rtthread_startup(void) +{ + /* init hardware interrupt */ + rt_hw_interrupt_init(); + + /* init board */ + rt_hw_board_init(); + + rt_show_version(); + + /* init tick */ + rt_system_tick_init(); + + /* init kernel object */ + rt_system_object_init(); + + /* init timer system */ + rt_system_timer_init(); + +#ifdef RT_USING_HEAP +#ifdef __CC_ARM + rt_system_heap_init((void*)&Image$$RW_IRAM1$$ZI$$Limit, (void*)0x204000); +#elif __ICCARM__ + rt_system_heap_init(__segment_end("HEAP"), (void*)0x204000); +#else + rt_system_heap_init((void*)&__bss_end, (void*)(&__bss_end+0x4000)); +#endif +#endif + + /* init scheduler system */ + rt_system_scheduler_init(); + +#ifdef RT_USING_HOOK /* if the hook is used */ + /* set idle thread hook */ + rt_thread_idle_sethook(rt_hw_led_flash); +#endif + +//#ifdef RT_USING_DEVICE + /* init hardware serial device */ + rt_hw_serial_init(); + /* init all device */ + rt_device_init_all(); +//#endif + + /* init application */ + rt_application_init(); + +#ifdef RT_USING_FINSH + /* init finsh */ + finsh_system_init(); + finsh_set_device("uart1"); +#endif + + /* init idle thread */ + rt_thread_idle_init(); + + /* start scheduler */ + rt_system_scheduler_start(); + + /* never reach here */ + return ; +} + +int main (void) +{ + /* invoke rtthread_startup */ + rtthread_startup(); + + return 0; +} + +/*@}*/ diff --git a/libcpu/xilinx/microblaze/context_gcc.S b/libcpu/xilinx/microblaze/context_gcc.S new file mode 100755 index 000000000..74b7f50a5 --- /dev/null +++ b/libcpu/xilinx/microblaze/context_gcc.S @@ -0,0 +1,224 @@ +/* + * File : context_gcc.S + * 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://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-17 nl1031 first implementation for MicroBlaze. + * + */ + +#include "microbalze.inc" + + .text + .globl rt_interrupt_enter + .globl rt_interrupt_leave + +/* + * rt_base_t rt_hw_interrupt_disable() + * copy from ucos-ii + */ + + .globl rt_hw_interrupt_disable + .ent rt_hw_interrupt_disable + .align 2 +rt_hw_interrupt_disable: + ADDIK r1, r1, -4 + SW r4, r1, r0 + + MFS r3, RMSR + ANDNI r4, r3, IE_BIT + MTS RMSR, r4 + + LW r4, r1, r0 + ADDIK r1, r1, 4 + + AND r0, r0, r0 /* NO-OP - pipeline flush */ + AND r0, r0, r0 /* NO-OP - pipeline flush */ + AND r0, r0, r0 /* NO-OP - pipeline flush */ + + RTSD r15, 8 + AND r0, r0, r0 + .end rt_hw_interrupt_disable + +/* + * void rt_hw_interrupt_enable(rt_base_t level) + * copy from ucos-ii + */ + .globl rt_hw_interrupt_enable + .ent rt_hw_interrupt_enable + .align 2 +rt_hw_interrupt_enable: + RTSD r15, 8 + MTS rMSR, r5 /* Move the saved status from r5 into rMSR */ + .end rt_hw_interrupt_enable + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to) + * r5 --> from + * r6 --> to + */ + + .globl rt_interrupt_from_thread + .globl rt_interrupt_to_thread + .globl rt_hw_context_switch + .ent rt_hw_context_switch + .align 2 +rt_hw_context_switch: + PUSH_ALL + MFS r3, RMSR /* save the MSR */ + SWI r3, r1, STACK_RMSR + SWI r1, r5, 0 /* store sp in preempted tasks TCB */ + LWI r1, r6, 0 /* get new task stack pointer */ + + LWI r3, r1, STACK_RMSR + ANDI r3, r3, IE_BIT + BNEI r3, rt_hw_context_switch_ie /*if IE bit set,should be use RTID (return from interrupt). */ + + LWI r3, r1, STACK_RMSR + MTS RMSR,r3 + POP_ALL + ADDIK r1, r1, STACK_SIZE + RTSD r15, 8 + AND r0, r0, r0 + +rt_hw_context_switch_ie: + + LWI r3, r1, STACK_RMSR + ANDNI r3, r3, IE_BIT /* clear IE bit, prevent interrupt occur immediately*/ + MTS RMSR,r3 + LWI r3, r1, STACK_R03 + POP_ALL + ADDIK r1, r1, STACK_SIZE + RTID r14, 0 /* IE bit will be set automatically */ + AND r0, r0, r0 + .end rt_hw_context_switch + +/* + * void rt_hw_context_switch_to(rt_uint32 to) + * r5 --> to + */ + .globl rt_hw_context_switch_to + .ent rt_hw_context_switch_to + .align 2 +rt_hw_context_switch_to: + LWI r1, r5, 0 /* get new task stack pointer */ + LWI r3, r1, STACK_RMSR + ANDNI r3, r3, IE_BIT /* clear IE bit, prevent interrupt occur immediately*/ + MTS RMSR,r3 + POP_ALL + ADDIK r1, r1, STACK_SIZE + RTID r14, 0 /* IE bit will be set automatically */ + AND r0, r0, r0 + + .end rt_hw_context_switch_to + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to) + */ + .globl rt_thread_switch_interrupt_flag + .globl rt_hw_context_switch_interrupt + .ent rt_hw_context_switch_interrupt + .align 2 +rt_hw_context_switch_interrupt: + LA r3, r0, rt_thread_switch_interrupt_flag + LWI r4, r3, 0 /* load rt_thread_switch_interrupt_flag into r4 */ + + ANDI r4, r4, 1 + BNEI r4, _reswitch /* if rt_thread_switch_interrupt_flag = 1 */ + + ADDIK r4, r0, 1 /* set rt_thread_switch_interrupt_flag to 1 */ + SWI r4, r3, 0 + + LA r3, r0, rt_interrupt_from_thread /* set rt_interrupt_from_thread */ + SWI r5, r3, 0 /* rt_interrupt_from_thread = from */ +_reswitch: + LA r3, r0, rt_interrupt_to_thread /* set rt_interrupt_to_thread */ + SWI r6, r3, 0 /* rt_interrupt_to_thread = to */ + RTSD r15, 8 + AND r0, r0, r0 + .end rt_hw_context_switch_interrupt + + + .globl _interrupt_handler + .section .text + .align 2 + .ent _interrupt_handler + .type _interrupt_handler, @function + +_interrupt_handler: + PUSH_ALL + MFS r3, RMSR + ORI r3, r3, IE_BIT + SWI r3, r1, STACK_RMSR /* push MSR */ + + BRLID r15, rt_interrupt_enter + AND r0, r0, r0 + + BRLID r15, rt_hw_trap_irq + AND r0, r0, r0 + + BRLID r15, rt_interrupt_leave + AND r0, r0, r0 + + /* + * if rt_thread_switch_interrupt_flag set, jump to + * rt_hw_context_switch_interrupt_do and don't return + */ + LA r3, r0, rt_thread_switch_interrupt_flag + LWI r4, r3, 0 + + ANDI r4, r4, 1 + BNEI r4, rt_hw_context_switch_interrupt_do + + LWI r3, r1, STACK_RMSR + ANDNI r3, r3, IE_BIT + MTS RMSR,r3 + POP_ALL + ADDIK r1, r1, STACK_SIZE + + RTID r14, 0 + AND r0, r0, r0 + +/* + * void rt_hw_context_switch_interrupt_do(rt_base_t flag) + */ +rt_hw_context_switch_interrupt_do: + SWI r0, r3, 0 /* clear rt_thread_switch_interrupt_flag */ + + LA r3, r0, rt_interrupt_from_thread + LW r4, r0, r3 + SWI r1, r4, 0 /* store sp in preempted tasks's TCB */ + + LA r3, r0, rt_interrupt_to_thread + LW r4, r0, r3 + LWI r1, r4, 0 /* get new task's stack pointer */ + + LWI r3, r1, STACK_RMSR + ANDI r3, r3, IE_BIT + BNEI r3, return_with_ie /*if IE bit set,should be use RTID (return from interrupt). */ + + LWI r3, r1, STACK_RMSR + MTS RMSR,r3 + POP_ALL + ADDIK r1, r1, STACK_SIZE + RTSD r15, 8 + AND r0, r0, r0 + +return_with_ie: + + LWI r3, r1, STACK_RMSR + ANDNI r3, r3, IE_BIT /* clear IE bit, prevent interrupt occur immediately*/ + MTS RMSR,r3 + LWI r3, r1, STACK_R03 + POP_ALL + ADDIK r1, r1, STACK_SIZE + RTID r14, 0 /* IE bit will be set automatically */ + AND r0, r0, r0 + +.end _interrupt_handler diff --git a/libcpu/xilinx/microblaze/cpu.c b/libcpu/xilinx/microblaze/cpu.c new file mode 100755 index 000000000..50a0e34dc --- /dev/null +++ b/libcpu/xilinx/microblaze/cpu.c @@ -0,0 +1,35 @@ +/* + * File : cpu.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop 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 + * 2006-08-23 Bernard first version + */ + +#include + +/** + * this function will reset CPU + * + */ +void rt_hw_cpu_reset() +{ +} + +/** + * this function will shutdown CPU + * + */ +void rt_hw_cpu_shutdown() +{ + rt_kprintf("shutdown...\n"); + + while (1); +} + diff --git a/libcpu/xilinx/microblaze/microbalze.inc b/libcpu/xilinx/microblaze/microbalze.inc new file mode 100755 index 000000000..19128df3f --- /dev/null +++ b/libcpu/xilinx/microblaze/microbalze.inc @@ -0,0 +1,116 @@ +/* + * File : microblaze.inc + * 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://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-12-17 nl1031 first implementation for MicroBlaze. + * + */ + + + +.equ STACK_RMSR, 0x00 +.equ STACK_R02, 0x04 +.equ STACK_R03, 0x08 +.equ STACK_R04, 0x0C +.equ STACK_R05, 0x10 +.equ STACK_R06, 0x14 +.equ STACK_R07, 0x18 +.equ STACK_R08, 0x1C +.equ STACK_R09, 0x20 +.equ STACK_R10, 0x24 +.equ STACK_R11, 0x28 +.equ STACK_R12, 0x2C +.equ STACK_R13, 0x30 +.equ STACK_R14, 0x34 +.equ STACK_R15, 0x38 +.equ STACK_R17, 0x3C +.equ STACK_R18, 0x40 +.equ STACK_R19, 0x44 +.equ STACK_R20, 0x48 +.equ STACK_R21, 0x4C +.equ STACK_R22, 0x50 +.equ STACK_R23, 0x54 +.equ STACK_R24, 0x58 +.equ STACK_R25, 0x5C +.equ STACK_R26, 0x60 +.equ STACK_R27, 0x64 +.equ STACK_R28, 0x68 +.equ STACK_R29, 0x6C +.equ STACK_R30, 0x70 +.equ STACK_R31, 0x74 + +.equ STACK_SIZE, 0x78 +.equ IE_BIT, 0x02 + +.macro PUSH_ALL + ADDIK r1, r1, -STACK_SIZE + SWI r2, r1, STACK_R02 + SWI r3, r1, STACK_R03 + SWI r4, r1, STACK_R04 + SWI r5, r1, STACK_R05 + SWI r6, r1, STACK_R06 + SWI r7, r1, STACK_R07 + SWI r8, r1, STACK_R08 + SWI r9, r1, STACK_R09 + SWI r10, r1, STACK_R10 + SWI r11, r1, STACK_R11 + SWI r12, r1, STACK_R12 + SWI r13, r1, STACK_R13 + SWI r14, r1, STACK_R14 + SWI r15, r1, STACK_R15 + SWI r17, r1, STACK_R17 + SWI r18, r1, STACK_R18 + SWI r19, r1, STACK_R19 + SWI r20, r1, STACK_R20 + SWI r21, r1, STACK_R21 + SWI r22, r1, STACK_R22 + SWI r23, r1, STACK_R23 + SWI r24, r1, STACK_R24 + SWI r25, r1, STACK_R25 + SWI r26, r1, STACK_R26 + SWI r27, r1, STACK_R27 + SWI r28, r1, STACK_R28 + SWI r29, r1, STACK_R29 + SWI r30, r1, STACK_R30 + SWI r31, r1, STACK_R31 +.endm + +.macro POP_ALL + LWI r31, r1, STACK_R31 + LWI r30, r1, STACK_R30 + LWI r29, r1, STACK_R29 + LWI r28, r1, STACK_R28 + LWI r27, r1, STACK_R27 + LWI r26, r1, STACK_R26 + LWI r25, r1, STACK_R25 + LWI r24, r1, STACK_R24 + LWI r23, r1, STACK_R23 + LWI r22, r1, STACK_R22 + LWI r21, r1, STACK_R21 + LWI r20, r1, STACK_R20 + LWI r19, r1, STACK_R19 + LWI r18, r1, STACK_R18 + LWI r17, r1, STACK_R17 + LWI r15, r1, STACK_R15 + LWI r14, r1, STACK_R14 + LWI r13, r1, STACK_R13 + LWI r12, r1, STACK_R12 + LWI r11, r1, STACK_R11 + LWI r10, r1, STACK_R10 + LWI r9, r1, STACK_R09 + LWI r8, r1, STACK_R08 + LWI r7, r1, STACK_R07 + LWI r6, r1, STACK_R06 + LWI r5, r1, STACK_R05 + LWI r4, r1, STACK_R04 + LWI r3, r1, STACK_R03 + LWI r2, r1, STACK_R02 +.endm + diff --git a/libcpu/xilinx/microblaze/serial.c b/libcpu/xilinx/microblaze/serial.c new file mode 100755 index 000000000..be43c5ead --- /dev/null +++ b/libcpu/xilinx/microblaze/serial.c @@ -0,0 +1,310 @@ +/* + * 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-08-23 Bernard first version + * 2009-05-14 Bernard add RT-THread device interface + * + * 2011-12-17 nl1031 MicroBlaze + */ + +#include +#include +#include "serial.h" + +typedef volatile rt_uint32_t REG32; +struct rt_mb_uart_lite_hw +{ + REG32 Rx_FIFO; // Receiver Holding Register + REG32 Tx_FIFO; // Transmitter Holding Register + REG32 STAT_REG; // Channel Status Register + REG32 CTRL_REG; // Control Register +}; + +struct rt_mb_uart_lite +{ + struct rt_device parent; + + struct rt_mb_uart_lite_hw* hw_base; + rt_uint16_t peripheral_id; + rt_uint32_t baudrate; + + /* reception field */ + rt_uint16_t save_index, read_index; + rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE]; +}; +#ifdef RT_USING_UART1 +struct rt_mb_uart_lite serial1; +#endif + +static void rt_hw_serial_isr(void) +{ + unsigned int status; + rt_base_t level; + struct rt_device* device; + struct rt_mb_uart_lite* serial = RT_NULL; + +#ifdef RT_USING_UART1 + /* serial 1 */ + serial = &serial1; +#endif + RT_ASSERT(serial != RT_NULL); + + /* get generic device object */ + device = (rt_device_t)serial; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + /* get uart status register */ + status = serial->hw_base->STAT_REG; + while (status & XUL_SR_RX_FIFO_VALID_DATA) + { + /* get received character */ + serial->rx_buffer[serial->save_index] = serial->hw_base->Rx_FIFO; + + /* move to next position */ + serial->save_index ++; + if (serial->save_index >= RT_UART_RX_BUFFER_SIZE) + serial->save_index = 0; + + /* if the next position is read index, discard this 'read char' */ + if (serial->save_index == serial->read_index) + { + serial->read_index ++; + if (serial->read_index >= RT_UART_RX_BUFFER_SIZE) + serial->read_index = 0; + } + status = serial->hw_base->STAT_REG; + } + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + /* indicate to upper layer application */ + if (device->rx_indicate != RT_NULL) + device->rx_indicate(device, 1); + +} + +static rt_err_t rt_serial_init (rt_device_t dev) +{ + struct rt_mb_uart_lite* serial = (struct rt_mb_uart_lite*) dev; + + RT_ASSERT(serial != RT_NULL); + + RT_ASSERT(serial->peripheral_id != XPAR_INTC_0_UARTLITE_1_VEC_ID); + +// serial->hw_base->CTRL_REG = XUL_CR_FIFO_RX_RESET | /* Reset Receiver */ +// XUL_CR_FIFO_TX_RESET; /* Reset Transmitter */ + + /* reset rx index */ + serial->save_index = 0; + serial->read_index = 0; + + /* reset rx buffer */ + rt_memset(serial->rx_buffer, 0, RT_UART_RX_BUFFER_SIZE); + + return RT_EOK; +} + +static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag) +{ + struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; + RT_ASSERT(serial != RT_NULL); + + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* enable UART rx interrupt */ + serial->hw_base->CTRL_REG = XUL_CR_ENABLE_INTR; /* enable interrupt */ + + /* install UART handler */ + rt_hw_interrupt_install(serial->peripheral_id, (rt_isr_handler_t)rt_hw_serial_isr, RT_NULL); + rt_hw_interrupt_umask(serial->peripheral_id); + } + + return RT_EOK; +} + +static rt_err_t rt_serial_close(rt_device_t dev) +{ + struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; + RT_ASSERT(serial != RT_NULL); + + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* disable interrupt */ + serial->hw_base->CTRL_REG = 0; /* RxReady interrupt */ + } + + 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; + struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; + RT_ASSERT(serial != RT_NULL); + + /* point to buffer */ + ptr = (rt_uint8_t*) buffer; + + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + while (size) + { + /* interrupt receive */ + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + if (serial->read_index != serial->save_index) + { + *ptr = serial->rx_buffer[serial->read_index]; + + serial->read_index ++; + if (serial->read_index >= RT_UART_RX_BUFFER_SIZE) + serial->read_index = 0; + } + else + { + /* no data in rx buffer */ + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + break; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + ptr ++; size --; + } + + return (rt_uint32_t)ptr - (rt_uint32_t)buffer; + } + else if (dev->flag & RT_DEVICE_FLAG_DMA_RX) + { + /* not support right now */ + RT_ASSERT(0); + } + else + { + /* poll mode */ + while (size) + { + /* Wait for Full Rx Buffer */ + while (!(serial->hw_base->STAT_REG & XUL_SR_RX_FIFO_VALID_DATA)); + + /* Read Character */ + *ptr = serial->hw_base->Rx_FIFO; + ptr ++; + size --; + } + + return (rt_size_t)ptr - (rt_size_t)buffer; + } + + return 0; +} + +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; + struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; + RT_ASSERT(serial != RT_NULL); + + ptr = (rt_uint8_t*) buffer; + if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY) + { + if (dev->flag & RT_DEVICE_FLAG_STREAM) + { + /* it's a stream mode device */ + while (size) + { + /* stream mode */ + if (*ptr == '\n') + { + while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY)); + serial->hw_base->Tx_FIFO = '\r'; + } + + /* Wait for Empty Tx Buffer */ + while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY)); + + /* Transmit Character */ + serial->hw_base->Tx_FIFO = *ptr; + ptr ++; size --; + } + } + else + { + while (size) + { + /* Wait for Empty Tx Buffer */ + while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY)); + + /* Transmit Character */ + serial->hw_base->Tx_FIFO = *ptr; + ptr ++; size --; + } + } + } + + return (rt_size_t)ptr - (rt_size_t)buffer; +} + +static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args) +{ + return RT_EOK; +} + +rt_err_t rt_hw_serial_init() +{ + rt_device_t device; + +#ifndef RT_USING_CONSOLE + int Status; + + /* + * Initialize the UartLite driver so that it is ready to use. + */ + Status = XUartLite_Initialize(&uart_lite, RS232_DEVICE_ID); + if (Status != XST_SUCCESS) + { + return; + } + +#endif + +#ifdef RT_USING_UART1 + device = (rt_device_t) &serial1; + + /* init serial device private data */ + serial1.hw_base = (struct rt_mb_uart_lite_hw*)XPAR_USB_UART_BASEADDR; + serial1.peripheral_id = XPAR_INTC_0_UARTLITE_1_VEC_ID; + serial1.baudrate = 9600; + + /* set device virtual interface */ + 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; + + /* register uart1 on device subsystem */ + rt_device_register(device, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX); +#endif + + + return RT_EOK; +} + + diff --git a/libcpu/xilinx/microblaze/serial.h b/libcpu/xilinx/microblaze/serial.h new file mode 100755 index 000000000..090efa84e --- /dev/null +++ b/libcpu/xilinx/microblaze/serial.h @@ -0,0 +1,6 @@ +#ifndef __RT_SERIAL_H__ +#define __RT_SERIAL_H__ +#include "xuartlite_l.h" +#include "xparameters.h" + +#endif diff --git a/libcpu/xilinx/microblaze/stack.c b/libcpu/xilinx/microblaze/stack.c new file mode 100755 index 000000000..fff1348ee --- /dev/null +++ b/libcpu/xilinx/microblaze/stack.c @@ -0,0 +1,71 @@ +/* + * File : stack.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 + * 2011-12-17 nl1031 first implementation for MicroBlaze. + * + */ +#include +extern void *_SDA_BASE_; +extern void *_SDA2_BASE_; + + + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, + rt_uint8_t *stack_addr, void *texit) +{ + unsigned long *stk; + + stk = (unsigned long *)stack_addr; + stk--; + stk--; + *stk-- = 0; /* r31 */ + *stk-- = 0; /* r30 */ + *stk-- = 0; /* r29 */ + *stk-- = 0; /* r28 */ + *stk-- = 0; /* r27 */ + *stk-- = 0; /* r26 */ + *stk-- = 0; /* r25 */ + *stk-- = 0; /* r24 */ + *stk-- = 0; /* r23 */ + *stk-- = 0; /* r22 */ + *stk-- = 0; /* r21 */ + *stk-- = 0; /* r20 */ + *stk-- = 0; /* r19 */ + *stk-- = 0; /* r18 */ + *stk-- = 0; /* r17 */ + *stk-- = (unsigned long)texit; /* r15 = task return address*/ + *stk-- = (unsigned long)tentry; /* r14 = entry address*/ + *stk-- = (unsigned long)&_SDA_BASE_; /* r13 */ + *stk-- = 0; /* r12 */ + *stk-- = 0; /* r11 */ + *stk-- = 0; /* r10 */ + *stk-- = 0; /* r09 */ + *stk-- = 0; /* r08 */ + *stk-- = 0; /* r07 */ + *stk-- = 0; /* r06 */ + *stk-- = (unsigned long) parameter; /* r05 */ + *stk-- = 0; /* r04 */ + *stk-- = 0; /* r03 */ + *stk-- = (unsigned long)&_SDA2_BASE_; /* r02 */ + *stk = 2; /* enable interrupt */ + return (rt_uint8_t *)stk; +} + diff --git a/libcpu/xilinx/microblaze/trap.c b/libcpu/xilinx/microblaze/trap.c new file mode 100755 index 000000000..3b3f98d10 --- /dev/null +++ b/libcpu/xilinx/microblaze/trap.c @@ -0,0 +1,211 @@ +/* + * File : trap.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-08-23 Bernard first version + * 2011-12-17 nl1031 for MicroBlaze + * + */ + +#include +#include "xparameters.h" +#include "xintc.h" +#include "xintc_i.h" +#include "xintc_l.h" + + +#define MAX_HANDLERS XPAR_INTC_MAX_NUM_INTR_INPUTS +extern XIntc int_ctl; /* The instance of the Interrupt Controller */ + + +extern rt_uint32_t rt_interrupt_nest; + +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + + +void rt_hw_interrupt_handler(int vector) +{ + rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init() +{ + rt_base_t index; + + XIntc_Config *CfgPtr; + + + CfgPtr = &XIntc_ConfigTable[0]; + + + for (index = 0; index < MAX_HANDLERS; index ++) + { + CfgPtr->HandlerTable[index].Handler = (XInterruptHandler)rt_hw_interrupt_handler; + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + /* disable interrupt */ + XIntc_Disable(&int_ctl,vector); +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + XIntc_Enable(&int_ctl,vector); +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +void rt_hw_interrupt_install(int vector, rt_isr_handler_t new_handler, rt_isr_handler_t *old_handler) +{ + XIntc_Config *CfgPtr; + + CfgPtr = &XIntc_ConfigTable[0]; + + if(vector >= 0 && vector < MAX_HANDLERS) + { + if (*old_handler != RT_NULL) *old_handler = (rt_isr_handler_t)CfgPtr->HandlerTable[vector].Handler; + if (new_handler != RT_NULL) CfgPtr->HandlerTable[vector].Handler = (XInterruptHandler)new_handler; + } +} + +/*****************************************************************************/ +/** copy from XIntc_DeviceInterruptHandler in xintc_l.c nl1031 +* +* This function is the primary interrupt handler for the driver. It must be +* connected to the interrupt source such that is called when an interrupt of +* the interrupt controller is active. It will resolve which interrupts are +* active and enabled and call the appropriate interrupt handler. It uses +* the AckBeforeService flag in the configuration data to determine when to +* acknowledge the interrupt. Highest priority interrupts are serviced first. +* The driver can be configured to service only the highest priority interrupt +* or all pending interrupts using the {XIntc_SetOptions()} function or +* the {XIntc_SetIntrSrvOption()} function. +* +* This function assumes that an interrupt vector table has been previously +* initialized. It does not verify that entries in the table are valid before +* calling an interrupt handler. +* +* +* @return None. +* +* @note +* +* The constant XPAR_INTC_MAX_NUM_INTR_INPUTS must be setup for this to compile. +* Interrupt IDs range from 0 - 31 and correspond to the interrupt input signals +* for the interrupt controller. XPAR_INTC_MAX_NUM_INTR_INPUTS specifies the +* highest numbered interrupt input signal that is used. +* +******************************************************************************/ + + +void rt_hw_trap_irq(void ) +{ + u32 intr_status; + u32 intr_mask = 1; + int intr_number; + volatile u32 reg; /* used as bit bucket */ + XIntc_Config *cfg_ptr; + + + /* Get the configuration data using the device ID */ + cfg_ptr = &XIntc_ConfigTable[0]; + + /* Get the interrupts that are waiting to be serviced */ + intr_status = XIntc_GetIntrStatus(XPAR_INTC_0_BASEADDR); + + /* Service each interrupt that is active and enabled by checking each + * bit in the register from LSB to MSB which corresponds to an interrupt + * intput signal + */ + for (intr_number = 0; intr_number < XPAR_INTC_MAX_NUM_INTR_INPUTS; intr_number++) + { + if (intr_status & 1) + { + XIntc_VectorTableEntry *table_ptr; + + /* If the interrupt has been setup to acknowledge it + * before servicing the interrupt, then ack it + */ + if (cfg_ptr->AckBeforeService & intr_mask) + { + XIntc_AckIntr(cfg_ptr->BaseAddress, intr_mask); + } + + /* The interrupt is active and enabled, call the + * interrupt handler that was setup with the specified + * parameter + */ + table_ptr = &(cfg_ptr->HandlerTable[intr_number]); + table_ptr->Handler(table_ptr->CallBackRef); + + /* If the interrupt has been setup to acknowledge it + * after it has been serviced then ack it + */ + if ((cfg_ptr->AckBeforeService & intr_mask) == 0) + { + XIntc_AckIntr(cfg_ptr->BaseAddress, intr_mask); + } + + /* + * Read the ISR again to handle architectures with posted write + * bus access issues. + */ + reg = XIntc_GetIntrStatus(cfg_ptr->BaseAddress); + + /* + * If only the highest priority interrupt is to be + * serviced, exit loop and return after servicing + * the interrupt + */ + if (cfg_ptr->Options == XIN_SVC_SGL_ISR_OPTION) + { + return; + } + } + + /* Move to the next interrupt to check */ + intr_mask <<= 1; + intr_status >>= 1; + + /* If there are no other bits set indicating that all interrupts + * have been serviced, then exit the loop + */ + if (intr_status == 0) + { + break; + } + } +} + +