]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_core/ck802/core_ck802.c
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
[freertos] / FreeRTOS / Demo / T-HEAD_CB2201_CDK / csi / csi_core / ck802 / core_ck802.c
1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /******************************************************************************
18  * @file     core_ck802.c
19  * @brief    CSI CK802 Core Peripheral Access Layer File
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23
24 #include <stdint.h>
25 #include <core_ck802.h>
26 #include <config.h>
27
28 /*******************************************************************************
29  *                Hardware Abstraction Layer
30   Core Function Interface contains:
31   - Core VIC Functions
32   - Core CORET Functions
33   - Core Register Access Functions
34  ******************************************************************************/
35 /**
36   \defgroup CSI_Core_FunctionInterface Functions and Instructions Reference
37 */
38
39 /* ##########################   NVIC functions  #################################### */
40 /**
41   \ingroup  CSI_Core_FunctionInterface
42   \defgroup CSI_Core_NVICFunctions NVIC Functions
43   \brief    Functions that manage interrupts and exceptions via the NVIC.
44   @{
45  */
46
47 /* Interrupt Priorities are WORD accessible only under CSKYv6M                   */
48 /* The following MACROS handle generation of the register offset and byte masks */
49 #define _BIT_SHIFT(IRQn)         (  ((((uint32_t)(int32_t)(IRQn))         )      &  0x03UL) * 8UL)
50 #define _IP_IDX(IRQn)            (   (((uint32_t)(int32_t)(IRQn))                >>    2UL)      )
51
52 static uint32_t s_nvic_prio_bits = __NVIC_PRIO_BITS;
53
54 /**
55   \brief   initialize the NVIC interrupt controller
56   \param [in]      prio_bits  the priority bits of NVIC interrupt controller.
57  */
58 void drv_nvic_init(uint32_t prio_bits)
59 {
60     if (s_nvic_prio_bits >= 8U) {
61         return;
62     }
63
64     s_nvic_prio_bits = prio_bits;
65 }
66
67 /**
68   \brief   Enable External Interrupt
69   \details Enables a device-specific interrupt in the NVIC interrupt controller.
70   \param [in]      IRQn  External interrupt number. Value cannot be negative.
71  */
72 void drv_nvic_enable_irq(int32_t IRQn)
73 {
74         NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
75     NVIC->ISSR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
76 }
77
78 /**
79   \brief   Disable External Interrupt
80   \details Disables a device-specific interrupt in the NVIC interrupt controller.
81   \param [in]      IRQn  External interrupt number. Value cannot be negative.
82  */
83 void drv_nvic_disable_irq(int32_t IRQn)
84 {
85     NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
86 }
87
88 /**
89   \brief   Enable External Secure Interrupt
90   \details Enables a secure device-specific interrupt in the NVIC interrupt controller.
91   \param [in]      IRQn  External interrupt number. Value cannot be negative.
92  */
93 void drv_nvic_enable_sirq(int32_t IRQn)
94 {
95     NVIC->ISSR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
96 }
97
98 /**
99   \brief   Get Pending Interrupt
100   \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
101   \param [in]      IRQn  Interrupt number.
102   \return             0  Interrupt status is not pending.
103   \return             1  Interrupt status is pending.
104  */
105 uint32_t drv_nvic_get_pending_irq(int32_t IRQn)
106 {
107     return ((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
108 }
109
110 /**
111   \brief   Set Pending Interrupt
112   \details Sets the pending bit of an external interrupt.
113   \param [in]      IRQn  Interrupt number. Value cannot be negative.
114  */
115 void drv_nvic_set_pending_irq(int32_t IRQn)
116 {
117     NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
118 }
119
120 /**
121   \brief   Clear Pending Interrupt
122   \details Clears the pending bit of an external interrupt.
123   \param [in]      IRQn  External interrupt number. Value cannot be negative.
124  */
125 void drv_nvic_clear_pending_irq(int32_t IRQn)
126 {
127     NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
128 }
129
130 /**
131   \brief   Get Wake up Interrupt
132   \details Reads the wake up register in the NVIC and returns the pending bit for the specified interrupt.
133   \param [in]      IRQn  Interrupt number.
134   \return             0  Interrupt is not set as wake up interrupt.
135   \return             1  Interrupt is set as wake up interrupt.
136  */
137 uint32_t drv_nvic_get_wakeup_irq(int32_t IRQn)
138 {
139     return ((uint32_t)(((NVIC->IWER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
140 }
141
142 /**
143   \brief   Set Wake up Interrupt
144   \details Sets the wake up bit of an external interrupt.
145   \param [in]      IRQn  Interrupt number. Value cannot be negative.
146  */
147 void drv_nvic_set_wakeup_irq(int32_t IRQn)
148 {
149     NVIC->IWER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
150 }
151
152 /**
153   \brief   Clear Wake up Interrupt
154   \details Clears the wake up bit of an external interrupt.
155   \param [in]      IRQn  External interrupt number. Value cannot be negative.
156  */
157 void drv_nvic_clear_wakeup_irq(int32_t IRQn)
158 {
159     NVIC->IWDR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
160 }
161
162 /**
163   \brief   Get Active Interrupt
164   \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
165   \param [in]      IRQn  Device specific interrupt number.
166   \return             0  Interrupt status is not active.
167   \return             1  Interrupt status is active.
168   \note    IRQn must not be negative.
169  */
170 uint32_t drv_nvic_get_active(int32_t IRQn)
171 {
172     return ((uint32_t)(((NVIC->IABR[0] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
173 }
174
175 /**
176   \brief   Set Threshold register
177   \details set the threshold register in the NVIC.
178   \param [in]      VectThreshold  specific vecter threshold.
179   \param [in]      PrioThreshold  specific priority threshold.
180  */
181 void drv_nvic_set_threshold(uint32_t VectThreshold, uint32_t PrioThreshold)
182 {
183     NVIC->IPTR = 0x80000000 | (((VectThreshold + 32) & 0xFF) << 8) | ((PrioThreshold & 0x3) << 6);
184 }
185
186 /**
187   \brief   Set Interrupt Priority
188   \details Sets the priority of an interrupt.
189   \note    The priority cannot be set for every core interrupt.
190   \param [in]      IRQn  Interrupt number.
191   \param [in]  priority  Priority to set.
192  */
193 void drv_nvic_set_prio(int32_t IRQn, uint32_t priority)
194 {
195     NVIC->IPR[_IP_IDX(IRQn)]  = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)]  & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
196                                  (((priority << (8U - s_nvic_prio_bits)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
197 }
198
199 /**
200   \brief   Get Interrupt Priority
201   \details Reads the priority of an interrupt.
202            The interrupt number can be positive to specify an external (device specific) interrupt,
203            or negative to specify an internal (core) interrupt.
204   \param [in]   IRQn  Interrupt number.
205   \return             Interrupt Priority.
206                       Value is aligned automatically to the implemented priority bits of the microcontroller.
207  */
208 uint32_t drv_nvic_get_prio(int32_t IRQn)
209 {
210     return ((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - s_nvic_prio_bits)));
211 }
212
213
214 /*@} end of CSI_Core_NVICFunctions */
215
216 /* ##################################    SysTick function  ############################################ */
217 /**
218   \ingroup  CSI_Core_FunctionInterface
219   \defgroup CSI_Core_SysTickFunctions SysTick Functions
220   \brief    Functions that configure the System.
221   @{
222  */
223
224
225 /**
226   \brief   CORE timer Configuration
227   \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
228            Counter is in free running mode to generate periodic interrupts.
229   \param [in]  ticks  Number of ticks between two interrupts.
230   \param [in]  IRQn   core timer Interrupt number.
231   \return          0  Function succeeded.
232   \return          1  Function failed.
233   \note    When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
234            function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
235            must contain a vendor-specific implementation of this function.
236  */
237 uint32_t drv_coret_config(uint32_t ticks, int32_t IRQn)
238 {
239     if ((ticks - 1UL) > CORET_LOAD_RELOAD_Msk) {
240         return (1UL);                                                   /* Reload value impossible */
241     }
242
243     CORET->LOAD  = (uint32_t)(ticks - 1UL);                           /* set reload register */
244     //drv_nvic_set_prio(IRQn, (1UL << s_nvic_prio_bits) - 1UL);  fix me  /* set Priority for Systick Interrupt */
245     CORET->VAL   = 0UL;                                               /* Load the CORET Counter Value */
246     CORET->CTRL  = CORET_CTRL_CLKSOURCE_Msk |
247                    CORET_CTRL_TICKINT_Msk |
248                    CORET_CTRL_ENABLE_Msk;                           /* Enable CORET IRQ and CORET Timer */
249     return (0UL);                                                     /* Function successful */
250 }
251
252 /**
253   \brief   get CORE timer reload value
254   \return          CORE timer counter value.
255  */
256 uint32_t drv_coret_get_load(void)
257 {
258     return CORET->LOAD;
259 }
260
261 /**
262   \brief   get CORE timer counter value
263   \return          CORE timer counter value.
264  */
265 uint32_t drv_coret_get_value(void)
266 {
267     return CORET->VAL;
268 }
269
270 /*@} end of CSI_Core_SysTickFunctions */
271
272 #if 0
273 /* ##################################### DCC function ########################################### */
274 /**
275   \ingroup  CSI_Core_FunctionInterface
276   \defgroup CSI_core_DebugFunctions HAD Functions
277   \brief    Functions that access the HAD debug interface.
278   @{
279  */
280
281 /**
282   \brief   HAD Send Character
283   \details Transmits a character via the HAD channel 0, and
284            \li Just returns when no debugger is connected that has booked the output.
285            \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
286   \param [in]     ch  Character to transmit.
287   \returns            Character to transmit.
288  */
289 uint32_t HAD_SendChar(uint32_t ch)
290 {
291     DCC->DERJR = (uint8_t)ch;
292
293     return (ch);
294 }
295
296
297 /**
298   \brief   HAD Receive Character
299   \details Inputs a character via the external variable \ref HAD_RxBuffer.
300   \return             Received character.
301   \return         -1  No character pending.
302  */
303 int32_t HAD_ReceiveChar(void)
304 {
305     int32_t ch = -1;                           /* no character available */
306
307     if (_FLD2VAL(DCC_EHSR_JW, DCC->EHSR)) {
308         ch = DCC->DERJW;
309     }
310
311     return (ch);
312 }
313
314
315 /**
316   \brief   HAD Check Character
317   \details Checks whether a character is pending for reading in the variable \ref HAD_RxBuffer.
318   \return          0  No character available.
319   \return          1  Character available.
320  */
321 int32_t HAD_CheckChar(void)
322 {
323     return _FLD2VAL(DCC_EHSR_JW, DCC->EHSR);                              /* no character available */
324 }
325
326 #endif
327
328 /*@} end of CSI_core_DebugFunctions */