cpuport.c 6.9 KB
Newer Older
A
ArcherChang 已提交
1 2
/*
 * File      : cpuport.c
B
Bernard Xiong 已提交
3 4 5 6
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
A
ArcherChang 已提交
7
 *
B
Bernard Xiong 已提交
8 9 10 11 12 13 14 15
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
A
ArcherChang 已提交
16 17 18
 *
 * Change Logs:
 * Date         Author      Notes
B
Bernard Xiong 已提交
19
 * 2017-08-25   Archer      first version
A
ArcherChang 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33
 */

#include <rtthread.h>

#include "nds32.h"

/*
 * Initialise the stack of a task to look exactly as if a call to
 * SAVE_CONTEXT had been called.
 *
 * See header file for description.
 *
 *
 * Stack Layout:
B
Bernard Xiong 已提交
34
 *                High  |-----------------|
A
ArcherChang 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
 *                      |       $R5       |
 *                      |-----------------|
 *                      |        .        |
 *                      |        .        |
 *                      |-----------------|
 *                      |       $R0       |
 *                      |-----------------|
 *                      |       $R30 (LP) |
 *                      |-----------------|
 *                      |       $R29 (GP) |
 *                      |-----------------|
 *                      |       $R28 (FP) |
 *                      |-----------------|
 *                      |   $R15   $R27   |
 *                      |-----------------|
 *                      |   $R10   $R26   |
 *                      |-----------------|
 *                      |        .        |
 *                      |        .        |
 *                      |-----------------|
 *                      |       $R6       |
 *                      |-----------------|
 *                      |       $IFC_LP   | (Option)
 *                      |-----------------|
 *                      |   $LC/$LE/$LB   | (Option)
 *                      |       (ZOL)     |
 *                      |-----------------|
 *                      |       $IPSW     |
 *                      |-----------------|
 *                      |       $IPC      |
 *                      |-----------------|
 *                      |    Dummy word   | (Option, only exist when IFC & ZOL both configured)
 *                      |-----------------|
 *                      |       $FPU      | (Option)
 *                      |-----------------|
 *                Low
 *
 */

struct stack_frame
{
    rt_uint32_t topOfStack[34];
};

/* flag in interrupt handling */
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
/* exception hook */
static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;

rt_base_t rt_hw_interrupt_disable(void)
{
B
Bernard Xiong 已提交
87
    rt_base_t level = __nds32__mfsr(NDS32_SR_PSW);
A
ArcherChang 已提交
88

B
Bernard Xiong 已提交
89
    GIE_DISABLE();
A
ArcherChang 已提交
90

B
Bernard Xiong 已提交
91
    return level;
A
ArcherChang 已提交
92 93 94 95
}

void rt_hw_interrupt_enable(rt_base_t level)
{
B
Bernard Xiong 已提交
96 97
    if (level & PSW_mskGIE)
        GIE_ENABLE();
A
ArcherChang 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
}

/* For relax support, must initial $gp at task init*/
extern uint32_t _SDA_BASE_ __attribute__ ((weak));

/**************************************************************
 * 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)
{
B
Bernard Xiong 已提交
118 119
    rt_int32_t i;
    rt_uint32_t *pxTopOfStack;
A
ArcherChang 已提交
120

B
Bernard Xiong 已提交
121
    pxTopOfStack = (rt_uint32_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 4);
A
ArcherChang 已提交
122

B
Bernard Xiong 已提交
123 124 125 126 127
    /* Simulate the stack frame as it would be created by a context switch */
    /* R0 ~ R5 registers */
    for (i = 5; i >= 1; i--)                         /* R5, R4, R3, R2 and R1. */
        *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
    *--pxTopOfStack = (rt_uint32_t)parameter;        /* R0 : Argument */
A
ArcherChang 已提交
128

B
Bernard Xiong 已提交
129 130 131 132
    /* R6 ~ R30 registers */
    *--pxTopOfStack = (rt_uint32_t)texit;   /* R30: $LP */
    *--pxTopOfStack = (rt_uint32_t)&_SDA_BASE_;         /* R29: $GP */
    *--pxTopOfStack = (rt_uint32_t)0x2828282828;        /* R28: $FP */
