1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 #include "los_compiler.h"
20
21 #include <nds_intrinsic.h>
22 #include <stdint.h>
23
24 #include <B91/sys.h>
25
26 #define MCACHE_CTL_ICACHE 1
27 #define MCACHE_CTL_DCACHE 2
28
29 #define SWIRE_MAGIC_REG 0x100c01
30 #define SWIRE_MAGIC_VALUE 0x40
31
32 typedef void (*InitFunc)(void);
33
34 extern UINT32 _ITB_BASE_;
35
36 extern UINT32 SEG_RETENTION_DATA_LMA_START[], SEG_RETENTION_DATA_VMA_START[], SEG_RETENTION_DATA_VMA_END[];
37 extern UINT32 SEG_RAMCODE_LMA_START[], SEG_RAMCODE_VMA_START[], SEG_RAMCODE_VMA_END[];
38 extern UINT32 SEG_DATA_LMA_START[], SEG_DATA_VMA_START[], SEG_DATA_VMA_END[];
39 extern UINT32 SEG_BSS_VMA_START[], SEG_BSS_VMA_END[];
40 extern UINT32 __int_stack_start[], __int_stack_end[];
41
42 extern InitFunc __preinit_array_start[] __attribute__((weak));
43 extern InitFunc __preinit_array_end[] __attribute__((weak));
44 extern InitFunc __init_array_start[] __attribute__((weak));
45 extern InitFunc __init_array_end[] __attribute__((weak));
46 extern InitFunc __fini_array_start[] __attribute__((weak));
47 extern InitFunc __fini_array_end[] __attribute__((weak));
48
49 #define STACK_MAGIC UINT32_C(0xDEADBEEF)
50
51 STATIC VOID BoardConfigInnerSafe(VOID);
52
53 #ifdef __GNUC__
54 #pragma GCC push_options
55 #pragma GCC optimize("-fno-stack-protector")
56 #endif /* __GNUC__ */
57
CopyBuf32(UINT32 * dst,const UINT32 * dstEnd,const UINT32 * src)58 __attribute__((noinline)) STATIC VOID CopyBuf32(UINT32 *dst, const UINT32 *dstEnd, const UINT32 *src)
59 {
60 while (dst < dstEnd) {
61 *dst++ = *src++;
62 }
63 }
64
65 #define COPY_SEGMENT(_SEGNAME_) CopyBuf32((_SEGNAME_##_VMA_START), (_SEGNAME_##_VMA_END), (_SEGNAME_##_LMA_START))
66
BoardConfigInner(void)67 __attribute__((used)) static void BoardConfigInner(void)
68 {
69 for (UINT32 *p = SEG_BSS_VMA_START; p < SEG_BSS_VMA_END; ++p) {
70 *p = 0;
71 }
72
73 COPY_SEGMENT(SEG_RETENTION_DATA);
74 COPY_SEGMENT(SEG_RAMCODE);
75 COPY_SEGMENT(SEG_DATA);
76
77 BoardConfigInnerSafe();
78 }
79
80 /*
81 * Use "naked" attribute to prevent stack usage before stack is initialized
82 */
BoardConfig(void)83 __attribute__((naked)) void BoardConfig(void)
84 {
85 write_reg8(SWIRE_MAGIC_REG, SWIRE_MAGIC_VALUE);
86
87 #ifdef __nds_execit
88 /* Initialize EXEC.IT table */
89 __builtin_riscv_csrw((UINT32)&_ITB_BASE_, NDS_UITB);
90 #endif /* __nds_execit */
91
92 /* Enable I/D-Cache */
93 UINT32 mcacheCtl = __builtin_riscv_csrr(NDS_MCACHE_CTL);
94 mcacheCtl |= MCACHE_CTL_ICACHE; /* I-Cache */
95 mcacheCtl |= MCACHE_CTL_DCACHE; /* D-Cache */
96 __builtin_riscv_csrw(mcacheCtl, NDS_MCACHE_CTL);
97 __asm__ volatile("fence.i");
98
99 for (UINT32 *p = __int_stack_start; p < __int_stack_end; ++p) {
100 *p = STACK_MAGIC;
101 }
102
103 __asm__ volatile("j BoardConfigInner");
104 }
105
106 #ifdef __GNUC__
107 #pragma GCC pop_options
108 #endif /* __GNUC__ */
109
110 /**
111 * @brief BoardConfigInnerSafe is safe part of BoardConfig without disabled stack protection
112 */
BoardConfigInnerSafe(VOID)113 STATIC VOID BoardConfigInnerSafe(VOID)
114 {
115 for (InitFunc *f = __preinit_array_start; f < __preinit_array_end; ++f) {
116 (*f)();
117 }
118
119 for (InitFunc *f = __init_array_start; f < __init_array_end; ++f) {
120 (*f)();
121 }
122
123 for (InitFunc *f = __fini_array_start; f < __fini_array_end; ++f) {
124 (*f)();
125 }
126 }
127