1 /**
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 #include <hpl_reset.h>
37 #include <hpl_sleep.h>
38 #include <hpl_delay.h>
39 #ifndef _UNIT_TEST_
40 #include <utils.h>
41 #endif
42 #include <utils_assert.h>
43 #include <peripheral_clk_config.h>
44 
45 #ifndef CONF_HCLK_FREQUENCY
46 #define CONF_HCLK_FREQUENCY 300000000
47 #endif
48 
49 #if CONF_HCLK_FREQUENCY < 1000
50 #define HCLK_FREQ_POWER 3
51 #elif CONF_HCLK_FREQUENCY < 10000
52 #define HCLK_FREQ_POWER 4
53 #elif CONF_HCLK_FREQUENCY < 100000
54 #define HCLK_FREQ_POWER 5
55 #elif CONF_HCLK_FREQUENCY < 1000000
56 #define HCLK_FREQ_POWER 6
57 #elif CONF_HCLK_FREQUENCY < 10000000
58 #define HCLK_FREQ_POWER 7
59 #elif CONF_HCLK_FREQUENCY < 100000000
60 #define HCLK_FREQ_POWER 8
61 #elif CONF_HCLK_FREQUENCY < 1000000000
62 #define HCLK_FREQ_POWER 9
63 #endif
64 
65 /**
66  * \brief The array of interrupt handlers
67  */
68 struct _irq_descriptor *_irq_table[PERIPH_COUNT_IRQn];
69 
70 /**
71  * \brief Reset MCU
72  */
_reset_mcu(void)73 void _reset_mcu(void)
74 {
75 	NVIC_SystemReset();
76 }
77 
78 /**
79  * \brief Retrieve the reset reason
80  */
_get_reset_reason(void)81 enum reset_reason _get_reset_reason(void)
82 {
83 	return (enum reset_reason)hri_rstc_read_SR_RSTTYP_bf(RSTC);
84 }
85 
86 /**
87  * \brief Retrieve current IRQ number
88  */
_irq_get_current(void)89 uint8_t _irq_get_current(void)
90 {
91 	return (uint8_t)__get_IPSR() - 16;
92 }
93 
94 /**
95  * \brief Disable the given IRQ
96  */
_irq_disable(uint8_t n)97 void _irq_disable(uint8_t n)
98 {
99 	NVIC_DisableIRQ((IRQn_Type)n);
100 }
101 
102 /**
103  * \brief Set the given IRQ
104  */
_irq_set(uint8_t n)105 void _irq_set(uint8_t n)
106 {
107 	NVIC_SetPendingIRQ((IRQn_Type)n);
108 }
109 
110 /**
111  * \brief Clear the given IRQ
112  */
_irq_clear(uint8_t n)113 void _irq_clear(uint8_t n)
114 {
115 	NVIC_ClearPendingIRQ((IRQn_Type)n);
116 }
117 
118 /**
119  * \brief Enable the given IRQ
120  */
_irq_enable(uint8_t n)121 void _irq_enable(uint8_t n)
122 {
123 	NVIC_EnableIRQ((IRQn_Type)n);
124 }
125 
126 /**
127  * \brief Register IRQ handler
128  */
_irq_register(const uint8_t n,struct _irq_descriptor * const irq)129 void _irq_register(const uint8_t n, struct _irq_descriptor *const irq)
130 {
131 	ASSERT(n < PERIPH_COUNT_IRQn);
132 
133 	_irq_table[n] = irq;
134 }
135 
136 /**
137  * \brief Default interrupt handler for unused IRQs.
138  */
Default_Handler(void)139 void Default_Handler(void)
140 {
141 	while (1) {
142 	}
143 }
144 
145 /**
146  * \brief Retrieve the amount of cycles to delay for the given amount of us
147  */
_get_cycles_for_us_internal(const uint16_t us,const uint32_t freq,const uint8_t power)148 static inline uint32_t _get_cycles_for_us_internal(const uint16_t us, const uint32_t freq, const uint8_t power)
149 {
150 	switch (power) {
151 	case 9:
152 		return (us * (freq / 1000000));
153 	case 8:
154 		return (us * (freq / 100000) + 9) / 10;
155 	case 7:
156 		return (us * (freq / 10000) + 99) / 100;
157 	case 6:
158 		return (us * (freq / 1000) + 999) / 1000;
159 	case 5:
160 		return (us * (freq / 100) + 9999) / 10000;
161 	default:
162 		return (us * freq + 999999) / 1000000;
163 	}
164 }
165 
166 /**
167  * \brief Retrieve the amount of cycles to delay for the given amount of us
168  */
_get_cycles_for_us(const uint16_t us)169 uint32_t _get_cycles_for_us(const uint16_t us)
170 {
171 	return _get_cycles_for_us_internal(us, CONF_HCLK_FREQUENCY, HCLK_FREQ_POWER);
172 }
173 
174 /**
175  * \brief Retrieve the amount of cycles to delay for the given amount of ms
176  */
_get_cycles_for_ms_internal(const uint16_t ms,const uint32_t freq,const uint8_t power)177 static 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) * 1000);
182 	case 8:
183 		return (ms * (freq / 100000) * 100);
184 	case 7:
185 		return (ms * (freq / 10000) * 10);
186 	case 6:
187 		return (ms * (freq / 1000));
188 	case 5:
189 		return (ms * (freq / 100) + 9) / 10;
190 	default:
191 		return (ms * (freq / 1) + 999) / 1000;
192 	}
193 }
194 
195 /**
196  * \brief Retrieve the amount of cycles to delay for the given amount of ms
197  */
_get_cycles_for_ms(const uint16_t ms)198 uint32_t _get_cycles_for_ms(const uint16_t ms)
199 {
200 	return _get_cycles_for_ms_internal(ms, CONF_HCLK_FREQUENCY, HCLK_FREQ_POWER);
201 }
202 /**
203  * \brief Initialize delay functionality
204  */
_delay_init(void * const hw)205 void _delay_init(void *const hw)
206 {
207 	(void)hw;
208 }
209 
210 /**
211  * \brief Delay loop to delay n number of cycles
212  *
213  * \note In theory, a single loop runs take 2 cycles or more. But we find it
214  * really only needs 1 cycle through debugging.
215  *
216  */
_delay_cycles(void * const hw,uint32_t cycles)217 void _delay_cycles(void *const hw, uint32_t cycles)
218 {
219 #ifndef _UNIT_TEST_
220 	(void)hw;
221 	(void)cycles;
222 #if defined __GNUC__
223 	__asm("__delay:\n"
224 	      "subs r1, r1, #1\n"
225 	      "bhi __delay\n");
226 #elif defined __CC_ARM
227 	__asm("__delay:\n"
228 	      "subs cycles, cycles, #1\n"
229 	      "bhi __delay\n");
230 #elif defined __ICCARM__
231 	__asm("__delay:\n"
232 	      "subs r1, r1, #1\n"
233 	      "bhi __delay\n");
234 #endif
235 #endif
236 }
237