aboutsummaryrefslogtreecommitdiffstats
path: root/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h
blob: dadc58c508e7eb1d5e23e1d0ed373fc224efdb04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/**
 * @file    EXTIv1/stm32_exti.h
 * @brief   EXTI helper driver header.
 *
 * @addtogroup STM32_EXTI
 * @{
 */

#ifndef STM32_EXTI_H
#define STM32_EXTI_H

/*===========================================================================*/
/* Driver constants.                                                         */
/*===========================================================================*/

/**
 * @name    EXTI channel modes
 * @{
 */
#define EXTI_MODE_MASK              7U  /**< @brief Mode parameter mask.    */
#define EXTI_MODE_EDGES_MASK        3U  /**< @brief Edges field mask.       */
#define EXTI_MODE_DISABLED          0U  /**< @brief Channel disabled.       */
#define EXTI_MODE_RISING_EDGE       1U  /**< @brief Rising edge callback.   */
#define EXTI_MODE_FALLING_EDGE      2U  /**< @brief Falling edge callback.  */
#define EXTI_MODE_BOTH_EDGES        3U  /**< @brief Both edges callback.    */
#define EXTI_MODE_ACTION_MASK       4U  /**< @brief Action field mask.      */
#define EXTI_MODE_ACTION_INTERRUPT  0U  /**< @brief Interrupt mode.         */
#define EXTI_MODE_ACTION_EVENT      4U  /**< @brief Event mode.             */
/** @} */

/* Handling differences in ST headers.*/
#if !defined(STM32H7XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) &&   \
    !defined(STM32G0XX) && !defined(STM32G4XX)
#define EMR1    EMR
#define IMR1    IMR
#define PR1     PR
#define RTSR1   RTSR
#define FTSR1   FTSR
#endif

/*===========================================================================*/
/* Driver pre-compile time settings.                                         */
/*===========================================================================*/

/*===========================================================================*/
/* Derived constants and error checks.                                       */
/*===========================================================================*/

#if !defined(STM32_EXTI_NUM_LINES)
#error "STM32_EXTI_NUM_LINES not defined in registry"
#endif

/* Checking for presence of bank 2 registers. If the definition is not
   present in registry then it is inferred by the number of channels (which
   is not an always-good method, see G0.*/
#if !defined(STM32_EXTI_HAS_GROUP2)
#if STM32_EXTI_NUM_LINES <= 32
#define STM32_EXTI_HAS_GROUP2       FALSE
#else
#define STM32_EXTI_HAS_GROUP2       TRUE
#endif
#endif /* !defined(STM32_EXTI_HAS_GROUP2) */

/* Determines if EXTI has dedicated CR register or if it is done in
   SYSCFG (old style).*/
#if !defined(STM32_EXTI_HAS_CR)
#define STM32_EXTI_HAS_CR           FALSE
#endif

/* Determines if EXTI has dedicated separate registers for raising and
   falling edges.*/
#if !defined(STM32_EXTI_SEPARATE_RF)
#define STM32_EXTI_SEPARATE_RF      FALSE
#endif

#if (STM32_EXTI_NUM_LINES < 0) || (STM32_EXTI_NUM_LINES > 63)
#error "invalid STM32_EXTI_NUM_LINES value"
#endif

#if !defined(STM32_EXTI_IMR1_MASK)
#error "STM32_EXTI_IMR1_MASK not defined in registry"
#endif

#if STM32_EXTI_NUM_LINES > 32
#if !defined(STM32_EXTI_IMR2_MASK)
#error "STM32_EXTI_IMR2_MASK not defined in registry"
#endif
#endif

/*===========================================================================*/
/* Driver data structures and types.                                         */
/*===========================================================================*/

/**
 * @brief   Type of an EXTI line identifier.
 */
typedef uint32_t extiline_t;

/**
 * @brief   Type of an EXTI line mode.
 */
typedef uint32_t extimode_t;

/*===========================================================================*/
/* Driver macros.                                                            */
/*===========================================================================*/

/**
 * @brief   From group 1 line number to mask.
 *
 * @param[in] line      line number in range 0..31
 */
