]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/sercom/sercom_interrupt.c
Complete SAMD20 demo - still needs tidy up.
[freertos] / FreeRTOS / Demo / CORTEX_M0+_Atmel_SAMD20_XPlained / RTOSDemo / src / ASF / sam0 / drivers / sercom / sercom_interrupt.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief SAM D20 Serial Peripheral Interface Driver\r
5  *\r
6  * Copyright (C) 2012-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 "sercom_interrupt.h"\r
44 \r
45 void *_sercom_instances[SERCOM_INST_NUM];\r
46 \r
47 /** Save status of initialized handlers. */\r
48 static bool _handler_table_initialized = false;\r
49 \r
50 /** Void pointers for saving device instance structures. */\r
51 static void (*_sercom_interrupt_handlers[SERCOM_INST_NUM])(const uint8_t instance);\r
52 \r
53 /**\r
54  * \internal\r
55  * Default interrupt handler.\r
56  *\r
57  * \param[in] instance SERCOM instance used.\r
58  */\r
59 static void _sercom_default_handler(\r
60                 const uint8_t instance)\r
61 {\r
62         ( void ) instance;\r
63         Assert(false);\r
64 }\r
65 \r
66 /**\r
67  * \internal\r
68  * Find index of given instance.\r
69  *\r
70  * \param[in] sercom_instance  Instance pointer.\r
71  *\r
72  * \return Index of given instance.\r
73  */\r
74 uint8_t _sercom_get_sercom_inst_index(\r
75                 Sercom *const sercom_instance)\r
76 {\r
77         /* Save all available SERCOM instances for compare. */\r
78         Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;\r
79 \r
80         /* Find index for sercom instance. */\r
81         for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {\r
82                 if ((uintptr_t)sercom_instance == (uintptr_t)sercom_instances[i]) {\r
83                         return i;\r
84                 }\r
85         }\r
86 \r
87         /* Invalid data given. */\r
88         Assert(false);\r
89         return 0;\r
90 }\r
91 \r
92 /**\r
93  * \internal\r
94  * Saves the given callback handler.\r
95  *\r
96  * \param[in]  instance           Instance index.\r
97  * \param[in]  interrupt_handler  Pointer to instance callback handler.\r
98  */\r
99 void _sercom_set_handler(\r
100                 const uint8_t instance,\r
101                 const sercom_handler_t interrupt_handler)\r
102 {\r
103         /* Initialize handlers with default handler and device instances with 0. */\r
104         if (_handler_table_initialized == false) {\r
105                 for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {\r
106                         _sercom_interrupt_handlers[i] = &_sercom_default_handler;\r
107                         _sercom_instances[i] = NULL;\r
108                 }\r
109 \r
110                 _handler_table_initialized = true;\r
111         }\r
112 \r
113         /* Save interrupt handler. */\r
114         _sercom_interrupt_handlers[instance] = interrupt_handler;\r
115 }\r
116 \r
117 \r
118 /** \internal\r
119  * Converts a given SERCOM index to its interrupt vector index.\r
120  */\r
121 #define _SERCOM_INTERRUPT_VECT_NUM(n, unused) \\r
122                 SYSTEM_INTERRUPT_MODULE_SERCOM##n,\r
123 \r
124 /** \internal\r
125  * Generates a SERCOM interrupt handler function for a given SERCOM index.\r
126  */\r
127 #define _SERCOM_INTERRUPT_HANDLER(n, unused) \\r
128                 void SERCOM##n##_Handler(void) \\r
129                 { \\r
130                         _sercom_interrupt_handlers[n](n); \\r
131                 }\r
132 \r
133 /**\r
134  * \internal\r
135  * Returns the system interrupt vector.\r
136  *\r
137  * \param[in]  sercom_instance  Instance pointer\r
138  *\r
139  * \return Enum of system interrupt vector\r
140  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM0\r
141  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM1\r
142  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM2\r
143  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM3\r
144  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM4\r
145  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM5\r
146  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM6\r
147  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM7\r
148  */\r
149 enum system_interrupt_vector _sercom_get_interrupt_vector(\r
150                 Sercom *const sercom_instance)\r
151 {\r
152         const uint8_t sercom_int_vectors[SERCOM_INST_NUM] =\r
153                 {\r
154                         MREPEAT(SERCOM_INST_NUM, _SERCOM_INTERRUPT_VECT_NUM, ~)\r
155                 };\r
156 \r
157         /* Retrieve the index of the SERCOM being requested */\r
158         uint8_t instance_index = _sercom_get_sercom_inst_index(sercom_instance);\r
159 \r
160         /* Get the vector number from the lookup table for the requested SERCOM */\r
161         return (enum system_interrupt_vector)sercom_int_vectors[instance_index];\r
162 }\r
163 \r
164 /** Auto-generate a set of interrupt handlers for each SERCOM in the device */\r
165 MREPEAT(SERCOM_INST_NUM, _SERCOM_INTERRUPT_HANDLER, ~)\r