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