1 /* 2 * File : cpuport.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2009 - 2012, RT-Thread Development Team 5 * 6 * The license and distribution terms for this file may be 7 * found in the file LICENSE in this distribution or at 8 * http://www.rt-thread.org/license/LICENSE 9 * 10 * Change Logs: 11 * Date Author Notes 12 * 2011-02-23 Bernard the first version 13 * 2012-09-25 lgnq save texit address in to thread stack 14 */ 15 16 #include <rtthread.h> 17 18 extern volatile rt_uint8_t rt_interrupt_nest; 19 20 /* switch flag on interrupt and thread pointer to save switch record */ 21 rt_uint32_t rt_interrupt_from_thread; 22 rt_uint32_t rt_interrupt_to_thread; 23 rt_uint8_t rt_thread_switch_interrupt_flag; 24 25 /** 26 * This function will initialize hardware interrupt 27 */ 28 void rt_hw_interrupt_init(void) 29 { 30 /* init interrupt nest, and context in thread sp */ 31 rt_interrupt_nest = 0; 32 rt_interrupt_from_thread = 0; 33 rt_interrupt_to_thread = 0; 34 rt_thread_switch_interrupt_flag = 0; 35 } 36 37 /** 38 * This function will initialize thread stack 39 * 40 * @param tentry the entry of thread 41 * @param parameter the parameter of entry 42 * @param stack_addr the beginning stack address 43 * @param texit the function will be called when thread exit 44 * 45 * @return stack address 46 */ 47 rt_uint8_t *rt_hw_stack_init(void *tentry, 48 void *parameter, 49 rt_uint8_t *stack_addr, 50 void *texit) 51 { 52 rt_uint16_t *pstk16; 53 rt_uint16_t flag; 54 55 flag = 0x0040; 56 pstk16 = (rt_uint16_t *)stack_addr; 57 58 *pstk16-- = (rt_uint32_t)texit >> 16L; 59 *pstk16-- = (rt_uint32_t)texit & 0x0000FFFFL; 60 61 /* Simulate ISR entry */ 62 *pstk16-- = (flag&0x00FF) | /* The lowest byte of the FLAG register */ 63 (((rt_uint32_t)tentry>>8)&0x00000F00) | /* The highest nibble of the PC register */ 64 ((flag<<4)&0xF000); /* The highest nibble of the FLAG register */ 65 *pstk16-- = (((rt_uint32_t)tentry)&0x0000FFFF); /* The lowest bytes of the PC register */ 66 67 /* Save registers onto stack frame */ 68 *pstk16-- = (rt_uint16_t)0xFBFB; /* FB register */ 69 *pstk16-- = (rt_uint16_t)0x3B3B; /* SB register */ 70 *pstk16-- = (rt_uint16_t)0xA1A1; /* A1 register */ 71 *pstk16-- = (rt_uint16_t)0xA0A0; /* A0 register */ 72 *pstk16-- = (rt_uint16_t)0x3333; /* R3 register */ 73 *pstk16-- = (rt_uint32_t)parameter >> 16L; /* Pass argument in R2 register */ 74 *pstk16-- = (rt_uint32_t)parameter & 0x0000FFFFL; /* Pass argument in R1 register */ 75 *pstk16 = (rt_uint16_t)0x0000; /* R0 register */ 76 77 /* return task's current stack address */ 78 return (rt_uint8_t *)pstk16; 79 } 80 81 void rt_hw_context_switch(rt_uint32_t from, rt_uint32_t to) 82 { 83 rt_interrupt_from_thread = from; 84 rt_interrupt_to_thread = to; 85 asm("INT #0"); 86 } 87 88 void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to) 89 { 90 if (rt_thread_switch_interrupt_flag != 1) 91 { 92 rt_thread_switch_interrupt_flag = 1; 93 rt_interrupt_from_thread = from; 94 } 95 rt_interrupt_to_thread = to; 96 } 97 98 #if defined(__GNUC__) 99 rt_base_t rt_hw_interrupt_disable(void) 100 { 101 register rt_uint16_t temp; 102 103 asm("STC FLG, %0":"=r" (temp)); 104 asm("FCLR I"); 105 106 return (rt_base_t)temp; 107 } 108 109 void rt_hw_interrupt_enable(rt_base_t level) 110 { 111 register rt_uint16_t temp; 112 113 temp = level & 0xffff; 114 asm("LDC %0, FLG": :"r" (temp)); 115 } 116 #endif