#define EXTI_MASK1(line) (uint32_t)(1U << (line))

/**
 * @brief   From group 2 line number to mask.
 *
 * @param[in] line      line number in range 32..63
 */
#define EXTI_MASK2(line) (uint32_t)(1U << ((line) - 32U))

/**
 * @brief   STM32 EXTI group 1 IRQ status clearing.
 *
 * @param[in] mask      mask of group 1 lines to be initialized
 *
 * @special
 */
#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
#define extiClearGroup1(mask) do {                                          \
  osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines");      \
  EXTI->PR1 = (uint32_t)(mask);                                             \
} while (false)
#else
#define extiClearGroup1(mask) do {                                          \
  osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines");      \
  EXTI->RPR1 = (uint32_t)(mask);                                            \
  EXTI->FPR1 = (uint32_t)(mask);                                            \
} while (false)
#endif

#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
/**
 * @brief   STM32 EXTI group 2 IRQ status clearing.
 *
 * @param[in] mask      mask of group 2 lines to be initialized
 *
 * @special
 */
#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
#define extiClearGroup2(mask) do {                                          \
  osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines");      \
  EXTI->PR2 = (uint32_t)(mask);                                             \
} while (false)
#else
#define extiClearGroup2(mask) do {                                          \
  osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines");      \
  EXTI->RPR2 = (uint32_t)(mask);                                            \
  EXTI->FPR2 = (uint32_t)(mask);                                            \
} while (false)
#endif
#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */

/**
 * @brief   Serves an EXTI interrupt in group 1.
 *
 * @param[in] mask      mask of lines to be cleared
 * @param[out] out      mask of lines needing processing
 *
 * @special
 */
#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
#define extiGetAndClearGroup1(mask, out) do {                               \
  uint32_t pr1;                                                             \
                                                                            \
  pr1 = EXTI->PR1 & (mask);                                                 \
  (out) = pr1;                                                              \
  EXTI->PR1 = pr1;                                                          \
} while (false)
#else
#define extiGetAndClearGroup1(mask, out) do {                               \
  uint32_t rpr1, fpr1;                                                      \
                                                                            \
  rpr1 = EXTI->RPR1 & (mask);                                               \
  fpr1 = EXTI->FPR1 & (mask);                                               \
  (out) = rpr1 | fpr1;                                                      \
  EXTI->RPR1 = rpr1;                                                        \
  EXTI->FPR1 = fpr1;                                                        \
} while (false)
#endif

#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
/**
 * @brief   Serves an EXTI interrupt in group 2.
 *
 * @param[in] mask      mask of lines to be cleared
 * @param[out] out      mask of lines needing processing
 *
 * @special
 */
#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
#define extiGetAndClearGroup2(mask, out) do {                               \
  uint32_t pr2;                                                             \
                                                                            \
  pr2 = EXTI->PR2 & (mask);                                                 \
  (out) = pr2;                                                              \
  EXTI->PR2 = pr2;                                                          \
} while (false)
#else
#define extiGetAndClearGroup2(mask, out) do {                               \
  uint32_t rpr2, fpr2;                                                      \
                                                                            \
  rpr2 = EXTI->RPR2 & (mask);                                               \
  fpr2 = EXTI->FPR2 & (mask);                                               \
  (out) = rpr2 | fpr2;                                                      \
  EXTI->RPR2 = rpr2;                                                        \
  EXTI->FPR2 = fpr2;                                                        \
} while (false)
#endif
#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */

/*===========================================================================*/
/* External declarations.                                                    */
/*===========================================================================*/

#ifdef __cplusplus
extern "C" {
#endif
  void extiEnableGroup1(uint32_t mask, extimode_t mode);
#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
  void extiEnableGroup2(uint32_t mask, extimode_t mode);
#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */
  void extiEnableLine(extiline_t line, extimode_t mode);
  void extiClearLine(extiline_t line);
  #ifdef __cplusplus
}
#endif

#endif /* STM32_EXTI_H */

/** @} */