blob: 4680ec310271eea70e5eefcf99f70948702ca137 [file] [log] [blame]
Kévin Redon69b92d92019-01-24 16:39:20 +01001/**
2 * \file
3 *
4 * \brief Core related functionality implementation.
5 *
6 * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Subject to your compliance with these terms, you may use Microchip
13 * software and any derivatives exclusively with Microchip products.
14 * It is your responsibility to comply with third party license terms applicable
15 * to your use of third party software (including open source software) that
16 * may accompany Microchip software.
17 *
18 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
19 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
20 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
21 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
22 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
23 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
24 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
25 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
26 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
27 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
28 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
29 *
30 * \asf_license_stop
31 *
32 */
33
34#include <hpl_core.h>
35#include <hpl_irq.h>
36#ifndef _UNIT_TEST_
37#include <utils.h>
38#endif
39#include <utils_assert.h>
40#include <peripheral_clk_config.h>
41
42#ifndef CONF_CPU_FREQUENCY
43#define CONF_CPU_FREQUENCY 1000000
44#endif
45
46#if CONF_CPU_FREQUENCY < 1000
47#define CPU_FREQ_POWER 3
48#elif CONF_CPU_FREQUENCY < 10000
49#define CPU_FREQ_POWER 4
50#elif CONF_CPU_FREQUENCY < 100000
51#define CPU_FREQ_POWER 5
52#elif CONF_CPU_FREQUENCY < 1000000
53#define CPU_FREQ_POWER 6
54#elif CONF_CPU_FREQUENCY < 10000000
55#define CPU_FREQ_POWER 7
56#elif CONF_CPU_FREQUENCY < 100000000
57#define CPU_FREQ_POWER 8
58#elif CONF_CPU_FREQUENCY < 1000000000
59#define CPU_FREQ_POWER 9
60#endif
61
62/**
63 * \brief The array of interrupt handlers
64 */
65struct _irq_descriptor *_irq_table[PERIPH_COUNT_IRQn];
66
67/**
68 * \brief Reset MCU
69 */
70void _reset_mcu(void)
71{
72 NVIC_SystemReset();
73}
74
75/**
76 * \brief Put MCU to sleep
77 */
78void _go_to_sleep(void)
79{
80 __DSB();
81 __WFI();
82}
83
84/**
85 * \brief Retrieve current IRQ number
86 */
87uint8_t _irq_get_current(void)
88{
89 return (uint8_t)__get_IPSR() - 16;
90}
91
92/**
93 * \brief Disable the given IRQ
94 */
95void _irq_disable(uint8_t n)
96{
97 NVIC_DisableIRQ((IRQn_Type)n);
98}
99
100/**
101 * \brief Set the given IRQ
102 */
103void _irq_set(uint8_t n)
104{
105 NVIC_SetPendingIRQ((IRQn_Type)n);
106}
107
108/**
109 * \brief Clear the given IRQ
110 */
111void _irq_clear(uint8_t n)
112{
113 NVIC_ClearPendingIRQ((IRQn_Type)n);
114}
115
116/**
117 * \brief Enable the given IRQ
118 */
119void _irq_enable(uint8_t n)
120{
121 NVIC_EnableIRQ((IRQn_Type)n);
122}
123
124/**
125 * \brief Register IRQ handler
126 */
127void _irq_register(const uint8_t n, struct _irq_descriptor *const irq)
128{
129 ASSERT(n < PERIPH_COUNT_IRQn);
130
131 _irq_table[n] = irq;
132}
133
134/**
135 * \brief Default interrupt handler for unused IRQs.
136 */
137void Default_Handler(void)
138{
139 while (1) {
140 }
141}
142
143/**
144 * \brief Retrieve the amount of cycles to delay for the given amount of us
145 */
146static inline uint32_t _get_cycles_for_us_internal(const uint16_t us, const uint32_t freq, const uint8_t power)
147{
148 switch (power) {
149 case 9:
150 return (us * (freq / 1000000) + 2) / 3;
151 case 8:
152 return (us * (freq / 100000) + 29) / 30;
153 case 7:
154 return (us * (freq / 10000) + 299) / 300;
155 case 6:
156 return (us * (freq / 1000) + 2999) / 3000;
157 case 5:
158 return (us * (freq / 100) + 29999) / 30000;
159 case 4:
160 return (us * (freq / 10) + 299999) / 300000;
161 default:
162 return (us * freq + 2999999) / 3000000;
163 }
164}
165
166/**
167 * \brief Retrieve the amount of cycles to delay for the given amount of us
168 */
169uint32_t _get_cycles_for_us(const uint16_t us)
170{
171 return _get_cycles_for_us_internal(us, CONF_CPU_FREQUENCY, CPU_FREQ_POWER);
172}
173
174/**
175 * \brief Retrieve the amount of cycles to delay for the given amount of ms
176 */
177static inline uint32_t _get_cycles_for_ms_internal(const uint16_t ms, const uint32_t freq, const uint8_t power)
178{
179 switch (power) {
180 case 9:
181 return (ms * (freq / 1000000) + 2) / 3 * 1000;
182 case 8:
183 return (ms * (freq / 100000) + 2) / 3 * 100;
184 case 7:
185 return (ms * (freq / 10000) + 2) / 3 * 10;
186 case 6:
187 return (ms * (freq / 1000) + 2) / 3;
188 case 5:
189 return (ms * (freq / 100) + 29) / 30;
190 case 4:
191 return (ms * (freq / 10) + 299) / 300;
192 default:
193 return (ms * (freq / 1) + 2999) / 3000;
194 }
195}
196
197/**
198 * \brief Retrieve the amount of cycles to delay for the given amount of ms
199 */
200uint32_t _get_cycles_for_ms(const uint16_t ms)
201{
202 return _get_cycles_for_ms_internal(ms, CONF_CPU_FREQUENCY, CPU_FREQ_POWER);
203}
204/**
205 * \brief Initialize delay functionality
206 */
207void _delay_init(void *const hw)
208{
209 (void)hw;
210}
211/**
212 * \brief Delay loop to delay n number of cycles
213 */
214void _delay_cycles(void *const hw, uint32_t cycles)
215{
216#ifndef _UNIT_TEST_
217 (void)hw;
218 (void)cycles;
Harald Welte9bb8bfe2019-05-17 16:10:00 +0200219#if defined(__GNUC__) && (__ARMCOMPILER_VERSION > 6000000) /* Keil MDK with ARM Compiler 6 */
220 __asm(".align 3 \n"
221 "__delay:\n"
222 "subs r1, r1, #1\n"
223 "bhi __delay\n");
224#elif defined __GNUC__
Kévin Redon69b92d92019-01-24 16:39:20 +0100225 __asm(".syntax unified\n"
Harald Welte9bb8bfe2019-05-17 16:10:00 +0200226 ".align 3 \n"
Kévin Redon69b92d92019-01-24 16:39:20 +0100227 "__delay:\n"
228 "subs r1, r1, #1\n"
229 "bhi __delay\n"
230 ".syntax divided");
231#elif defined __CC_ARM
232 __asm("__delay:\n"
233 "subs cycles, cycles, #1\n"
234 "bhi __delay\n");
235#elif defined __ICCARM__
236 __asm("__delay:\n"
237 "subs r1, r1, #1\n"
238 "bhi.n __delay\n");
239#endif
240#endif
241}