A
ArcherChang 已提交
133
#ifdef __NDS32_REDUCE_REGS__
B
Bernard Xiong 已提交
134 135 136
    *--pxTopOfStack = (rt_uint32_t)0x1515151515;        /* R15 */
    for (i = 10; i >= 6; i--)                           /* R10 ~ R6 */
        *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
A
ArcherChang 已提交
137
#else
B
Bernard Xiong 已提交
138 139
    for (i = 27; i >= 6; i--)                           /* R27 ~ R6 */
        *--pxTopOfStack = (rt_uint32_t)0x01010101UL * i;
A
ArcherChang 已提交
140 141
#endif

B
Bernard Xiong 已提交
142
    /* IFC system register */
A
ArcherChang 已提交
143
#ifdef __TARGET_IFC_EXT
B
Bernard Xiong 已提交
144
    *--pxTopOfStack = (rt_uint32_t)0x0;                 /* $IFC_LP */
A
ArcherChang 已提交
145 146
#endif

B
Bernard Xiong 已提交
147
    /* ZOL system registers */
A
ArcherChang 已提交
148
#ifdef __TARGET_ZOL_EXT
B
Bernard Xiong 已提交
149 150 151
    *--pxTopOfStack = (rt_uint32_t)0x0;                 /* $LC */
    *--pxTopOfStack = (rt_uint32_t)0x0;                 /* $LE */
    *--pxTopOfStack = (rt_uint32_t)0x0;                 /* $LB */
A
ArcherChang 已提交
152 153
#endif

B
Bernard Xiong 已提交
154 155 156 157 158
    /* IPSW and IPC system registers */
    /* Default IPSW: enable GIE, set CPL to 7, clear IFCON */
    i = (__nds32__mfsr(NDS32_SR_PSW) | PSW_mskGIE | PSW_mskCPL) & ~PSW_mskIFCON;
    *--pxTopOfStack = (rt_uint32_t)i;                /* $IPSW */
    *--pxTopOfStack = (rt_uint32_t)tentry;           /* $IPC */
A
ArcherChang 已提交
159

B
Bernard Xiong 已提交
160
    /* Dummy word for 8-byte stack alignment */
A
ArcherChang 已提交
161
#if defined(__TARGET_IFC_EXT) && defined(__TARGET_ZOL_EXT)
B
Bernard Xiong 已提交
162
    *--pxTopOfStack = (rt_uint32_t)0xFFFFFFFF;          /* Dummy */
A
ArcherChang 已提交
163 164
#endif

B
Bernard Xiong 已提交
165
    /* FPU registers */
A
ArcherChang 已提交
166
#ifdef __TARGET_FPU_EXT
B
Bernard Xiong 已提交
167 168
    for (i = 0; i < FPU_REGS; i++)
        *--pxTopOfStack = (rt_uint32_t)0x0;         /* FPU */
A
ArcherChang 已提交
169 170
#endif

B
Bernard Xiong 已提交
171
    return (rt_uint8_t *)pxTopOfStack;
A
ArcherChang 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
}

/**
 * This function set the hook, which is invoked on fault exception handling.
 *
 * @param exception_handle the exception handling hook function.
 */
void rt_hw_exception_install(rt_err_t (*exception_handle)(void* context))
{
    rt_exception_hook = exception_handle;
}

#ifdef RT_USING_CPU_FFS
/**
 * This function finds the first bit set (beginning with the least significant bit)
 * in value and return the index of that bit.
 *
 * Bits are numbered starting at 1 (the least significant bit).  A return value of
 * zero from any of these functions means that the argument was zero.
 *
 * @return return the index of the first bit set. If value is 0, then this function
 * shall return 0.
 */
B
Bernard Xiong 已提交
195
#if defined(__GNUC__)
A
ArcherChang 已提交
196 197 198 199 200 201 202
int __rt_ffs(int value)
{
    return __builtin_ffs(value);
}
#endif

#endif