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 */
rt_hw_interrupt_init(void)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 */
rt_hw_stack_init(void * tentry,void * parameter,rt_uint8_t * stack_addr,void * texit)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
rt_hw_context_switch(rt_uint32_t from,rt_uint32_t to)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
rt_hw_context_switch_interrupt(rt_uint32_t from,rt_uint32_t to)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__)
rt_hw_interrupt_disable(void)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
rt_hw_interrupt_enable(rt_base_t level)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