xref: /nrf52832-nimble/rt-thread/libcpu/m16c/m16c62p/cpuport.c (revision 104654410c56c573564690304ae786df310c91fc)
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