]> git.sur5r.net Git - freertos/blob
042e5b30ddfc6757b233f287ca5e65b98afe2ce0
[freertos] /
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         Assert(false);\r
63 }\r
64 \r
65 /**\r
66  * \internal\r
67  * Find index of given instance.\r
68  *\r
69  * \param[in] sercom_instance  Instance pointer.\r
70  *\r
71  * \return Index of given instance.\r
72  */\r
73 uint8_t _sercom_get_sercom_inst_index(\r
74                 Sercom *const sercom_instance)\r
75 {\r
76         /* Save all available SERCOM instances for compare. */\r
77         Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;\r
78 \r
79         /* Find index for sercom instance. */\r
80         for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {\r
81                 if ((uintptr_t)sercom_instance == (uintptr_t)sercom_instances[i]) {\r
82                         return i;\r
83                 }\r
84         }\r
85 \r
86         /* Invalid data given. */\r
87         Assert(false);\r
88         return 0;\r
89 }\r
90 \r
91 /**\r
92  * \internal\r
93  * Saves the given callback handler.\r
94  *\r
95  * \param[in]  instance           Instance index.\r
96  * \param[in]  interrupt_handler  Pointer to instance callback handler.\r
97  */\r
98 void _sercom_set_handler(\r
99                 const uint8_t instance,\r
100                 const sercom_handler_t interrupt_handler)\r
101 {\r
102         /* Initialize handlers with default handler and device instances with 0. */\r
103         if (_handler_table_initialized == false) {\r
104                 for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {\r
105                         _sercom_interrupt_handlers[i] = &_sercom_default_handler;\r
106                         _sercom_instances[i] = NULL;\r
107                 }\r
108 \r
109                 _handler_table_initialized = true;\r
110         }\r
111 \r
112         /* Save interrupt handler. */\r
113         _sercom_interrupt_handlers[instance] = interrupt_handler;\r
114 }\r
115 \r
116 \r
117 /** \internal\r
118  * Converts a given SERCOM index to its interrupt vector index.\r
119  */\r
120 #define _SERCOM_INTERRUPT_VECT_NUM(n, unused) \\r
121                 SYSTEM_INTERRUPT_MODULE_SERCOM##n,\r
122 \r
123 /** \internal\r
124  * Generates a SERCOM interrupt handler function for a given SERCOM index.\r
125  */\r
126 #define _SERCOM_INTERRUPT_HANDLER(n, unused) \\r
127                 void SERCOM##n##_Handler(void) \\r
128                 { \\r
129                         _sercom_interrupt_handlers[n](n); \\r
130                 }\r
131 \r
132 /**\r
133  * \internal\r
134  * Returns the system interrupt vector.\r
135  *\r
136  * \param[in]  sercom_instance  Instance pointer\r
137  *\r
138  * \return Enum of system interrupt vector\r
139  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM0\r
140  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM1\r
141  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM2\r
142  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM3\r
143  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM4\r
144  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM5\r
145  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM6\r
146  * \retval SYSTEM_INTERRUPT_MODULE_SERCOM7\r
147  */\r
148 enum system_interrupt_vector _sercom_get_interrupt_vector(\r
149                 Sercom *const sercom_instance)\r
150 {\r
151         const uint8_t sercom_int_vectors[SERCOM_INST_NUM] =\r
152                 {\r
153                         MREPEAT(SERCOM_INST_NUM, _SERCOM_INTERRUPT_VECT_NUM, ~)\r
154                 };\r
155 \r
156         /* Retrieve the index of the SERCOM being requested */\r
157         uint8_t instance_index = _sercom_get_sercom_inst_index(sercom_instance);\r
158 \r
159         /* Get the vector number from the lookup table for the requested SERCOM */\r
160         return (enum system_interrupt_vector)sercom_int_vectors[instance_index];\r
161 }\r
162 \r
163 /** Auto-generate a set of interrupt handlers for each SERCOM in the device */\r
164 MREPEAT(SERCOM_INST_NUM, _SERCOM_INTERRUPT_HANDLER, ~)\r