]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/interrupt/system_interrupt.c
Starting point for the SAMD20 demo.
[freertos] / FreeRTOS / Demo / CORTEX_M0+_Atmel_SAMD20_XPlained / RTOSDemo / src / ASF / sam0 / drivers / system / interrupt / system_interrupt.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief SAM D20 System Interrupt Driver\r
5  *\r
6  * Copyright (C) 2013 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 #include "system_interrupt.h"\r
44 \r
45 /**\r
46  * \brief Check if a interrupt line is pending\r
47  *\r
48  * Checks if the requested interrupt vector is pending.\r
49  *\r
50  * \param[in] vector  Interrupt vector number to check\r
51  *\r
52  * \returns A boolean identifying if the requested interrupt vector is pending.\r
53  *\r
54  * \retval true   Specified interrupt vector is pending\r
55  * \retval false  Specified interrupt vector is not pending\r
56  *\r
57  */\r
58 bool system_interrupt_is_pending(\r
59                 const enum system_interrupt_vector vector)\r
60 {\r
61         bool result;\r
62 \r
63         if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) {\r
64                 result = ((NVIC->ISPR[0] & (1 << vector)) != 0);\r
65         } else if (vector == SYSTEM_INTERRUPT_SYSTICK) {\r
66                 result = ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0);\r
67         } else {\r
68                 Assert(false);\r
69                 result = false;\r
70         }\r
71 \r
72         return result;\r
73 }\r
74 \r
75 /**\r
76  * \brief Set a interrupt vector as pending\r
77  *\r
78  * Set the requested interrupt vector as pending (i.e issues a software\r
79  * interrupt request for the specified vector). The software handler will be\r
80  * handled (if enabled) in a priority order based on vector number and\r
81  * configured priority settings.\r
82  *\r
83  * \param[in] vector  Interrupt vector number which is set as pending\r
84  *\r
85  * \returns Status code identifying if the vector was successfully set as\r
86  *          pending.\r
87  *\r
88  * \retval STATUS_OK           If no error was detected\r
89  * \retval STATUS_INVALID_ARG  If an unsupported interrupt vector number was given\r
90  */\r
91 enum status_code system_interrupt_set_pending(\r
92                 const enum system_interrupt_vector vector)\r
93 {\r
94         enum status_code status = STATUS_OK;\r
95 \r
96         if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) {\r
97                 NVIC->ISPR[0] = (1 << vector);\r
98         } else if (vector == SYSTEM_INTERRUPT_NON_MASKABLE) {\r
99                 /* Note: Because NMI has highest priority it will be executed\r
100                  * immediately after it has been set pending */\r
101                 SCB->ICSR = SCB_ICSR_NMIPENDSET_Msk;\r
102         } else if (vector == SYSTEM_INTERRUPT_SYSTICK) {\r
103                 SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;\r
104         } else {\r
105                 /* The user want to set something unsupported as pending */\r
106                 Assert(false);\r
107                 status = STATUS_ERR_INVALID_ARG;\r
108         }\r
109 \r
110         return status;\r
111 }\r
112 \r
113 /**\r
114  * \brief Clear pending interrupt vector\r
115  *\r
116  * Clear a pending interrupt vector, so the software handler is not executed.\r
117  *\r
118  * \param[in] vector  Interrupt vector number to clear\r
119  *\r
120  * \returns A status code identifying if the interrupt pending state was\r
121  *          successfully cleared.\r
122  *\r
123  * \retval STATUS_OK           If no error was detected\r
124  * \retval STATUS_INVALID_ARG  If an unsupported interrupt vector number was given\r
125  */\r
126 enum status_code system_interrupt_clear_pending(\r
127                 const enum system_interrupt_vector vector)\r
128 {\r
129         enum status_code status = STATUS_OK;\r
130 \r
131         if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) {\r
132                 NVIC->ICPR[0] = (1 << vector);\r
133         } else if (vector == SYSTEM_INTERRUPT_NON_MASKABLE) {\r
134                 /* Note: Clearing of NMI pending interrupts does not make sense and is\r
135                  * not supported by the device, as it has the highest priority and will\r
136                  * always be executed at the moment it is set */\r
137                 return STATUS_ERR_INVALID_ARG;\r
138         } else if (vector == SYSTEM_INTERRUPT_SYSTICK) {\r
139                 SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk;\r
140         } else {\r
141                 Assert(false);\r
142                 status = STATUS_ERR_INVALID_ARG;\r
143         }\r
144 \r
145         return status;\r
146 }\r
147 \r
148 /**\r
149  * \brief Set interrupt vector priority level\r
150  *\r
151  * Set the priority level of an external interrupt or exception.\r
152  *\r
153  * \param[in] vector          Interrupt vector to change\r
154  * \param[in] priority_level  New vector priority level to set\r
155  *\r
156  * \returns Status code indicating if the priority level of the interrupt was\r
157  *          successfully set.\r
158  *\r
159  * \retval STATUS_OK           If no error was detected\r
160  * \retval STATUS_INVALID_ARG  If an unsupported interrupt vector number was given\r
161  */\r
162 enum status_code system_interrupt_set_priority(\r
163                 const enum system_interrupt_vector vector,\r
164                 const enum system_interrupt_priority_level priority_level)\r
165 {\r
166         enum status_code status = STATUS_OK;\r
167 \r
168         if (vector >= _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START) {\r
169                 uint8_t register_num = vector / 4;\r
170                 uint8_t priority_pos = ((vector % 4) * 8) + (8 - __NVIC_PRIO_BITS);\r
171 \r
172                 NVIC->IP[register_num] = (priority_level << priority_pos);\r
173         } else if (vector == SYSTEM_INTERRUPT_SYSTICK) {\r
174                 SCB->SHP[1] = (priority_level << _SYSTEM_INTERRUPT_SYSTICK_PRI_POS);\r
175         } else {\r
176                 Assert(false);\r
177                 status = STATUS_ERR_INVALID_ARG;\r
178         }\r
179 \r
180         return status;\r
181 }\r
182 \r
183 /**\r
184  * \brief Get interrupt vector priority level\r
185  *\r
186  * Retrieves the priority level of the requested external interrupt or exception.\r
187  *\r
188  * \param[in] vector  Interrupt vector of which the priority level will be read\r
189  *\r
190  * \return Currently configured interrupt priority level of the given interrupt\r
191  *         vector.\r
192  */\r
193 enum system_interrupt_priority_level system_interrupt_get_priority(\r
194                 const enum system_interrupt_vector vector)\r
195 {\r
196         uint8_t register_num = vector / 4;\r
197         uint8_t priority_pos = ((vector % 4) * 8) + (8 - __NVIC_PRIO_BITS);\r
198 \r
199         enum system_interrupt_priority_level priority = SYSTEM_INTERRUPT_PRIORITY_LEVEL_0;\r
200 \r
201         if (vector >= 0) {\r
202                 priority = (enum system_interrupt_priority_level)\r
203                                 ((NVIC->IP[register_num] >> priority_pos) & _SYSTEM_INTERRUPT_PRIORITY_MASK);\r
204         } else if (vector == SYSTEM_INTERRUPT_SYSTICK) {\r
205                 priority = (enum system_interrupt_priority_level)\r
206                                 ((SCB->SHP[1] >> _SYSTEM_INTERRUPT_SYSTICK_PRI_POS) & _SYSTEM_INTERRUPT_PRIORITY_MASK);\r
207         }\r
208 \r
209         return priority;\r
210 }\r
211 \r