1 /**
2 * \file
3 *
4 * \brief Core related functionality implementation.
5 *
6 * Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43
44 #include <hpl_core.h>
45 #include <hpl_irq.h>
46 #include <hpl_reset.h>
47 #include <hpl_sleep.h>
48 #include <hpl_delay.h>
49 #ifndef _UNIT_TEST_
50 #include <utils.h>
51 #endif
52 #include <utils_assert.h>
53 #include <peripheral_clk_config.h>
54
55 #ifndef CONF_CPU_FREQUENCY
56 #define CONF_CPU_FREQUENCY 1000000
57 #endif
58
59 #if CONF_CPU_FREQUENCY < 1000
60 #define CPU_FREQ_POWER 3
61 #elif CONF_CPU_FREQUENCY < 10000
62 #define CPU_FREQ_POWER 4
63 #elif CONF_CPU_FREQUENCY < 100000
64 #define CPU_FREQ_POWER 5
65 #elif CONF_CPU_FREQUENCY < 1000000
66 #define CPU_FREQ_POWER 6
67 #elif CONF_CPU_FREQUENCY < 10000000
68 #define CPU_FREQ_POWER 7
69 #elif CONF_CPU_FREQUENCY < 100000000
70 #define CPU_FREQ_POWER 8
71 #endif
72
73 /**
74 * \brief The array of interrupt handlers
75 */
76 struct _irq_descriptor *_irq_table[PERIPH_COUNT_IRQn];
77
78 /**
79 * \brief Reset MCU
80 */
_reset_mcu(void)81 void _reset_mcu(void)
82 {
83 NVIC_SystemReset();
84 }
85
86 /**
87 * \brief Put MCU to sleep
88 */
_go_to_sleep(void)89 void _go_to_sleep(void)
90 {
91 __DSB();
92 __WFI();
93 }
94
95 /**
96 * \brief Retrieve current IRQ number
97 */
_irq_get_current(void)98 uint8_t _irq_get_current(void)
99 {
100 return (uint8_t)__get_IPSR() - 16;
101 }
102
103 /**
104 * \brief Disable the given IRQ
105 */
_irq_disable(uint8_t n)106 void _irq_disable(uint8_t n)
107 {
108 NVIC_DisableIRQ((IRQn_Type)n);
109 }
110
111 /**
112 * \brief Set the given IRQ
113 */
_irq_set(uint8_t n)114 void _irq_set(uint8_t n)
115 {
116 NVIC_SetPendingIRQ((IRQn_Type)n);
117 }
118
119 /**
120 * \brief Clear the given IRQ
121 */
_irq_clear(uint8_t n)122 void _irq_clear(uint8_t n)
123 {
124 NVIC_ClearPendingIRQ((IRQn_Type)n);
125 }
126
127 /**
128 * \brief Enable the given IRQ
129 */
_irq_enable(uint8_t n)130 void _irq_enable(uint8_t n)
131 {
132 NVIC_EnableIRQ((IRQn_Type)n);
133 }
134
135 /**
136 * \brief Register IRQ handler
137 */
_irq_register(const uint8_t n,struct _irq_descriptor * const irq)138 void _irq_register(const uint8_t n, struct _irq_descriptor *const irq)
139 {
140 ASSERT(n < PERIPH_COUNT_IRQn);
141
142 _irq_table[n] = irq;
143 }
144
145 /**
146 * \brief Default interrupt handler for unused IRQs.
147 */
Default_Handler(void)148 void Default_Handler(void)
149 {
150 while (1) {
151 }
152 }
153
154 /**
155 * \brief Retrieve the amount of cycles to delay for the given amount of us
156 */
_get_cycles_for_us_internal(const uint16_t us,const uint32_t freq,const uint8_t power)157 static inline uint32_t _get_cycles_for_us_internal(const uint16_t us, const uint32_t freq, const uint8_t power)
158 {
159 switch (power) {
160 case 8:
161 return (us * (freq / 100000) - 1) / 10 + 1;
162 case 7:
163 return (us * (freq / 10000) - 1) / 100 + 1;
164 case 6:
165 return (us * (freq / 1000) - 1) / 1000 + 1;
166 case 5:
167 return (us * (freq / 100) - 1) / 10000 + 1;
168 case 4:
169 return (us * (freq / 10) - 1) / 100000 + 1;
170 default:
171 return (us * freq - 1) / 1000000 + 1;
172 }
173 }
174
175 /**
176 * \brief Retrieve the amount of cycles to delay for the given amount of us
177 */
_get_cycles_for_us(const uint16_t us)178 uint32_t _get_cycles_for_us(const uint16_t us)
179 {
180 return _get_cycles_for_us_internal(us, CONF_CPU_FREQUENCY, CPU_FREQ_POWER);
181 }
182
183 /**
184 * \brief Retrieve the amount of cycles to delay for the given amount of ms
185 */
_get_cycles_for_ms_internal(const uint16_t ms,const uint32_t freq,const uint8_t power)186 static inline uint32_t _get_cycles_for_ms_internal(const uint16_t ms, const uint32_t freq, const uint8_t power)
187 {
188 switch (power) {
189 case 8:
190 return (ms * (freq / 100000)) * 100;
191 case 7:
192 return (ms * (freq / 10000)) * 10;
193 case 6:
194 return (ms * (freq / 1000));
195 case 5:
196 return (ms * (freq / 100) - 1) / 10 + 1;
197 case 4:
198 return (ms * (freq / 10) - 1) / 100 + 1;
199 default:
200 return (ms * freq - 1) / 1000 + 1;
201 }
202 }
203
204 /**
205 * \brief Retrieve the amount of cycles to delay for the given amount of ms
206 */
_get_cycles_for_ms(const uint16_t ms)207 uint32_t _get_cycles_for_ms(const uint16_t ms)
208 {
209 return _get_cycles_for_ms_internal(ms, CONF_CPU_FREQUENCY, CPU_FREQ_POWER);
210 }
211