├── LICENSE
├── README.md
├── drivers.mk
├── drivers_conf_example.h
├── inc
├── dac_driver.h
├── drivers.h
├── eeprom_driver.h
├── eicu_driver.h
├── iuart_driver.h
├── iwdg_driver.h
└── timcap_driver.h
├── src
├── 24xx_driver.c
├── 25xx_driver.c
├── dac_driver.c
├── drivers.c
├── eeprom_driver.c
├── eicu_driver.c
├── iuart_driver.c
├── iwdg_driver.c
└── timcap_driver.c
└── stm32
├── dac_driver_lld.c
├── dac_driver_lld.h
├── eicu_driver_lld.c
├── eicu_driver_lld.h
├── extra_rcc.h
├── extra_registry.h
├── iuart_driver_lld.c
├── iuart_driver_lld.h
├── iwdg_driver_lld.c
├── iwdg_driver_lld.h
├── timcap_driver_lld.c
└── timcap_driver_lld.h
/README.md:
--------------------------------------------------------------------------------
1 | ChibiOS-Drivers
2 | ===============
3 |
4 | Collection of drivers for ChibiOS' HAL.
5 |
6 | **This repo is being deprecated. Please consider using ChibiOS-Contrib instead.**
7 |
8 | #### Using
9 | * Clone this repo in the same directory as ChibiOS-RT. (not inside)
10 | * Include the drivers.mk file into your project's Makefile ( include $(CHIBIOS)/../ChibiOS-Drivers/drivers.mk )
11 | * Add the required files lists to the CSRC and CINC lists ( Usually $(STM32DRIVERSRC) and $(STM32DRIVERINC) )
12 | * Include the drivers.h file in main.c, and anywhere else needed
13 | * Add a driversInit() call just below halInit()
14 | * include drivers_conf.h at the top of mcuconf.h
15 | * You might have to tweak extra_registry.h and drivers_conf.h depending on your hardware
16 |
17 | Everything else works like using a standard driver.
18 | So far only drivers for STM32.
19 |
20 | #### Drivers list
21 | * Digital Analog Converter (dac), with optional DMA transfers
22 | * Timer input capture (timcap), works on all channels simultaneously
23 | * Independent watchdog timer (iwdg)
24 | * Interrupt based UART (iuart), in case you run out of DMA channels
25 | * Enhanced input capture unit (eicu).
26 | * Eeprom via SPI and/or I2C.
27 |
--------------------------------------------------------------------------------
/drivers.mk:
--------------------------------------------------------------------------------
1 |
2 | DRIVERPATH = $(CHIBIOS)/../ChibiOS-Drivers
3 |
4 | DRIVERSRC = $(DRIVERPATH)/src/drivers.c
5 | DRIVERSRC += $(DRIVERPATH)/src/timcap_driver.c
6 | DRIVERSRC += $(DRIVERPATH)/src/dac_driver.c
7 | DRIVERSRC += $(DRIVERPATH)/src/iwdg_driver.c
8 | DRIVERSRC += $(DRIVERPATH)/src/iuart_driver.c
9 | DRIVERSRC += $(DRIVERPATH)/src/eicu_driver.c
10 | DRIVERSRC += $(DRIVERPATH)/src/eeprom_driver.c
11 | DRIVERSRC += $(DRIVERPATH)/src/24xx_driver.c
12 | DRIVERSRC += $(DRIVERPATH)/src/25xx_driver.c
13 |
14 | DRIVERINC += $(DRIVERPATH)/inc
15 |
16 | STM32DRIVERSRC = $(DRIVERSRC)
17 | STM32DRIVERSRC += $(DRIVERPATH)/stm32/iwdg_driver_lld.c
18 | STM32DRIVERSRC += $(DRIVERPATH)/stm32/timcap_driver_lld.c
19 | STM32DRIVERSRC += $(DRIVERPATH)/stm32/dac_driver_lld.c
20 | STM32DRIVERSRC += $(DRIVERPATH)/stm32/iuart_driver_lld.c
21 | STM32DRIVERSRC += $(DRIVERPATH)/stm32/eicu_driver_lld.c
22 |
23 | STM32DRIVERINC = $(DRIVERINC)
24 | STM32DRIVERINC += $(DRIVERPATH)/stm32
25 |
--------------------------------------------------------------------------------
/drivers_conf_example.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DRIVERS_CONF_H
3 | #define _DRIVERS_CONF_H
4 |
5 | /**
6 | * @brief Enables the Drivers.
7 | */
8 | #if !defined(DRIVER_USE_DAC) || defined(__DOXYGEN__)
9 | #define DRIVER_USE_DAC TRUE
10 | #endif
11 |
12 | #if !defined(DRIVER_USE_IWDG) || defined(__DOXYGEN__)
13 | #define DRIVER_USE_IWDG TRUE
14 | #endif
15 |
16 | #if !defined(DRIVER_USE_TIMCAP) || defined(__DOXYGEN__)
17 | #define DRIVER_USE_TIMCAP TRUE
18 | #endif
19 |
20 | #if !defined(DRIVER_USE_IUART) || defined(__DOXYGEN__)
21 | #define DRIVER_USE_IUART TRUE
22 | #endif
23 |
24 | #if !defined(DRIVER_USE_EICU) || defined(__DOXYGEN__)
25 | #define DRIVER_USE_EICU TRUE
26 | #endif
27 |
28 | #if !defined(DRIVER_USE_EEPROM) || defined(__DOXYGEN__)
29 | #define DRIVER_USE_EEPROM TRUE
30 | #endif
31 |
32 |
33 | /*
34 | * DAC driver system settings.
35 | */
36 | #define STM32_DAC_USE_CHN1 TRUE
37 | #define STM32_DAC_USE_CHN2 TRUE
38 | #define STM32_DAC_CHN1_IRQ_PRIORITY 10
39 | #define STM32_DAC_CHN2_IRQ_PRIORITY 10
40 | #define STM32_DAC_CHN3_IRQ_PRIORITY 10
41 | #define STM32_DAC_CHN1_DMA_PRIORITY 2
42 | #define STM32_DAC_CHN2_DMA_PRIORITY 2
43 | #define STM32_DAC_CHN3_DMA_PRIORITY 2
44 | #define STM32_DAC_CHN1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
45 | #define STM32_DAC_CHN2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
46 | #define STM32_DAC_CHN3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
47 | #define STM32_DAC_DMA_ERROR_HOOK(dacp) chSysHalt()
48 |
49 | /*
50 | * TIMCAP driver system settings.
51 | */
52 | #define STM32_TIMCAP_USE_TIM1 TRUE
53 | #define STM32_TIMCAP_USE_TIM2 FALSE
54 | #define STM32_TIMCAP_USE_TIM3 FALSE
55 | #define STM32_TIMCAP_TIM1_IRQ_PRIORITY 2
56 | #define STM32_TIMCAP_TIM2_IRQ_PRIORITY 2
57 | #define STM32_TIMCAP_TIM3_IRQ_PRIORITY 2
58 |
59 | /*
60 | * IUART driver system settings.
61 | */
62 | #define STM32_IUART_USE_USART1 TRUE
63 | #define STM32_IUART_USE_USART2 FALSE
64 | #define STM32_IUART_USART1_IRQ_PRIORITY 3
65 | #define STM32_IUART_USART2_IRQ_PRIORITY 3
66 |
67 | /*
68 | * Extended ICU driver system settings.
69 | */
70 | #define STM32_EICU_USE_TIM1 FALSE
71 | #define STM32_EICU_USE_TIM2 FALSE
72 | #define STM32_EICU_USE_TIM3 TRUE
73 | #define STM32_EICU_USE_TIM4 FALSE
74 | #define STM32_EICU_USE_TIM5 FALSE
75 | #define STM32_EICU_USE_TIM8 FALSE
76 | #define STM32_EICU_USE_TIM9 FALSE
77 | #define STM32_EICU_USE_TIM12 FALSE
78 | #define STM32_EICU_TIM1_IRQ_PRIORITY 3
79 | #define STM32_EICU_TIM2_IRQ_PRIORITY 3
80 | #define STM32_EICU_TIM3_IRQ_PRIORITY 3
81 | #define STM32_EICU_TIM4_IRQ_PRIORITY 3
82 | #define STM32_EICU_TIM5_IRQ_PRIORITY 3
83 | #define STM32_EICU_TIM8_IRQ_PRIORITY 3
84 | #define STM32_EICU_TIM9_IRQ_PRIORITY 3
85 | #define STM32_EICU_TIM12_IRQ_PRIORITY 3
86 |
87 | /*
88 | * EEPROM driver system settings.
89 | */
90 | #define EEPROM_DRV_USE_25XX TRUE
91 | #define EEPROM_DRV_USE_24XX FALSE
92 |
93 | #endif /* _DRIVERS_CONF_H */
--------------------------------------------------------------------------------
/inc/dac_driver.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/HAL - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012,2013,2014 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/HAL
6 |
7 | ChibiOS/HAL is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | /**
22 | * @file dac.h
23 | * @brief DAC Driver macros and structures.
24 | *
25 | * @addtogroup DAC
26 | * @{
27 | */
28 |
29 | #ifndef _DAC_DRIVER_H_
30 | #define _DAC_DRIVER_H_
31 |
32 | #if DRIVER_USE_DAC || defined(__DOXYGEN__)
33 |
34 | /*===========================================================================*/
35 | /* Driver constants. */
36 | /*===========================================================================*/
37 |
38 | /*===========================================================================*/
39 | /* Driver pre-compile time settings. */
40 | /*===========================================================================*/
41 |
42 | /**
43 | * @name DAC configuration options
44 | * @{
45 | */
46 | /**
47 | * @brief Enables synchronous APIs.
48 | * @note Disabling this option saves both code and data space.
49 | */
50 | #if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
51 | #define DAC_USE_WAIT TRUE
52 | #endif
53 |
54 | /**
55 | * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
56 | * @note Disabling this option saves both code and data space.
57 | */
58 | #if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
59 | #define DAC_USE_MUTUAL_EXCLUSION TRUE
60 | #endif
61 | /** @} */
62 |
63 | /*===========================================================================*/
64 | /* Derived constants and error checks. */
65 | /*===========================================================================*/
66 |
67 | /*===========================================================================*/
68 | /* Driver data structures and types. */
69 | /*===========================================================================*/
70 |
71 | /**
72 | * @brief Driver state machine possible states.
73 | */
74 | typedef enum {
75 | DAC_UNINIT = 0, /**< Not initialized. */
76 | DAC_STOP = 1, /**< Stopped. */
77 | DAC_READY = 2, /**< Ready. */
78 | DAC_ACTIVE = 3, /**< Exchanging data. */
79 | DAC_COMPLETE = 4, /**< Asynchronous operation complete. */
80 | DAC_ERROR = 5 /**< Error. */
81 | } dacstate_t;
82 |
83 | #include "dac_driver_lld.h"
84 |
85 | /*===========================================================================*/
86 | /* Driver macros. */
87 | /*===========================================================================*/
88 |
89 | /**
90 | * @name Low Level driver helper macros
91 | * @{
92 | */
93 | #if DAC_USE_WAIT || defined(__DOXYGEN__)
94 | /**
95 | * @brief Waits for operation completion.
96 | * @details This function waits for the driver to complete the current
97 | * operation.
98 | * @pre An operation must be running while the function is invoked.
99 | * @note No more than one thread can wait on a DAC driver using
100 | * this function.
101 | *
102 | * @param[in] dacp pointer to the @p DACDriver object
103 | *
104 | * @notapi
105 | */
106 | #define _dac_wait_s(dacp) osalThreadSuspendS(&(dacp)->thread)
107 |
108 | /**
109 | * @brief Resumes a thread waiting for a conversion completion.
110 | *
111 | * @param[in] dacp pointer to the @p DACDriver object
112 | *
113 | * @notapi
114 | */
115 | #define _dac_reset_i(dacp) osalThreadResumeI(&(dacp)->thread, MSG_RESET)
116 |
117 | /**
118 | * @brief Resumes a thread waiting for a conversion completion.
119 | *
120 | * @param[in] dacp pointer to the @p DACDriver object
121 | *
122 | * @notapi
123 | */
124 | #define _dac_reset_s(dacp) osalThreadResumeS(&(dacp)->thread, MSG_RESET)
125 |
126 | /**
127 | * @brief Wakes up the waiting thread.
128 | *
129 | * @param[in] dacp pointer to the @p DACDriver object
130 | *
131 | * @notapi
132 | */
133 | #define _dac_wakeup_isr(dacp) { \
134 | osalSysLockFromISR(); \
135 | osalThreadResumeI(&(dacp)->thread, MSG_OK); \
136 | osalSysUnlockFromISR(); \
137 | }
138 |
139 | /**
140 | * @brief Wakes up the waiting thread with a timeout message.
141 | *
142 | * @param[in] dacp pointer to the @p DACDriver object
143 | *
144 | * @notapi
145 | */
146 | #define _dac_timeout_isr(dacp) { \
147 | osalSysLockFromISR(); \
148 | osalThreadResumeI(&(dacp)->thread, MSG_TIMEOUT); \
149 | osalSysUnlockFromISR(); \
150 | }
151 |
152 | #else /* !DAC_USE_WAIT */
153 | #define _dac_wait_s(dacp)
154 | #define _dac_reset_i(dacp)
155 | #define _dac_reset_s(dacp)
156 | #define _dac_wakeup_isr(dacp)
157 | #define _dac_timeout_isr(dacp)
158 | #endif /* !DAC_USE_WAIT */
159 |
160 | /**
161 | * @brief Common ISR code, half buffer event.
162 | * @details This code handles the portable part of the ISR code:
163 | * - Callback invocation.
164 | * .
165 | * @note This macro is meant to be used in the low level drivers
166 | * implementation only.
167 | *
168 | * @param[in] dacp pointer to the @p DACDriver object
169 | *
170 | * @notapi
171 | */
172 | #define _dac_isr_half_code(dacp) { \
173 | if ((dacp)->grpp->end_cb != NULL) { \
174 | (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth / 2); \
175 | } \
176 | }
177 |
178 | /**
179 | * @brief Common ISR code, full buffer event.
180 | * @details This code handles the portable part of the ISR code:
181 | * - Callback invocation.
182 | * - Waiting thread wakeup, if any.
183 | * - Driver state transitions.
184 | * .
185 | * @note This macro is meant to be used in the low level drivers
186 | * implementation only.
187 | *
188 | * @param[in] dacp pointer to the @p DACDriver object
189 | *
190 | * @notapi
191 | */
192 | #define _dac_isr_full_code(dacp) { \
193 | if ((dacp)->grpp->circular) { \
194 | /* Callback handling.*/ \
195 | if ((dacp)->grpp->end_cb != NULL) { \
196 | if ((dacp)->depth > 1) { \
197 | /* Invokes the callback passing the 2nd half of the buffer.*/ \
198 | size_t half = (dacp)->depth / 2; \
199 | size_t half_index = half * (dacp)->grpp->num_channels; \
200 | (dacp)->grpp->end_cb(dacp, (dacp)->samples + half_index, half); \
201 | } \
202 | else { \
203 | /* Invokes the callback passing the whole buffer.*/ \
204 | (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth); \
205 | } \
206 | } \
207 | } \
208 | else { \
209 | /* End conversion.*/ \
210 | dac_lld_stop_conversion(dacp); \
211 | if ((dacp)->grpp->end_cb != NULL) { \
212 | (dacp)->state = DAC_COMPLETE; \
213 | if ((dacp)->depth > 1) { \
214 | /* Invokes the callback passing the 2nd half of the buffer.*/ \
215 | size_t half = (dacp)->depth / 2; \
216 | size_t half_index = half * (dacp)->grpp->num_channels; \
217 | (dacp)->grpp->end_cb(dacp, (dacp)->samples + half_index, half); \
218 | } \
219 | else { \
220 | /* Invokes the callback passing the whole buffer.*/ \
221 | (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth); \
222 | } \
223 | if ((dacp)->state == DAC_COMPLETE) { \
224 | (dacp)->state = DAC_READY; \
225 | (dacp)->grpp = NULL; \
226 | } \
227 | } \
228 | else { \
229 | (dacp)->state = DAC_READY; \
230 | (dacp)->grpp = NULL; \
231 | } \
232 | _dac_wakeup_isr(dacp); \
233 | } \
234 | }
235 |
236 | /**
237 | * @brief Common ISR code, error event.
238 | * @details This code handles the portable part of the ISR code:
239 | * - Callback invocation.
240 | * - Waiting thread timeout signaling, if any.
241 | * - Driver state transitions.
242 | * .
243 | * @note This macro is meant to be used in the low level drivers
244 | * implementation only.
245 | *
246 | * @param[in] dacp pointer to the @p DACDriver object
247 | * @param[in] err platform dependent error code
248 | *
249 | * @notapi
250 | */
251 | #define _dac_isr_error_code(dacp, err) { \
252 | dac_lld_stop_conversion(dacp); \
253 | if ((dacp)->grpp->error_cb != NULL) { \
254 | (dacp)->state = DAC_ERROR; \
255 | (dacp)->grpp->error_cb(dacp, err); \
256 | if ((dacp)->state == DAC_ERROR) \
257 | (dacp)->state = DAC_READY; \
258 | } \
259 | (dacp)->grpp = NULL; \
260 | _dac_timeout_isr(dacp); \
261 | }
262 | /** @} */
263 |
264 | /*===========================================================================*/
265 | /* External declarations. */
266 | /*===========================================================================*/
267 |
268 | #ifdef __cplusplus
269 | extern "C" {
270 | #endif
271 | void dacInit(void);
272 | void dacObjectInit(DACDriver *dacp);
273 | void dacStart(DACDriver *dacp, const DACConfig *config);
274 | void dacStop(DACDriver *dacp);
275 | void dacConvertOne(DACDriver *dacp, dacsample_t value);
276 | void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp,
277 | const dacsample_t *samples, size_t depth);
278 | void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp,
279 | const dacsample_t *samples, size_t depth);
280 | void dacStopConversion(DACDriver *dacp);
281 | void dacStopConversionI(DACDriver *dacp);
282 | #if DAC_USE_WAIT || defined(__DOXYGEN__)
283 | msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp,
284 | const dacsample_t *samples, size_t depth);
285 | #endif /* DAC_USE_WAIT */
286 | #if DAC_USE_MUTUAL_EXCLUSION
287 | void dacAcquireBus(DACDriver *dacp);
288 | void dacReleaseBus(DACDriver *dacp);
289 | #endif /* DAC_USE_MUTUAL_EXCLUSION */
290 | #ifdef __cplusplus
291 | }
292 | #endif
293 |
294 | #endif /* DRIVER_USE_DAC */
295 |
296 | #endif /* _DAC_DRIVER_H_ */
297 |
298 | /** @} */
299 |
--------------------------------------------------------------------------------
/inc/drivers.h:
--------------------------------------------------------------------------------
1 | #ifndef DRIVERS_H
2 | #define DRIVERS_H
3 |
4 | #include "hal.h"
5 | #include "drivers_conf.h"
6 | #include "dac_driver.h"
7 | #include "eeprom_driver.h"
8 | #include "iwdg_driver.h"
9 | #include "timcap_driver.h"
10 | #include "iuart_driver.h"
11 | #include "eicu_driver.h"
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif
16 | void driversInit(void);
17 | #ifdef __cplusplus
18 | }
19 | #endif
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/inc/eeprom_driver.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Timon Wong
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | /*
24 | Copyright 2012 Uladzimir Pylinski aka barthess.
25 | You may use this work without restrictions, as long as this notice is included.
26 | The work is provided "as is" without warranty of any kind, neither express nor implied.
27 | */
28 |
29 | #ifndef __EEPROM_H__
30 | #define __EEPROM_H__
31 |
32 | #if defined(DRIVER_USE_EEPROM) && DRIVER_USE_EEPROM
33 |
34 | #include "ch.h"
35 | #include "drivers.h"
36 |
37 | #ifndef EEPROM_DRV_USE_25XX
38 | #define EEPROM_DRV_USE_25XX FALSE
39 | #endif
40 |
41 | #ifndef EEPROM_DRV_USE_24XX
42 | #define EEPROM_DRV_USE_24XX FALSE
43 | #endif
44 |
45 | #if EEPROM_DRV_USE_25XX && EEPROM_DRV_USE_24XX
46 | #define EEPROM_DRV_TABLE_SIZE 2
47 | #elif EEPROM_DRV_USE_25XX || EEPROM_DRV_USE_24XX
48 | #define EEPROM_DRV_TABLE_SIZE 1
49 | #else
50 | #error "No EEPROM device selected!"
51 | #endif
52 |
53 | #define _eeprom_file_config_data \
54 | /* Lower barrier of file in EEPROM memory array. */ \
55 | uint32_t barrier_low; \
56 | /* Higher barrier of file in EEPROM memory array. */ \
57 | uint32_t barrier_hi; \
58 | /* Size of memory array in bytes. */ \
59 | uint32_t size; \
60 | /* Size of single page in bytes. */ \
61 | uint16_t pagesize; \
62 | /* Time needed by IC for single byte/page writing. */ \
63 | systime_t write_time;
64 |
65 | typedef uint32_t fileoffset_t;
66 | #define FILE_OK 0
67 | #define FILE_ERROR 0xFFFFFFFFUL
68 |
69 | typedef struct {
70 | _eeprom_file_config_data
71 | } EepromFileConfig;
72 |
73 | /**
74 | * @brief @p EepromFileStream specific data.
75 | */
76 | #define _eeprom_file_stream_data \
77 | _base_sequential_stream_data \
78 | uint32_t errors; \
79 | uint32_t position; \
80 |
81 | /**
82 | * @extends BaseFileStreamVMT
83 | *
84 | * @brief @p EepromFileStream virtual methods table.
85 | */
86 | struct EepromFileStreamVMT {
87 | _base_sequential_stream_methods
88 | };
89 |
90 | /**
91 | * @extends BaseFileStream
92 | *
93 | * @brief EEPROM file stream driver class.
94 | * @details This class extends @p BaseFileStream by adding some fields.
95 | */
96 | typedef struct {
97 | /** @brief Virtual Methods Table.*/
98 | const struct EepromFileStreamVMT *vmt;
99 | _eeprom_file_stream_data
100 | /** pointer to config object, must be overwritten by all derived classes.*/
101 | const EepromFileConfig *cfg;
102 | } EepromFileStream;
103 |
104 | /**
105 | * @brief Low level device descriptor.
106 | */
107 | typedef struct {
108 | const char *name;
109 | const struct EepromFileStreamVMT *efsvmt;
110 | } EepromDevice;
111 |
112 | #if HAL_USE_I2C || defined(__DOXYGEN__)
113 |
114 | /**
115 | * @extends EepromFileConfig
116 | */
117 | typedef struct {
118 | _eeprom_file_config_data
119 | /**
120 | * Driver connected to IC.
121 | */
122 | I2CDriver *i2cp;
123 | /**
124 | * Address of IC on I2C bus.
125 | */
126 | i2caddr_t addr;
127 | /**
128 | * Pointer to write buffer. The safest size is (pagesize + 2)
129 | */
130 | uint8_t *write_buf;
131 | } I2CEepromFileConfig;
132 |
133 | /**
134 | * @brief @p I2CEepromFileStream specific data.
135 | */
136 | #define _eeprom_file_stream_data_i2c \
137 | _eeprom_file_stream_data
138 |
139 | /**
140 | * @extends EepromFileStream
141 | *
142 | * @brief EEPROM file stream driver class for I2C device.
143 | */
144 | typedef struct {
145 | const struct EepromFileStreamVMT *vmt;
146 | _eeprom_file_stream_data_i2c
147 | /* Overwritten parent data member. */
148 | const I2CEepromFileConfig *cfg;
149 | } I2CEepromFileStream;
150 |
151 |
152 | /**
153 | * Open I2C EEPROM IC as file and return pointer to the file stream object
154 | * @note Fucntion allways successfully open file. All checking makes
155 | * in read/write functions.
156 | */
157 | #define I2CEepromFileOpen(efs, eepcfg, eepdev) \
158 | EepromFileOpen((EepromFileStream *)efs, (EepromFileConfig *)eepcfg, eepdev);
159 |
160 | #endif /* HAL_USE_I2C */
161 |
162 | #if HAL_USE_SPI || defined(__DOXYGEN__)
163 |
164 | /**
165 | * @extends EepromFileConfig
166 | */
167 | typedef struct {
168 | _eeprom_file_config_data
169 | /**
170 | * Driver connected to IC.
171 | */
172 | SPIDriver *spip;
173 | /**
174 | * Config associated with SPI driver.
175 | */
176 | const SPIConfig *spicfg;
177 | } SPIEepromFileConfig;
178 |
179 | /**
180 | * @brief @p SPIEepromFileStream specific data.
181 | */
182 | #define _eeprom_file_stream_data_spi \
183 | _eeprom_file_stream_data
184 |
185 | /**
186 | * @extends EepromFileStream
187 | *
188 | * @brief EEPROM file stream driver class for SPI device.
189 | */
190 | typedef struct {
191 | const struct EepromFileStreamVMT *vmt;
192 | _eeprom_file_stream_data_spi
193 | /* Overwritten parent data member. */
194 | const SPIEepromFileConfig *cfg;
195 | } SPIEepromFileStream;
196 |
197 | /**
198 | * Open I2C EEPROM IC as file and return pointer to the file stream object
199 | * @note Fucntion allways successfully open file. All checking makes
200 | * in read/write functions.
201 | */
202 | EepromFileStream *SPIEepromFileOpen(SPIEepromFileStream *efs,
203 | const SPIEepromFileConfig *eepcfg,
204 | const EepromDevice *eepdev);
205 |
206 | #define SPIEepromFileOpen(efs, eepcfg, eepdev) \
207 | EepromFileOpen((EepromFileStream *)efs, (EepromFileConfig *)eepcfg, eepdev);
208 |
209 | #endif /* HAL_USE_SPI */
210 |
211 | #if !defined(chFileStreamRead)
212 | /**
213 | * @brief File Stream read.
214 | * @details The function reads data from a file into a buffer.
215 | *
216 | * @param[in] ip pointer to a @p BaseSequentialStream or derived class
217 | * @param[out] bp pointer to the data buffer
218 | * @param[in] n the maximum amount of data to be transferred
219 | * @return The number of bytes transferred. The return value can
220 | * be less than the specified number of bytes if the
221 | * stream reaches the end of the available data.
222 | *
223 | * @api
224 | */
225 | #define chFileStreamRead(ip, bp, n) (chSequentialStreamRead(ip, bp, n))
226 | #endif
227 |
228 | #if !defined(chFileStreamWrite)
229 | /**
230 | * @brief File Stream write.
231 | * @details The function writes data from a buffer to a file.
232 | *
233 | * @param[in] ip pointer to a @p BaseSequentialStream or derived class
234 | * @param[in] bp pointer to the data buffer
235 | * @param[in] n the maximum amount of data to be transferred
236 | * @return The number of bytes transferred. The return value can
237 | * be less than the specified number of bytes if the
238 | * stream reaches a physical end of file and cannot be
239 | * extended.
240 | *
241 | * @api
242 | */
243 | #define chFileStreamWrite(ip, bp, n) (chSequentialStreamWrite(ip, bp, n))
244 | #endif
245 |
246 | const EepromDevice *EepromFindDevice(const char *name);
247 |
248 | EepromFileStream *EepromFileOpen(EepromFileStream *efs,
249 | const EepromFileConfig *eepcfg,
250 | const EepromDevice *eepdev);
251 |
252 | uint8_t EepromReadByte(EepromFileStream *efs);
253 | uint16_t EepromReadHalfword(EepromFileStream *efs);
254 | uint32_t EepromReadWord(EepromFileStream *efs);
255 | size_t EepromWriteByte(EepromFileStream *efs, uint8_t data);
256 | size_t EepromWriteHalfword(EepromFileStream *efs, uint16_t data);
257 | size_t EepromWriteWord(EepromFileStream *efs, uint32_t data);
258 |
259 | fileoffset_t eepfs_getsize(void *ip);
260 | fileoffset_t eepfs_getposition(void *ip);
261 | fileoffset_t eepfs_lseek(void *ip, fileoffset_t offset);
262 | uint32_t eepfs_close(void *ip);
263 | int eepfs_geterror(void *ip);
264 | msg_t eepfs_put(void *ip, uint8_t b);
265 | msg_t eepfs_get(void *ip);
266 |
267 | #endif /* #if defined(DRIVER_USE_EEPROM) && DRIVER_USE_EEPROM */
268 | #endif /* __EEPROM_H__ */
--------------------------------------------------------------------------------
/inc/eicu_driver.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | /*
17 | Rewritten by Emil Fresk (1/5 - 2014) for extended input capture
18 | functionallity. And fix for spourious callbacks in the interrupt handler.
19 | */
20 |
21 | #ifndef _EICU_H_
22 | #define _EICU_H_
23 |
24 | #if DRIVER_USE_EICU || defined(__DOXYGEN__)
25 |
26 | /*===========================================================================*/
27 | /* Driver constants. */
28 | /*===========================================================================*/
29 |
30 | /*===========================================================================*/
31 | /* Driver pre-compile time settings. */
32 | /*===========================================================================*/
33 |
34 | /*===========================================================================*/
35 | /* Derived constants and error checks. */
36 | /*===========================================================================*/
37 |
38 | /*===========================================================================*/
39 | /* Driver data structures and types. */
40 | /*===========================================================================*/
41 |
42 | /**
43 | * @brief Driver state machine possible states.
44 | */
45 | typedef enum {
46 | EICU_UNINIT = 0, /* Not initialized. */
47 | EICU_STOP = 1, /* Stopped. */
48 | EICU_READY = 2, /* Ready. */
49 | EICU_WAITING = 3, /* Waiting for first edge. */
50 | EICU_ACTIVE = 4, /* Active cycle phase. */
51 | EICU_IDLE = 5 /* Idle cycle phase. */
52 | } eicustate_t;
53 |
54 | /**
55 | * @brief EICU channel selection definition
56 | */
57 | typedef enum {
58 | EICU_CHANNEL_1 = 0,
59 | EICU_CHANNEL_2 = 1,
60 | EICU_CHANNEL_3 = 2,
61 | EICU_CHANNEL_4 = 3
62 | } eicuchannel_t;
63 |
64 | /**
65 | * @brief Type of a structure representing an EICU driver.
66 | */
67 | typedef struct EICUDriver EICUDriver;
68 |
69 | /**
70 | * @brief EICU notification callback type.
71 | *
72 | * @param[in] eicup Pointer to a EICUDriver object
73 | * @param[in] channel EICU channel that fired the interrupt
74 | */
75 | typedef void (*eicucallback_t)(EICUDriver *eicup, eicuchannel_t channel);
76 |
77 | #include "eicu_driver_lld.h"
78 |
79 | /*===========================================================================*/
80 | /* Driver macros. */
81 | /*===========================================================================*/
82 |
83 | /**
84 | * @name Macro Functions
85 | * @{
86 | */
87 | /**
88 | * @brief Enables the extended input capture.
89 | *
90 | * @param[in] eicup Pointer to the @p EICUDriver object
91 | *
92 | * @iclass
93 | */
94 | #define eicuEnableI(eicup) eicu_lld_enable(eicup)
95 |
96 | /**
97 | * @brief Disables the extended input capture.
98 | *
99 | * @param[in] eicup Pointer to the @p EICUDriver object
100 | *
101 | * @iclass
102 | */
103 | #define eicuDisableI(eicup) eicu_lld_disable(eicup)
104 |
105 | /**
106 | * @brief Returns the width of the latest pulse.
107 | * @details The pulse width is defined as number of ticks between the start
108 | * edge and the stop edge.
109 | * @note This function is meant to be invoked from the width capture
110 | * callback only.
111 | *
112 | * @param[in] eicup Pointer to the @p EICUDriver object
113 | * @param[in] channel The timer channel that fired the interrupt.
114 | * @return The number of ticks.
115 | *
116 | * @special
117 | */
118 | #define eicuGetWidth(eicup, channel) eicu_lld_get_width((eicup), (channel))
119 |
120 | /**
121 | * @brief Returns the width of the latest cycle.
122 | * @details The cycle width is defined as number of ticks between a start
123 | * edge and the next start edge.
124 | * @note This function is meant to be invoked from the width capture
125 | * callback only.
126 | *
127 | * @param[in] eicup Pointer to the @p EICUDriver object
128 | * @return The number of ticks.
129 | *
130 | * @special
131 | */
132 | #define eicuGetPeriod(eicup) eicu_lld_get_period(eicup)
133 | /** @} */
134 |
135 | /**
136 | * @name Low Level driver helper macros
137 | * @{
138 | */
139 | /**
140 | * @brief Common ISR code, EICU PWM width event.
141 | *
142 | * @param[in] eicup Pointer to the @p EICUDriver object
143 | * @param[in] channel The timer channel that fired the interrupt.
144 | *
145 | * @notapi
146 | */
147 | #define _eicu_isr_invoke_pwm_width_cb(eicup, channel) { \
148 | if ((eicup)->state != EICU_WAITING) { \
149 | (eicup)->state = EICU_IDLE; \
150 | (eicup)->config->iccfgp[channel]->width_cb((eicup), (channel)); \
151 | } \
152 | }
153 |
154 | /**
155 | * @brief Common ISR code, EICU PWM period event.
156 | *
157 | * @param[in] eicup Pointer to the @p EICUDriver object
158 | * @param[in] channel The timer channel that fired the interrupt.
159 | *
160 | * @notapi
161 | */
162 | #define _eicu_isr_invoke_pwm_period_cb(eicup, channel) { \
163 | eicustate_t previous_state = (eicup)->state; \
164 | (eicup)->state = EICU_ACTIVE; \
165 | if (previous_state != EICU_WAITING) \
166 | (eicup)->config->period_cb((eicup), (channel)); \
167 | }
168 |
169 | /**
170 | * @brief Common ISR code, EICU Pulse width event.
171 | * @details This macro needs special care since it needs to invert the
172 | * correct polarity bit to detect pulses.
173 | * @note This macro assumes that the polarity is not changed by some
174 | * external user. It must only be changed using the HAL.
175 | *
176 | * @param[in] eicup Pointer to the @p EICUDriver object
177 | * @param[in] channel The timer channel that fired the interrupt.
178 | *
179 | * @notapi
180 | */
181 | #define _eicu_isr_invoke_pulse_width_cb(eicup, channel) { \
182 | if ((eicup)->state == EICU_ACTIVE) { \
183 | (eicup)->state = EICU_READY; \
184 | eicu_lld_invert_polarity((eicup), (channel)); \
185 | (eicup)->config->iccfgp[(channel)]->width_cb((eicup), (channel)); \
186 | } else { \
187 | (eicup)->state = EICU_ACTIVE; \
188 | (eicup)->last_count[(channel)] = eicu_lld_get_compare((eicup), (channel)); \
189 | eicu_lld_invert_polarity((eicup), (channel)); \
190 | } \
191 | }
192 |
193 | /**
194 | * @brief Common ISR code, EICU Edge detect event.
195 | *
196 | * @param[in] eicup Pointer to the @p EICUDriver object
197 | * @param[in] channel The timer channel that fired the interrupt.
198 | *
199 | * @notapi
200 | */
201 | #define _eicu_isr_invoke_edge_detect_cb(eicup, channel) { \
202 | (eicup)->state = EICU_READY; \
203 | (eicup)->config->iccfgp[(channel)]->width_cb((eicup), (channel)); \
204 | }
205 |
206 | /**
207 | * @brief Common ISR code, EICU timer overflow event.
208 | *
209 | * @param[in] eicup Pointer to the @p EICUDriver object
210 | *
211 | * @notapi
212 | */
213 | #define _eicu_isr_invoke_overflow_cb(icup) { \
214 | (eicup)->config->overflow_cb(eicup, 0); \
215 | }
216 | /** @} */
217 |
218 | /*===========================================================================*/
219 | /* External declarations. */
220 | /*===========================================================================*/
221 |
222 | #ifdef __cplusplus
223 | extern "C" {
224 | #endif
225 | void eicuInit(void);
226 | void eicuObjectInit(EICUDriver *eicup);
227 | void eicuStart(EICUDriver *eicup, const EICUConfig *config);
228 | void eicuStop(EICUDriver *eicup);
229 | void eicuEnable(EICUDriver *eicup);
230 | void eicuDisable(EICUDriver *eicup);
231 | #ifdef __cplusplus
232 | }
233 | #endif
234 |
235 | #endif /* DRIVER_USE_EICU */
236 |
237 | #endif /* _EICU_H_ */
238 |
239 | /** @} */
240 |
--------------------------------------------------------------------------------
/inc/iuart_driver.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012,2013 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | ---
21 |
22 | A special exception to the GPL can be applied should you wish to distribute
23 | a combined work that includes ChibiOS/RT, without being obliged to provide
24 | the source code for any proprietary components. See the file exception.txt
25 | for full details of how and when the exception can be applied.
26 | */
27 |
28 | /**
29 | * @file iuart.h
30 | * @brief IUART Driver macros and structures.
31 | *
32 | * @addtogroup IUART
33 | * @{
34 | */
35 |
36 | #ifndef _IUART_DRIVER_H_
37 | #define _IUART_DRIVER_H_
38 |
39 | #if DRIVER_USE_IUART || defined(__DOXYGEN__)
40 |
41 | /*===========================================================================*/
42 | /* Driver constants. */
43 | /*===========================================================================*/
44 |
45 | /**
46 | * @name IUART status flags
47 | * @{
48 | */
49 | #define IUART_NO_ERROR 0 /**< @brief No pending conditions. */
50 | #define IUART_PARITY_ERROR 4 /**< @brief Parity error happened. */
51 | #define IUART_FRAMING_ERROR 8 /**< @brief Framing error happened. */
52 | #define IUART_OVERRUN_ERROR 16 /**< @brief Overflow happened. */
53 | #define IUART_NOISE_ERROR 32 /**< @brief Noise on the line. */
54 | #define IUART_BREAK_DETECTED 64 /**< @brief Break detected. */
55 | /** @} */
56 |
57 | /*===========================================================================*/
58 | /* Driver pre-compile time settings. */
59 | /*===========================================================================*/
60 |
61 | /*===========================================================================*/
62 | /* Derived constants and error checks. */
63 | /*===========================================================================*/
64 |
65 | /*===========================================================================*/
66 | /* Driver data structures and types. */
67 | /*===========================================================================*/
68 |
69 | /**
70 | * @brief Driver state machine possible states.
71 | */
72 | typedef enum {
73 | IUART_UNINIT = 0, /**< Not initialized. */
74 | IUART_STOP = 1, /**< Stopped. */
75 | IUART_READY = 2 /**< Ready. */
76 | } iuartstate_t;
77 |
78 | /**
79 | * @brief Transmitter state machine states.
80 | */
81 | typedef enum {
82 | IUART_TX_IDLE = 0, /**< Not transmitting. */
83 | IUART_TX_ACTIVE = 1, /**< Transmitting. */
84 | IUART_TX_COMPLETE = 2 /**< Buffer complete. */
85 | } iuarttxstate_t;
86 |
87 | /**
88 | * @brief Receiver state machine states.
89 | */
90 | typedef enum {
91 | IUART_RX_IDLE = 0, /**< Not receiving. */
92 | IUART_RX_ACTIVE = 1, /**< Receiving. */
93 | IUART_RX_COMPLETE = 2 /**< Buffer complete. */
94 | } iuartrxstate_t;
95 |
96 | #include "iuart_driver_lld.h"
97 |
98 | /*===========================================================================*/
99 | /* Driver macros. */
100 | /*===========================================================================*/
101 |
102 | /*===========================================================================*/
103 | /* External declarations. */
104 | /*===========================================================================*/
105 |
106 | #ifdef __cplusplus
107 | extern "C" {
108 | #endif
109 | void iuartInit(void);
110 | void iuartObjectInit(IUARTDriver *iuartp);
111 | void iuartStart(IUARTDriver *iuartp, const IUARTConfig *config);
112 | void iuartStop(IUARTDriver *iuartp);
113 | void iuartStartSend(IUARTDriver *iuartp, size_t n, const void *txbuf);
114 | void iuartStartSendI(IUARTDriver *iuartp, size_t n, const void *txbuf);
115 | size_t iuartStopSend(IUARTDriver *iuartp);
116 | size_t iuartStopSendI(IUARTDriver *iuartp);
117 | void iuartStartReceive(IUARTDriver *iuartp, size_t n, void *rxbuf);
118 | void iuartStartReceiveI(IUARTDriver *iuartp, size_t n, void *rxbuf);
119 | size_t iuartStopReceive(IUARTDriver *iuartp);
120 | size_t iuartStopReceiveI(IUARTDriver *iuartp);
121 | #ifdef __cplusplus
122 | }
123 | #endif
124 |
125 | #endif /* DRIVER_USE_IUART */
126 |
127 | #endif /* _IUART_DRIVER_H_ */
128 |
129 | /** @} */
130 |
--------------------------------------------------------------------------------
/inc/iwdg_driver.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | ---
21 |
22 | A special exception to the GPL can be applied should you wish to distribute
23 | a combined work that includes ChibiOS/RT, without being obliged to provide
24 | the source code for any proprietary components. See the file exception.txt
25 | for full details of how and when the exception can be applied.
26 | */
27 |
28 | /**
29 | * @file iwdg.h
30 | * @brief IWDG Driver macros and structures.
31 | *
32 | * @addtogroup IWDG
33 | * @{
34 | */
35 |
36 | #ifndef _IWDG_DRIVER_H_
37 | #define _IWDG_DRIVER_H_
38 |
39 | #if DRIVER_USE_IWDG || defined(__DOXYGEN__)
40 |
41 | /*===========================================================================*/
42 | /* Driver constants. */
43 | /*===========================================================================*/
44 |
45 | /*===========================================================================*/
46 | /* Driver pre-compile time settings. */
47 | /*===========================================================================*/
48 |
49 | /*===========================================================================*/
50 | /* Derived constants and error checks. */
51 | /*===========================================================================*/
52 |
53 | /*===========================================================================*/
54 | /* Driver data structures and types. */
55 | /*===========================================================================*/
56 |
57 | /**
58 | * @brief Driver state machine possible states.
59 | */
60 | typedef enum {
61 | IWDG_UNINIT = 0, /**< Not initialized. */
62 | IWDG_STOP = 1, /**< Stopped. */
63 | IWDG_READY = 2, /**< Ready. */
64 | } iwdgstate_t;
65 |
66 | /**
67 | * @brief Type of a structure representing a IWDG driver.
68 | */
69 |
70 |
71 | #include "iwdg_driver_lld.h"
72 |
73 |
74 | /*===========================================================================*/
75 | /* Driver macros. */
76 | /*===========================================================================*/
77 |
78 | /*===========================================================================*/
79 | /* External declarations. */
80 | /*===========================================================================*/
81 |
82 | #ifdef __cplusplus
83 | extern "C" {
84 | #endif
85 | void iwdgInit(void);
86 | void iwdgStart( IWDGDriver *iwdgp, const IWDGConfig * config );
87 | void iwdgReset( IWDGDriver *iwdgp );
88 | #ifdef __cplusplus
89 | }
90 | #endif
91 |
92 | #endif /* DRIVER_USE_IWDG */
93 |
94 | #endif /* _IWDG_DRIVER_H_ */
95 |
96 | /** @} */
97 |
--------------------------------------------------------------------------------
/inc/timcap_driver.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012,2013 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | /**
22 | * @file timcap.h
23 | * @brief TIMCAP Driver macros and structures.
24 | *
25 | * @addtogroup TIMCAP
26 | * @{
27 | */
28 |
29 | #ifndef _TIMCAP_DRIVER_H_
30 | #define _TIMCAP_DRIVER_H_
31 |
32 | #include "ch.h"
33 | #include "hal.h"
34 |
35 | #if DRIVER_USE_TIMCAP || defined(__DOXYGEN__)
36 |
37 | /*===========================================================================*/
38 | /* Driver constants. */
39 | /*===========================================================================*/
40 |
41 | /*===========================================================================*/
42 | /* Driver pre-compile time settings. */
43 | /*===========================================================================*/
44 |
45 | /*===========================================================================*/
46 | /* Derived constants and error checks. */
47 | /*===========================================================================*/
48 |
49 | /*===========================================================================*/
50 | /* Driver data structures and types. */
51 | /*===========================================================================*/
52 |
53 | /**
54 | * @brief Driver state machine possible states.
55 | */
56 | typedef enum {
57 | TIMCAP_UNINIT = 0, /**< Not initialized. */
58 | TIMCAP_STOP = 1, /**< Stopped. */
59 | TIMCAP_READY = 2, /**< Ready. */
60 | TIMCAP_WAITING = 3, /**< Waiting first edge. */
61 | TIMCAP_ACTIVE = 4, /**< Active cycle phase. */
62 | TIMCAP_IDLE = 5, /**< Idle cycle phase. */
63 | } timcapstate_t;
64 |
65 | /**
66 | * @brief Type of a structure representing an TIMCAP driver.
67 | */
68 | typedef struct TIMCAPDriver TIMCAPDriver;
69 |
70 |
71 | /**
72 | * @brief TIMCAP notification callback type.
73 | *
74 | * @param[in] timcapp pointer to a @p TIMCAPDriver object
75 | */
76 | typedef void (*timcapcallback_t)(TIMCAPDriver *timcapp);
77 |
78 | #include "timcap_driver_lld.h"
79 |
80 | /*===========================================================================*/
81 | /* Driver macros. */
82 | /*===========================================================================*/
83 |
84 | /**
85 | * @name Macro Functions
86 | * @{
87 | */
88 | /**
89 | * @brief Enables the input capture.
90 | *
91 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
92 | *
93 | * @iclass
94 | */
95 | #define timcapEnableI(timcapp) timcap_lld_enable(timcapp)
96 |
97 | /**
98 | * @brief Disables the input capture.
99 | *
100 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
101 | *
102 | * @iclass
103 | */
104 | #define timcapDisableI(timcapp) timcap_lld_disable(timcapp)
105 |
106 |
107 |
108 |
109 | /** @} */
110 |
111 | /**
112 | * @name Low Level driver helper macros
113 | * @{
114 | */
115 |
116 |
117 | /**
118 | * @brief Common ISR code, TIMCAP channel 1 event.
119 | *
120 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
121 | *
122 | * @notapi
123 | */
124 | #define _timcap_isr_invoke_channel1_cb(timcapp) { \
125 | timcapstate_t previous_state = (timcapp)->state; \
126 | (timcapp)->state = TIMCAP_ACTIVE; \
127 | if (previous_state != TIMCAP_WAITING) \
128 | (timcapp)->config->capture_cb_array[0](timcapp); \
129 | }
130 |
131 | /**
132 | * @brief Common ISR code, TIMCAP channel 2 event.
133 | *
134 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
135 | *
136 | * @notapi
137 | */
138 | #define _timcap_isr_invoke_channel2_cb(timcapp) { \
139 | timcapstate_t previous_state = (timcapp)->state; \
140 | (timcapp)->state = TIMCAP_ACTIVE; \
141 | if (previous_state != TIMCAP_WAITING) \
142 | (timcapp)->config->capture_cb_array[1](timcapp); \
143 | }
144 |
145 | /**
146 | * @brief Common ISR code, TIMCAP channel 3 event.
147 | *
148 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
149 | *
150 | * @notapi
151 | */
152 | #define _timcap_isr_invoke_channel3_cb(timcapp) { \
153 | timcapstate_t previous_state = (timcapp)->state; \
154 | (timcapp)->state = TIMCAP_ACTIVE; \
155 | if (previous_state != TIMCAP_WAITING) \
156 | (timcapp)->config->capture_cb_array[2](timcapp); \
157 | }
158 |
159 | /**
160 | * @brief Common ISR code, TIMCAP channel 4 event.
161 | *
162 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
163 | *
164 | * @notapi
165 | */
166 | #define _timcap_isr_invoke_channel4_cb(timcapp) { \
167 | timcapstate_t previous_state = (timcapp)->state; \
168 | (timcapp)->state = TIMCAP_ACTIVE; \
169 | if (previous_state != TIMCAP_WAITING) \
170 | (timcapp)->config->capture_cb_array[3](timcapp); \
171 | }
172 |
173 | /**
174 | * @brief Common ISR code, TIMCAP timer overflow event.
175 | *
176 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
177 | *
178 | * @notapi
179 | */
180 | #define _timcap_isr_invoke_overflow_cb(timcapp) { \
181 | (timcapp)->config->overflow_cb(timcapp); \
182 | }
183 | /** @} */
184 |
185 | /*===========================================================================*/
186 | /* External declarations. */
187 | /*===========================================================================*/
188 |
189 | #ifdef __cplusplus
190 | extern "C" {
191 | #endif
192 | void timcapInit(void);
193 | void timcapObjectInit(TIMCAPDriver *timcapp);
194 | void timcapStart(TIMCAPDriver *timcapp, const TIMCAPConfig *config);
195 | void timcapStop(TIMCAPDriver *timcapp);
196 | void timcapEnable(TIMCAPDriver *timcapp);
197 | void timcapDisable(TIMCAPDriver *timcapp);
198 | #ifdef __cplusplus
199 | }
200 | #endif
201 |
202 | #endif /* DRIVER_USE_TIMCAP */
203 |
204 | #endif /* _TIMCAP_DRIVER_H_ */
205 |
206 | /** @} */
207 |
--------------------------------------------------------------------------------
/src/24xx_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Timon Wong
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | /*
24 | Copyright 2012 Uladzimir Pylinski aka barthess.
25 | You may use this work without restrictions, as long as this notice is included.
26 | The work is provided "as is" without warranty of any kind, neither express nor implied.
27 | */
28 |
29 | /*****************************************************************************
30 | * DATASHEET NOTES
31 | *****************************************************************************
32 | Write cycle time (byte or page) - 5 ms
33 |
34 | Note:
35 | Page write operations are limited to writing bytes within a single physical
36 | page, regardless of the number of bytes actually being written. Physical page
37 | boundaries start at addresses that are integer multiples of the page buffer
38 | size (or page size and end at addresses that are integer multiples of
39 | [page size]. If a Page Write command attempts to write across a physical
40 | page boundary, the result is that the data wraps around to the beginning of
41 | the current page (overwriting data previously stored there), instead of
42 | being written to the next page as might be expected.
43 | *********************************************************************/
44 |
45 | #include "eeprom_driver.h"
46 | #include
47 |
48 | #if HAL_USE_I2C || defined(__DOXYGEN__)
49 |
50 | #if EEPROM_DRV_USE_24XX || defined(__DOXYGEN__)
51 |
52 | /*
53 | ******************************************************************************
54 | * DEFINES
55 | ******************************************************************************
56 | */
57 | #if defined(SAM7_PLATFORM)
58 | #define EEPROM_I2C_CLOCK (MCK / (((i2cp->config->cwgr & 0xFF) + ((i2cp->config->cwgr >> 8) & 0xFF)) * (1 << ((i2cp->config->cwgr >> 16) & 7)) + 6))
59 | #else
60 | #define EEPROM_I2C_CLOCK (i2cp->config->clock_speed)
61 | #endif
62 |
63 | /*
64 | ******************************************************************************
65 | * EXTERNS
66 | ******************************************************************************
67 | */
68 |
69 | /*
70 | ******************************************************************************
71 | * GLOBAL VARIABLES
72 | ******************************************************************************
73 | */
74 |
75 | /*
76 | *******************************************************************************
77 | * LOCAL FUNCTIONS
78 | *******************************************************************************
79 | */
80 | /**
81 | * @brief Split one uint16_t address to two uint8_t.
82 | *
83 | * @param[in] txbuf pointer to driver transmit buffer
84 | * @param[in] addr uint16_t address
85 | */
86 | #define eeprom_split_addr(txbuf, addr){ \
87 | (txbuf)[0] = ((uint8_t)((addr >> 8) & 0xFF)); \
88 | (txbuf)[1] = ((uint8_t)(addr & 0xFF)); \
89 | }
90 |
91 | /*
92 | *******************************************************************************
93 | * EXPORTED FUNCTIONS
94 | *******************************************************************************
95 | */
96 |
97 | /**
98 | * @brief Calculates requred timeout.
99 | */
100 | static systime_t calc_timeout(I2CDriver *i2cp, size_t txbytes, size_t rxbytes) {
101 | const uint32_t bitsinbyte = 10;
102 | uint32_t tmo;
103 | tmo = ((txbytes + rxbytes + 1) * bitsinbyte * 1000);
104 | tmo /= EEPROM_I2C_CLOCK;
105 | tmo += 10; /* some additional milliseconds to be safer */
106 | return MS2ST(tmo);
107 | }
108 |
109 | /**
110 | * @brief EEPROM read routine.
111 | *
112 | * @param[in] eepcfg pointer to configuration structure of eeprom file
113 | * @param[in] offset addres of 1-st byte to be read
114 | * @param[in] data pointer to buffer with data to be written
115 | * @param[in] len number of bytes to be red
116 | */
117 | static msg_t eeprom_read(const I2CEepromFileConfig *eepcfg,
118 | uint32_t offset, uint8_t *data, size_t len) {
119 |
120 | msg_t status = MSG_RESET;
121 | systime_t tmo = calc_timeout(eepcfg->i2cp, 2, len);
122 |
123 | osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
124 | "out of device bounds");
125 |
126 | eeprom_split_addr(eepcfg->write_buf, (offset + eepcfg->barrier_low));
127 |
128 | #if I2C_USE_MUTUAL_EXCLUSION
129 | i2cAcquireBus(eepcfg->i2cp);
130 | #endif
131 |
132 | status = i2cMasterTransmitTimeout(eepcfg->i2cp, eepcfg->addr,
133 | eepcfg->write_buf, 2, data, len, tmo);
134 |
135 | #if I2C_USE_MUTUAL_EXCLUSION
136 | i2cReleaseBus(eepcfg->i2cp);
137 | #endif
138 |
139 | return status;
140 | }
141 |
142 | /**
143 | * @brief EEPROM write routine.
144 | * @details Function writes data to EEPROM.
145 | * @pre Data must be fit to single EEPROM page.
146 | *
147 | * @param[in] eepcfg pointer to configuration structure of eeprom file
148 | * @param[in] offset addres of 1-st byte to be write
149 | * @param[in] data pointer to buffer with data to be written
150 | * @param[in] len number of bytes to be written
151 | */
152 | static msg_t eeprom_write(const I2CEepromFileConfig *eepcfg, uint32_t offset,
153 | const uint8_t *data, size_t len) {
154 | msg_t status = MSG_RESET;
155 | systime_t tmo = calc_timeout(eepcfg->i2cp, (len + 2), 0);
156 |
157 | osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
158 | "out of device bounds");
159 | osalDbgAssert((((offset + eepcfg->barrier_low) / eepcfg->pagesize) ==
160 | (((offset + eepcfg->barrier_low) + len - 1) / eepcfg->pagesize)),
161 | "data can not be fitted in single page");
162 |
163 | /* write address bytes */
164 | eeprom_split_addr(eepcfg->write_buf, (offset + eepcfg->barrier_low));
165 | /* write data bytes */
166 | memcpy(&(eepcfg->write_buf[2]), data, len);
167 |
168 | #if I2C_USE_MUTUAL_EXCLUSION
169 | i2cAcquireBus(eepcfg->i2cp);
170 | #endif
171 |
172 | status = i2cMasterTransmitTimeout(eepcfg->i2cp, eepcfg->addr,
173 | eepcfg->write_buf, (len + 2), NULL, 0, tmo);
174 |
175 | #if I2C_USE_MUTUAL_EXCLUSION
176 | i2cReleaseBus(eepcfg->i2cp);
177 | #endif
178 |
179 | /* wait until EEPROM process data */
180 | chThdSleep(eepcfg->write_time);
181 |
182 | return status;
183 | }
184 |
185 | /**
186 | * @brief Determines and returns size of data that can be processed
187 | */
188 | static size_t __clamp_size(void *ip, size_t n) {
189 |
190 | if ((eepfs_getposition(ip) + n) > eepfs_getsize(ip))
191 | return eepfs_getsize(ip) - eepfs_getposition(ip);
192 | else
193 | return n;
194 | }
195 |
196 | /**
197 | * @brief Write data that can be fitted in one page boundary
198 | */
199 | static void __fitted_write(void *ip, const uint8_t *data, size_t len, uint32_t *written) {
200 |
201 | msg_t status = MSG_RESET;
202 |
203 | osalDbgAssert(len != 0, "something broken in hi level part");
204 |
205 | status = eeprom_write(((I2CEepromFileStream *)ip)->cfg,
206 | eepfs_getposition(ip), data, len);
207 | if (status == MSG_OK) {
208 | *written += len;
209 | eepfs_lseek(ip, eepfs_getposition(ip) + len);
210 | }
211 | }
212 |
213 | /**
214 | * @brief Write data to EEPROM.
215 | * @details Only one EEPROM page can be written at once. So fucntion
216 | * splits large data chunks in small EEPROM transactions if needed.
217 | * @note To achieve the maximum effectivity use write operations
218 | * aligned to EEPROM page boundaries.
219 | */
220 | static size_t write(void *ip, const uint8_t *bp, size_t n) {
221 |
222 | size_t len = 0; /* bytes to be written at one trasaction */
223 | uint32_t written; /* total bytes successfully written */
224 | uint16_t pagesize;
225 | uint32_t firstpage;
226 | uint32_t lastpage;
227 |
228 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
229 |
230 | if (n == 0)
231 | return 0;
232 |
233 | n = __clamp_size(ip, n);
234 | if (n == 0)
235 | return 0;
236 |
237 | pagesize = ((EepromFileStream *)ip)->cfg->pagesize;
238 | firstpage = (((EepromFileStream *)ip)->cfg->barrier_low +
239 | eepfs_getposition(ip)) / pagesize;
240 | lastpage = (((EepromFileStream *)ip)->cfg->barrier_low +
241 | eepfs_getposition(ip) + n - 1) / pagesize;
242 |
243 | written = 0;
244 | /* data fitted in single page */
245 | if (firstpage == lastpage) {
246 | len = n;
247 | __fitted_write(ip, bp, len, &written);
248 | bp += len;
249 | return written;
250 | }
251 |
252 | else {
253 | /* write first piece of data to first page boundary */
254 | len = ((firstpage + 1) * pagesize) - eepfs_getposition(ip);
255 | len -= ((EepromFileStream *)ip)->cfg->barrier_low;
256 | __fitted_write(ip, bp, len, &written);
257 | bp += len;
258 |
259 | /* now writes blocks at a size of pages (may be no one) */
260 | while ((n - written) > pagesize) {
261 | len = pagesize;
262 | __fitted_write(ip, bp, len, &written);
263 | bp += len;
264 | }
265 |
266 | /* wrtie tail */
267 | len = n - written;
268 | if (len == 0)
269 | return written;
270 | else {
271 | __fitted_write(ip, bp, len, &written);
272 | }
273 | }
274 |
275 | return written;
276 | }
277 |
278 | /**
279 | * Read some bytes from current position in file. After successful
280 | * read operation the position pointer will be increased by the number
281 | * of read bytes.
282 | */
283 | static size_t read(void *ip, uint8_t *bp, size_t n) {
284 | msg_t status = MSG_OK;
285 |
286 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
287 |
288 | if (n == 0)
289 | return 0;
290 |
291 | n = __clamp_size(ip, n);
292 | if (n == 0)
293 | return 0;
294 |
295 | /* Stupid I2C cell in STM32F1x does not allow to read single byte.
296 | So we must read 2 bytes and return needed one. */
297 | #if defined(STM32F1XX_I2C)
298 | if (n == 1) {
299 | uint8_t __buf[2];
300 | /* if NOT last byte of file requested */
301 | if ((eepfs_getposition(ip) + 1) < eepfs_getsize(ip)) {
302 | if (read(ip, __buf, 2) == 2) {
303 | eepfs_lseek(ip, (eepfs_getposition(ip) + 1));
304 | bp[0] = __buf[0];
305 | return 1;
306 | }
307 | else
308 | return 0;
309 | }
310 | else {
311 | eepfs_lseek(ip, (eepfs_getposition(ip) - 1));
312 | if (read(ip, __buf, 2) == 2) {
313 | eepfs_lseek(ip, (eepfs_getposition(ip) + 2));
314 | bp[0] = __buf[1];
315 | return 1;
316 | }
317 | else
318 | return 0;
319 | }
320 | }
321 | #endif /* defined(STM32F1XX_I2C) */
322 |
323 | /* call low level function */
324 | status = eeprom_read(((I2CEepromFileStream *)ip)->cfg,
325 | eepfs_getposition(ip), bp, n);
326 | if (status != MSG_OK)
327 | return 0;
328 | else {
329 | eepfs_lseek(ip, (eepfs_getposition(ip) + n));
330 | return n;
331 | }
332 | }
333 |
334 | static const struct EepromFileStreamVMT vmt = {
335 | write,
336 | read,
337 | eepfs_put,
338 | eepfs_get,/*
339 | eepfs_close,
340 | eepfs_geterror,
341 | eepfs_getsize,
342 | eepfs_getposition,
343 | eepfs_lseek,*/
344 | };
345 |
346 | EepromDevice eepdev_24xx = {
347 | "24XX",
348 | &vmt
349 | };
350 |
351 | #endif /* EEPROM_DRV_USE_24XX */
352 |
353 | #endif /* HAL_USE_I2C */
354 |
--------------------------------------------------------------------------------
/src/25xx_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Timon Wong
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | /*
24 | Copyright 2012 Uladzimir Pylinski aka barthess.
25 | You may use this work without restrictions, as long as this notice is included.
26 | The work is provided "as is" without warranty of any kind, neither express nor implied.
27 | */
28 |
29 | /*****************************************************************************
30 | * DATASHEET NOTES
31 | *****************************************************************************
32 | Write cycle time (byte or page) - 5 ms
33 |
34 | Note:
35 | Page write operations are limited to writing bytes within a single physical
36 | page, regardless of the number of bytes actually being written. Physical page
37 | boundaries start at addresses that are integer multiples of the page buffer
38 | size (or page size and end at addresses that are integer multiples of
39 | [page size]. If a Page Write command attempts to write across a physical
40 | page boundary, the result is that the data wraps around to the beginning of
41 | the current page (overwriting data previously stored there), instead of
42 | being written to the next page as might be expected.
43 | *********************************************************************/
44 |
45 | #include "eeprom_driver.h"
46 | #include
47 |
48 | #if HAL_USE_SPI || defined(__DOXYGEN__)
49 |
50 | #if EEPROM_DRV_USE_25XX || defined(__DOXYGEN__)
51 |
52 | /**
53 | * @name Commands of 25XX chip.
54 | * @{
55 | */
56 | #define CMD_READ 0x03 /**< @brief Read data from memory array beginning at
57 | selected address. */
58 | #define CMD_WRITE 0x02 /**< @brief Write data to memory array beginning at
59 | selected address. */
60 | #define CMD_WRDI 0x04 /**< Reset the write enable latch (disable write
61 | operations). */
62 | #define CMD_WREN 0x06 /**< Set the write enable latch (enable write
63 | operations). */
64 | #define CMD_RDSR 0x05 /**< Read STATUS register. */
65 | #define CMD_WRSR 0x01 /**< Write STATUS register. */
66 |
67 | /** @} */
68 |
69 | /**
70 | * @name Status of 25XX chip.
71 | * @{}
72 | */
73 | #define STAT_BP1 0x08 /**< @brief Block protection (high). */
74 | #define STAT_BP0 0x04 /**< @brief Block protection (low). */
75 | #define STAT_WEL 0x02 /**< @brief Write enable latch. */
76 | #define STAT_WIP 0x01 /**< @brief Write-In-Progress. */
77 |
78 | /** @} */
79 |
80 | /**
81 | * @brief 25XX low level write then read rountine.
82 | *
83 | * @param[in] eepcfg pointer to configuration structure of eeprom file.
84 | * @param[in] txbuf pointer to buffer to be transfered.
85 | * @param[in] txlen number of bytes to be transfered.
86 | * @param[out] rxbuf pointer to buffer to be received.
87 | * @param[in] rxlen number of bytes to be received.
88 | */
89 | static void ll_25xx_transmit_receive(const SPIEepromFileConfig *eepcfg,
90 | const uint8_t *txbuf, size_t txlen,
91 | uint8_t *rxbuf, size_t rxlen) {
92 |
93 | #if SPI_USE_MUTUAL_EXCLUSION
94 | spiAcquireBus(eepcfg->spip);
95 | #endif
96 |
97 | spiStart(eepcfg->spip, eepcfg->spicfg);
98 | spiSelect(eepcfg->spip);
99 | spiSend(eepcfg->spip, txlen, &txbuf);
100 | if (rxlen) /* Check if receive is needed. */
101 | spiReceive(eepcfg->spip, rxlen, &rxbuf);
102 | spiUnselect(eepcfg->spip);
103 |
104 | #if SPI_USE_MUTUAL_EXCLUSION
105 | spiReleaseBus(eepcfg->spip);
106 | #endif
107 | }
108 |
109 | /**
110 | * @brief Check whether the device is busy (writing in progress).
111 | *
112 | * @param[in] eepcfg pointer to configuration structure of eeprom file.
113 | * @return @p true on busy.
114 | */
115 | static bool ll_eeprom_is_busy(const SPIEepromFileConfig *eepcfg) {
116 |
117 | uint8_t cmd = CMD_RDSR;
118 | uint8_t stat;
119 | ll_25xx_transmit_receive(eepcfg, &cmd, 1, &stat, 1);
120 | if (stat & STAT_WIP)
121 | return TRUE;
122 | return FALSE;
123 | }
124 |
125 | /**
126 | * @brief Lock device.
127 | *
128 | * @param[in] eepcfg pointer to configuration structure of eeprom file.
129 | */
130 | static void ll_eeprom_lock(const SPIEepromFileConfig *eepcfg) {
131 |
132 | uint8_t cmd = CMD_WRDI;
133 | ll_25xx_transmit_receive(eepcfg, &cmd, 1, NULL, 0);
134 | }
135 |
136 | /**
137 | * @brief Unlock device.
138 | *
139 | * @param[in] eepcfg pointer to configuration structure of eeprom file.
140 | */
141 | static void ll_eeprom_unlock(const SPIEepromFileConfig *eepcfg) {
142 |
143 | uint8_t cmd = CMD_WREN;
144 | ll_25xx_transmit_receive(eepcfg, &cmd, 1, NULL, 0);
145 | }
146 |
147 | /**
148 | * @brief Prepare byte sequence for command and address
149 | *
150 | * @param[in] seq pointer to first 3byte sequence
151 | * @param[in] size size of the eeprom device
152 | * @param[in] cmd command
153 | * @param[in] addr address
154 | * @return number of bytes of this sequence
155 | */
156 | static uint8_t ll_eeprom_prepare_seq(uint8_t *seq, uint32_t size, uint8_t cmd,
157 | uint32_t addr) {
158 |
159 | seq[0] = ((uint8_t)cmd & 0xff);
160 |
161 | if (size > 0xffffUL) {
162 | /* High density, 24bit address. */
163 | seq[1] = (uint8_t)((addr >> 16) & 0xff);
164 | seq[2] = (uint8_t)((addr >> 8) & 0xff);
165 | seq[3] = (uint8_t)(addr & 0xff);
166 | return 4;
167 | }
168 | else if (size > 0x00ffUL) {
169 | /* Medium density, 16bit address. */
170 | seq[1] = (uint8_t)((addr >> 8) & 0xff);
171 | seq[2] = (uint8_t)(addr & 0xff);
172 | return 3;
173 | }
174 |
175 | /* Low density, 8bit address. */
176 | seq[1] = (uint8_t)(addr & 0xff);
177 | return 2;
178 | }
179 |
180 | /**
181 | * @brief EEPROM read routine.
182 | *
183 | * @param[in] eepcfg pointer to configuration structure of eeprom file.
184 | * @param[in] offset addres of 1-st byte to be read.
185 | * @param[out] data pointer to buffer with data to be written.
186 | * @param[in] len number of bytes to be red.
187 | */
188 | static msg_t ll_eeprom_read(const SPIEepromFileConfig *eepcfg, uint32_t offset,
189 | uint8_t *data, size_t len) {
190 |
191 | uint8_t txbuff[4];
192 | uint8_t txlen;
193 |
194 | osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
195 | "out of device bounds");
196 |
197 | txlen = ll_eeprom_prepare_seq(txbuff, eepcfg->size, CMD_READ,
198 | (offset + eepcfg->barrier_low));
199 | ll_25xx_transmit_receive(eepcfg, txbuff, txlen, data, len);
200 |
201 | return MSG_OK;
202 | }
203 |
204 | /**
205 | * @brief EEPROM write routine.
206 | * @details Function writes data to EEPROM.
207 | * @pre Data must be fit to single EEPROM page.
208 | *
209 | * @param[in] eepcfg pointer to configuration structure of eeprom file.
210 | * @param[in] offset addres of 1-st byte to be writen.
211 | * @param[in] data pointer to buffer with data to be written.
212 | * @param[in] len number of bytes to be written.
213 | */
214 | static msg_t ll_eeprom_write(const SPIEepromFileConfig *eepcfg, uint32_t offset,
215 | const uint8_t *data, size_t len) {
216 |
217 | uint8_t txbuff[4];
218 | uint8_t txlen;
219 | systime_t now;
220 |
221 | osalDbgAssert(((len <= eepcfg->size) && ((offset + len) <= eepcfg->size)),
222 | "out of device bounds");
223 | osalDbgAssert((((offset + eepcfg->barrier_low) / eepcfg->pagesize) ==
224 | (((offset + eepcfg->barrier_low) + len - 1) / eepcfg->pagesize)),
225 | "data can not be fitted in single page");
226 |
227 | /* Unlock array for writting. */
228 | ll_eeprom_unlock(eepcfg);
229 |
230 | #if SPI_USE_MUTUAL_EXCLUSION
231 | spiAcquireBus(eepcfg->spip);
232 | #endif
233 |
234 | spiStart(eepcfg->spip, eepcfg->spicfg);
235 | spiSelect(eepcfg->spip);
236 | txlen = ll_eeprom_prepare_seq(txbuff, eepcfg->size, CMD_WRITE,
237 | (offset + eepcfg->barrier_low));
238 | spiSend(eepcfg->spip, txlen, txbuff);
239 | spiSend(eepcfg->spip, len, data);
240 | spiUnselect(eepcfg->spip);
241 |
242 | #if SPI_USE_MUTUAL_EXCLUSION
243 | spiReleaseBus(eepcfg->spip);
244 | #endif
245 |
246 | /* Wait until EEPROM process data. */
247 | now = chVTGetSystemTimeX();
248 | while (ll_eeprom_is_busy(eepcfg)) {
249 | if ((chVTGetSystemTimeX() - now) > eepcfg->write_time) {
250 | return MSG_TIMEOUT;
251 | }
252 |
253 | chThdYield();
254 | }
255 |
256 | /* Lock array preventing unexpected access */
257 | ll_eeprom_lock(eepcfg);
258 | return MSG_OK;
259 | }
260 |
261 | /**
262 | * @brief Determines and returns size of data that can be processed
263 | */
264 | static size_t __clamp_size(void *ip, size_t n) {
265 |
266 | if ((eepfs_getposition(ip) + n) > eepfs_getsize(ip))
267 | return eepfs_getsize(ip) - eepfs_getposition(ip);
268 | else
269 | return n;
270 | }
271 |
272 | /**
273 | * @brief Write data that can be fitted in one page boundary
274 | */
275 | static void __fitted_write(void *ip, const uint8_t *data, size_t len, uint32_t *written) {
276 |
277 | msg_t status = MSG_RESET;
278 |
279 | osalDbgAssert(len != 0, "something broken in hi level part");
280 |
281 | status = ll_eeprom_write(((SPIEepromFileStream *)ip)->cfg,
282 | eepfs_getposition(ip), data, len);
283 | if (status == MSG_OK) {
284 | *written += len;
285 | eepfs_lseek(ip, eepfs_getposition(ip) + len);
286 | }
287 | }
288 |
289 | /**
290 | * @brief Write data to EEPROM.
291 | * @details Only one EEPROM page can be written at once. So fucntion
292 | * splits large data chunks in small EEPROM transactions if needed.
293 | * @note To achieve the maximum effectivity use write operations
294 | * aligned to EEPROM page boundaries.
295 | */
296 | static size_t write(void *ip, const uint8_t *bp, size_t n) {
297 |
298 | size_t len = 0; /* bytes to be written at one trasaction */
299 | uint32_t written; /* total bytes successfully written */
300 | uint16_t pagesize;
301 | uint32_t firstpage;
302 | uint32_t lastpage;
303 |
304 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
305 |
306 | if (n == 0)
307 | return 0;
308 |
309 | n = __clamp_size(ip, n);
310 | if (n == 0)
311 | return 0;
312 |
313 | pagesize = ((EepromFileStream *)ip)->cfg->pagesize;
314 | firstpage = (((EepromFileStream *)ip)->cfg->barrier_low + eepfs_getposition(ip)) / pagesize;
315 | lastpage = (((EepromFileStream *)ip)->cfg->barrier_low + eepfs_getposition(ip) + n - 1) / pagesize;
316 |
317 | written = 0;
318 | /* data fitted in single page */
319 | if (firstpage == lastpage) {
320 | len = n;
321 | __fitted_write(ip, bp, len, &written);
322 | bp += len;
323 | return written;
324 | }
325 | else {
326 | /* write first piece of data to first page boundary */
327 | len = ((firstpage + 1) * pagesize) - eepfs_getposition(ip);
328 | len -= ((EepromFileStream *)ip)->cfg->barrier_low;
329 | __fitted_write(ip, bp, len, &written);
330 | bp += len;
331 |
332 | /* now writes blocks at a size of pages (may be no one) */
333 | while ((n - written) > pagesize) {
334 | len = pagesize;
335 | __fitted_write(ip, bp, len, &written);
336 | bp += len;
337 | }
338 |
339 | /* wrtie tail */
340 | len = n - written;
341 | if (len == 0)
342 | return written;
343 | else {
344 | __fitted_write(ip, bp, len, &written);
345 | }
346 | }
347 |
348 | return written;
349 | }
350 |
351 | /**
352 | * Read some bytes from current position in file. After successful
353 | * read operation the position pointer will be increased by the number
354 | * of read bytes.
355 | */
356 | static size_t read(void *ip, uint8_t *bp, size_t n) {
357 |
358 | msg_t status = MSG_OK;
359 |
360 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
361 |
362 | if (n == 0)
363 | return 0;
364 |
365 | n = __clamp_size(ip, n);
366 | if (n == 0)
367 | return 0;
368 |
369 | /* call low level function */
370 | status = ll_eeprom_read(((SPIEepromFileStream *)ip)->cfg,
371 | eepfs_getposition(ip), bp, n);
372 | if (status != MSG_OK)
373 | return 0;
374 | else {
375 | eepfs_lseek(ip, (eepfs_getposition(ip) + n));
376 | return n;
377 | }
378 | }
379 |
380 | static const struct EepromFileStreamVMT vmt = {
381 | write,
382 | read,
383 | eepfs_put,
384 | eepfs_get,/*
385 | eepfs_close,
386 | eepfs_geterror,
387 | eepfs_getsize,
388 | eepfs_getposition,
389 | eepfs_lseek,*/
390 | };
391 |
392 | EepromDevice eepdev_25xx = {
393 | "25XX",
394 | &vmt
395 | };
396 |
397 | #endif /* EEPROM_DRV_USE_25XX */
398 |
399 | #endif /* HAL_USE_SPI */
400 |
--------------------------------------------------------------------------------
/src/dac_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/HAL - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012,2013,2014 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/HAL
6 |
7 | ChibiOS/HAL is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | /**
22 | * @file dac.c
23 | * @brief DAC Driver code.
24 | *
25 | * @addtogroup DAC
26 | * @{
27 | */
28 |
29 | #include "hal.h"
30 | #include "drivers.h"
31 |
32 | #if DRIVER_USE_DAC || defined(__DOXYGEN__)
33 |
34 | /*===========================================================================*/
35 | /* Driver local definitions. */
36 | /*===========================================================================*/
37 |
38 | /*===========================================================================*/
39 | /* Driver exported variables. */
40 | /*===========================================================================*/
41 |
42 | /*===========================================================================*/
43 | /* Driver local variables. */
44 | /*===========================================================================*/
45 |
46 | /*===========================================================================*/
47 | /* Driver local functions. */
48 | /*===========================================================================*/
49 |
50 | /*===========================================================================*/
51 | /* Driver exported functions. */
52 | /*===========================================================================*/
53 |
54 | /**
55 | * @brief DAC Driver initialization.
56 | * @note This function is implicitly invoked by @p halInit(), there is
57 | * no need to explicitly initialize the driver.
58 | *
59 | * @init
60 | */
61 | void dacInit(void) {
62 |
63 | dac_lld_init();
64 | }
65 |
66 | /**
67 | * @brief Initializes the standard part of a @p DACDriver structure.
68 | *
69 | * @param[out] dacp pointer to the @p DACDriver object
70 | *
71 | * @init
72 | */
73 | void dacObjectInit(DACDriver *dacp) {
74 |
75 | dacp->state = DAC_STOP;
76 | dacp->config = NULL;
77 | #if DAC_USE_WAIT
78 | dacp->thread = NULL;
79 | #endif /* DAC_USE_WAIT */
80 | #if DAC_USE_MUTUAL_EXCLUSION
81 | osalMutexObjectInit(&dacp->mutex);
82 | #endif /* DAC_USE_MUTUAL_EXCLUSION */
83 | #if defined(DAC_DRIVER_EXT_INIT_HOOK)
84 | DAC_DRIVER_EXT_INIT_HOOK(dacp);
85 | #endif
86 | }
87 |
88 | /**
89 | * @brief Configures and activates the DAC peripheral.
90 | *
91 | * @param[in] dacp pointer to the @p DACDriver object
92 | * @param[in] config pointer to the @p DACConfig object
93 | *
94 | * @api
95 | */
96 | void dacStart(DACDriver *dacp, const DACConfig *config) {
97 |
98 | osalDbgCheck((dacp != NULL) && (config != NULL));
99 |
100 | osalSysLock();
101 |
102 | osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
103 | "invalid state");
104 |
105 | dacp->config = config;
106 | dac_lld_start(dacp);
107 | dacp->state = DAC_READY;
108 |
109 | osalSysUnlock();
110 | }
111 |
112 | /**
113 | * @brief Deactivates the DAC peripheral.
114 | * @note Deactivating the peripheral also enforces a release of the slave
115 | * select line.
116 | *
117 | * @param[in] dacp pointer to the @p DACDriver object
118 | *
119 | * @api
120 | */
121 | void dacStop(DACDriver *dacp) {
122 |
123 | osalDbgCheck(dacp != NULL);
124 |
125 | osalSysLock();
126 |
127 | osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
128 | "invalid state");
129 |
130 | dac_lld_stop(dacp);
131 | dacp->state = DAC_STOP;
132 |
133 | osalSysUnlock();
134 | }
135 |
136 | /**
137 | * @brief Starts a single DAC conversion.
138 | * @details Starts a single synchronous conversion operation.
139 | *
140 | * @param[in] dacp pointer to the @p DACDriver object
141 | * @param[in] value the value to output
142 | *
143 | * @api
144 | */
145 | void dacConvertOne(DACDriver *dacp, dacsample_t value) {
146 |
147 | osalDbgCheck(dacp != NULL);
148 | osalDbgAssert((dacp->state == DAC_READY) ||
149 | (dacp->state == DAC_COMPLETE) ||
150 | (dacp->state == DAC_ERROR),
151 | "not ready");
152 |
153 | dacp->state = DAC_ACTIVE;
154 | dac_lld_single_convert(dacp, value);
155 | dacp->state = DAC_READY;
156 | }
157 |
158 | /**
159 | * @brief Starts a DAC conversion.
160 | * @details Starts an asynchronous conversion operation.
161 | * @note The buffer is organized as a matrix of M*N elements where M is the
162 | * channels number configured into the conversion group and N is the
163 | * buffer depth. The samples are sequentially written into the buffer
164 | * with no gaps.
165 | *
166 | * @param[in] dacp pointer to the @p DACDriver object
167 | * @param[in] grpp pointer to a @p DACConversionGroup object
168 | * @param[in] samples pointer to the samples buffer
169 | * @param[in] depth buffer depth (matrix rows number). The buffer depth
170 | * must be one or an even number.
171 | *
172 | * @api
173 | */
174 | void dacStartConversion(DACDriver *dacp,
175 | const DACConversionGroup *grpp,
176 | const dacsample_t *samples,
177 | size_t depth) {
178 |
179 | osalSysLock();
180 | dacStartConversionI(dacp, grpp, samples, depth);
181 | osalSysUnlock();
182 | }
183 |
184 | /**
185 | * @brief Starts a DAC conversion.
186 | * @details Starts an asynchronous conversion operation.
187 | * @post The callbacks associated to the conversion group will be invoked
188 | * on buffer fill and error events.
189 | * @note The buffer is organized as a matrix of M*N elements where M is the
190 | * channels number configured into the conversion group and N is the
191 | * buffer depth. The samples are sequentially written into the buffer
192 | * with no gaps.
193 | *
194 | * @param[in] dacp pointer to the @p DACDriver object
195 | * @param[in] grpp pointer to a @p DACConversionGroup object
196 | * @param[in] samples pointer to the samples buffer
197 | * @param[in] depth buffer depth (matrix rows number). The buffer depth
198 | * must be one or an even number.
199 | *
200 | * @iclass
201 | */
202 | void dacStartConversionI(DACDriver *dacp,
203 | const DACConversionGroup *grpp,
204 | const dacsample_t *samples,
205 | size_t depth) {
206 |
207 | osalDbgCheckClassI();
208 | osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
209 | ((depth == 1) || ((depth & 1) == 0)));
210 | osalDbgAssert((dacp->state == DAC_READY) ||
211 | (dacp->state == DAC_COMPLETE) ||
212 | (dacp->state == DAC_ERROR),
213 | "not ready");
214 |
215 | dacp->samples = samples;
216 | dacp->depth = depth;
217 | dacp->grpp = grpp;
218 | dacp->state = DAC_ACTIVE;
219 | dac_lld_start_conversion(dacp);
220 | }
221 |
222 | /**
223 | * @brief Stops an ongoing conversion.
224 | * @details This function stops the currently ongoing conversion and returns
225 | * the driver in the @p DAC_READY state. If there was no conversion
226 | * being processed then the function does nothing.
227 | *
228 | * @param[in] dacp pointer to the @p DACDriver object
229 | *
230 | * @api
231 | */
232 | void dacStopConversion(DACDriver *dacp) {
233 |
234 | osalDbgCheck(dacp != NULL);
235 |
236 | osalSysLock();
237 |
238 | osalDbgAssert((dacp->state == DAC_READY) ||
239 | (dacp->state == DAC_ACTIVE),
240 | "invalid state");
241 |
242 | if (dacp->state != DAC_READY) {
243 | dac_lld_stop_conversion(dacp);
244 | dacp->grpp = NULL;
245 | dacp->state = DAC_READY;
246 | _dac_reset_s(dacp);
247 | }
248 |
249 | osalSysUnlock();
250 | }
251 |
252 | /**
253 | * @brief Stops an ongoing conversion.
254 | * @details This function stops the currently ongoing conversion and returns
255 | * the driver in the @p DAC_READY state. If there was no conversion
256 | * being processed then the function does nothing.
257 | *
258 | * @param[in] dacp pointer to the @p DACDriver object
259 | *
260 | * @iclass
261 | */
262 | void dacStopConversionI(DACDriver *dacp) {
263 |
264 | osalDbgCheckClassI();
265 | osalDbgCheck(dacp != NULL);
266 | osalDbgAssert((dacp->state == DAC_READY) ||
267 | (dacp->state == DAC_ACTIVE) ||
268 | (dacp->state == DAC_COMPLETE),
269 | "invalid state");
270 |
271 | if (dacp->state != DAC_READY) {
272 | dac_lld_stop_conversion(dacp);
273 | dacp->grpp = NULL;
274 | dacp->state = DAC_READY;
275 | _dac_reset_i(dacp);
276 | }
277 | }
278 |
279 | #if DAC_USE_WAIT || defined(__DOXYGEN__)
280 | /**
281 | * @brief Performs a DAC conversion.
282 | * @details Performs a synchronous conversion operation.
283 | * @note The buffer is organized as a matrix of M*N elements where M is the
284 | * channels number configured into the conversion group and N is the
285 | * buffer depth. The samples are sequentially written into the buffer
286 | * with no gaps.
287 | *
288 | * @param[in] dacp pointer to the @p DACDriver object
289 | * @param[in] grpp pointer to a @p DACConversionGroup object
290 | * @param[out] samples pointer to the samples buffer
291 | * @param[in] depth buffer depth (matrix rows number). The buffer depth
292 | * must be one or an even number.
293 | * @return The operation result.
294 | * @retval MSG_OK Conversion finished.
295 | * @retval MSG_RESET The conversion has been stopped using
296 | * @p acdStopConversion() or @p acdStopConversionI(),
297 | * the result buffer may contain incorrect data.
298 | * @retval MSG_TIMEOUT The conversion has been stopped because an hardware
299 | * error.
300 | *
301 | * @api
302 | */
303 | msg_t dacConvert(DACDriver *dacp,
304 | const DACConversionGroup *grpp,
305 | const dacsample_t *samples,
306 | size_t depth) {
307 | msg_t msg;
308 |
309 | osalSysLock();
310 |
311 | dacStartConversionI(dacp, grpp, samples, depth);
312 | msg = osalThreadSuspendS(&dacp->thread);
313 |
314 | osalSysUnlock();
315 | return msg;
316 | }
317 | #endif /* DAC_USE_WAIT */
318 |
319 | #if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
320 | /**
321 | * @brief Gains exclusive access to the DAC bus.
322 | * @details This function tries to gain ownership to the DAC bus, if the bus
323 | * is already being used then the invoking thread is queued.
324 | * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
325 | * must be enabled.
326 | *
327 | * @param[in] dacp pointer to the @p DACDriver object
328 | *
329 | * @api
330 | */
331 | void dacAcquireBus(DACDriver *dacp) {
332 |
333 | osalDbgCheck(dacp != NULL);
334 |
335 | osalMutexLock(&dacp->mutex);
336 | }
337 |
338 | /**
339 | * @brief Releases exclusive access to the DAC bus.
340 | * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
341 | * must be enabled.
342 | *
343 | * @param[in] dacp pointer to the @p DACDriver object
344 | *
345 | * @api
346 | */
347 | void dacReleaseBus(DACDriver *dacp) {
348 |
349 | osalDbgCheck(dacp != NULL);
350 |
351 | osalMutexUnlock(&dacp->mutex);
352 | }
353 | #endif /* DAC_USE_MUTUAL_EXCLUSION */
354 |
355 | #endif /* DRIVER_USE_DAC */
356 |
357 | /** @} */
358 |
--------------------------------------------------------------------------------
/src/drivers.c:
--------------------------------------------------------------------------------
1 | #include "drivers.h"
2 |
3 | void driversInit(void)
4 | {
5 | #if defined(DRIVER_USE_DAC) && DRIVER_USE_DAC
6 | dacInit();
7 | #endif
8 | #if defined(DRIVER_USE_IWDG) && DRIVER_USE_IWDG
9 | iwdgInit();
10 | #endif
11 | #if defined(DRIVER_USE_TIMCAP) && DRIVER_USE_TIMCAP
12 | timcapInit();
13 | #endif
14 | #if defined(DRIVER_USE_IUART) && DRIVER_USE_IUART
15 | iuartInit();
16 | #endif
17 | #if defined(DRIVER_USE_EICU) && DRIVER_USE_EICU
18 | eicuInit();
19 | #endif
20 | }
21 |
--------------------------------------------------------------------------------
/src/eeprom_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Timon Wong
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | /*
24 | Copyright 2012 Uladzimir Pylinski aka barthess.
25 | You may use this work without restrictions, as long as this notice is included.
26 | The work is provided "as is" without warranty of any kind, neither express nor implied.
27 | */
28 |
29 | #if defined(DRIVER_USE_EEPROM) && DRIVER_USE_EEPROM
30 |
31 | #include "eeprom_driver.h"
32 | #include
33 |
34 | extern EepromDevice eepdev_24xx;
35 | extern EepromDevice eepdev_25xx;
36 |
37 | EepromDevice *__eeprom_drv_table[] = {
38 | /* I2C related. */
39 | #if HAL_USE_I2C
40 |
41 | # if EEPROM_DRV_USE_24XX
42 | &eepdev_24xx,
43 | # endif
44 |
45 | #endif /* HAL_USE_I2C */
46 |
47 | /* SPI related. */
48 | #if HAL_USE_SPI
49 |
50 | # if EEPROM_DRV_USE_25XX
51 | &eepdev_25xx,
52 | # endif
53 |
54 | #endif /* HAL_USE_SPI */
55 | };
56 |
57 |
58 | /**
59 | * @breif Find low level EEPROM device by id.
60 | */
61 | const EepromDevice *EepromFindDevice(const char *name) {
62 |
63 | int i;
64 | const EepromDevice *drv;
65 |
66 | osalDbgCheck(name != NULL);
67 |
68 | for (i = 0; i < EEPROM_DRV_TABLE_SIZE; i++) {
69 | drv = __eeprom_drv_table[i];
70 | if (drv->name != NULL && strcmp(drv->name, name) == 0) {
71 | return drv;
72 | }
73 | }
74 |
75 | return NULL;
76 | }
77 |
78 | /**
79 | * Open EEPROM IC as file and return pointer to the file stream object
80 | * @note Fucntion allways successfully open file. All checking makes
81 | * in read/write functions.
82 | */
83 | EepromFileStream *EepromFileOpen(EepromFileStream *efs,
84 | const EepromFileConfig *eepcfg,
85 | const EepromDevice *eepdev) {
86 |
87 | osalDbgAssert((efs != NULL) && (eepcfg != NULL) && (eepdev != NULL) &&
88 | (eepdev->efsvmt != NULL), "EepromFileOpen");
89 | osalDbgAssert(efs->vmt != eepdev->efsvmt, "file allready opened");
90 | osalDbgAssert(eepcfg->barrier_hi > eepcfg->barrier_low, "wrong barriers");
91 | osalDbgAssert(eepcfg->pagesize < eepcfg->size, "pagesize can not be lager than EEPROM size");
92 | osalDbgAssert(eepcfg->barrier_hi <= eepcfg->size, "barrier out of bounds");
93 |
94 | efs->vmt = eepdev->efsvmt;
95 | efs->cfg = eepcfg;
96 | efs->errors = FILE_OK;
97 | efs->position = 0;
98 | return (EepromFileStream *)efs;
99 | }
100 |
101 | uint8_t EepromReadByte(EepromFileStream *efs) {
102 |
103 | uint8_t buf;
104 | chFileStreamRead(efs, &buf, sizeof(buf));
105 | return buf;
106 | }
107 |
108 | uint16_t EepromReadHalfword(EepromFileStream *efs) {
109 |
110 | uint16_t buf;
111 | chFileStreamRead(efs, (uint8_t *)&buf, sizeof(buf));
112 | return buf;
113 | }
114 |
115 | uint32_t EepromReadWord(EepromFileStream *efs) {
116 |
117 | uint32_t buf;
118 | chFileStreamRead(efs, (uint8_t *)&buf, sizeof(buf));
119 | return buf;
120 | }
121 |
122 | size_t EepromWriteByte(EepromFileStream *efs, uint8_t data) {
123 |
124 | return chFileStreamWrite(efs, &data, sizeof(data));
125 | }
126 |
127 | size_t EepromWriteHalfword(EepromFileStream *efs, uint16_t data) {
128 |
129 | return chFileStreamWrite(efs, (uint8_t *)&data, sizeof(data));
130 | }
131 |
132 | size_t EepromWriteWord(EepromFileStream *efs, uint32_t data) {
133 |
134 | return chFileStreamWrite(efs, (uint8_t *)&data, sizeof(data));
135 | }
136 |
137 | fileoffset_t eepfs_getsize(void *ip) {
138 |
139 | uint32_t h, l;
140 |
141 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL) &&
142 | (((EepromFileStream *)ip)->cfg != NULL));
143 |
144 | h = ((EepromFileStream *)ip)->cfg->barrier_hi;
145 | l = ((EepromFileStream *)ip)->cfg->barrier_low;
146 | return h - l;
147 | }
148 |
149 | fileoffset_t eepfs_getposition(void *ip) {
150 |
151 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
152 |
153 | return ((EepromFileStream *)ip)->position;
154 | }
155 |
156 | fileoffset_t eepfs_lseek(void *ip, fileoffset_t offset) {
157 |
158 | uint32_t size;
159 |
160 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
161 |
162 | size = eepfs_getsize(ip);
163 | if (offset > size)
164 | offset = size;
165 | ((EepromFileStream *)ip)->position = offset;
166 | return offset;
167 | }
168 |
169 | uint32_t eepfs_close(void *ip) {
170 |
171 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
172 |
173 | ((EepromFileStream *)ip)->errors = FILE_OK;
174 | ((EepromFileStream *)ip)->position = 0;
175 | ((EepromFileStream *)ip)->vmt = NULL;
176 | ((EepromFileStream *)ip)->cfg = NULL;
177 | return FILE_OK;
178 | }
179 |
180 | int eepfs_geterror(void *ip) {
181 |
182 | osalDbgCheck((ip != NULL) && (((EepromFileStream *)ip)->vmt != NULL));
183 | return ((EepromFileStream *)ip)->errors;
184 | }
185 |
186 | msg_t eepfs_put(void *ip, uint8_t b) {
187 |
188 | (void)ip;
189 | (void)b;
190 | return 0;
191 | }
192 |
193 | msg_t eepfs_get(void *ip) {
194 |
195 | (void)ip;
196 | return 0;
197 | }
198 |
199 | #endif /* #if defined(DRIVER_USE_EEPROM) && DRIVER_USE_EEPROM */
--------------------------------------------------------------------------------
/src/eicu_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | /*
17 | Rewritten by Emil Fresk (1/5 - 2014) for extended input capture
18 | functionallity. And fix for spourious callbacks in the interrupt handler.
19 | */
20 |
21 | /* *
22 | *
23 | * Hardware Abstraction Layer for Extended Input Capture Unit
24 | *
25 | * */
26 |
27 | #include "ch.h"
28 | #include "hal.h"
29 | #include "eicu_driver.h" /* Should be in hal.h but is not a part of ChibiOS */
30 |
31 | #if DRIVER_USE_EICU || defined(__DOXYGEN__)
32 |
33 |
34 | /*===========================================================================*/
35 | /* Driver local definitions. */
36 | /*===========================================================================*/
37 |
38 | /*===========================================================================*/
39 | /* Driver exported variables. */
40 | /*===========================================================================*/
41 |
42 | /*===========================================================================*/
43 | /* Driver local variables and types. */
44 | /*===========================================================================*/
45 |
46 | /*===========================================================================*/
47 | /* Driver local functions. */
48 | /*===========================================================================*/
49 |
50 | /*===========================================================================*/
51 | /* Driver exported functions. */
52 | /*===========================================================================*/
53 |
54 | /**
55 | * @brief EICU Driver initialization.
56 | *
57 | * @init
58 | */
59 |
60 | void eicuInit(void) {
61 |
62 | eicu_lld_init();
63 | }
64 |
65 | /**
66 | * @brief Initializes the standard part of a @p EICUDriver structure.
67 | *
68 | * @param[out] eicup Pointer to the @p EICUDriver object
69 | *
70 | * @init
71 | */
72 | void eicuObjectInit(EICUDriver *eicup) {
73 |
74 | eicup->state = EICU_STOP;
75 | eicup->config = NULL;
76 | }
77 |
78 | /**
79 | * @brief Configures and activates the EICU peripheral.
80 | *
81 | * @param[in] eicup Pointer to the @p EICUDriver object
82 | * @param[in] config Pointer to the @p EICUConfig object
83 | *
84 | * @api
85 | */
86 | void eicuStart(EICUDriver *eicup, const EICUConfig *config) {
87 |
88 | osalDbgCheck((eicup != NULL) && (config != NULL));
89 |
90 | osalSysLock();
91 | osalDbgAssert((eicup->state == EICU_STOP) || (eicup->state == EICU_READY),
92 | "invalid state");
93 | eicup->config = config;
94 | eicu_lld_start(eicup);
95 | eicup->state = EICU_READY;
96 | osalSysUnlock();
97 | }
98 |
99 | /**
100 | * @brief Deactivates the EICU peripheral.
101 | *
102 | * @param[in] eicup Pointer to the @p EICUDriver object
103 | *
104 | * @api
105 | */
106 | void eicuStop(EICUDriver *eicup) {
107 |
108 | osalDbgCheck(eicup != NULL);
109 |
110 | osalSysLock();
111 | osalDbgAssert((eicup->state == EICU_STOP) || (eicup->state == EICU_READY),
112 | "invalid state");
113 | eicu_lld_stop(eicup);
114 | eicup->state = EICU_STOP;
115 | osalSysUnlock();
116 | }
117 |
118 | /**
119 | * @brief Enables the extended input capture.
120 | *
121 | * @param[in] eicup Pointer to the @p EICUDriver object
122 | *
123 | * @api
124 | */
125 | void eicuEnable(EICUDriver *eicup) {
126 |
127 | osalDbgCheck(eicup != NULL);
128 |
129 | osalSysLock();
130 | osalDbgAssert(eicup->state == EICU_READY, "invalid state");
131 | eicu_lld_enable(eicup);
132 | eicup->state = EICU_WAITING;
133 | osalSysUnlock();
134 | }
135 |
136 | /**
137 | * @brief Disables the extended input capture.
138 | *
139 | * @param[in] eicup Pointer to the @p EICUDriver object
140 | *
141 | * @api
142 | */
143 | void eicuDisable(EICUDriver *eicup) {
144 |
145 | osalDbgCheck(eicup != NULL);
146 |
147 | osalSysLock();
148 | osalDbgAssert((eicup->state == EICU_READY) || (eicup->state == EICU_WAITING) ||
149 | (eicup->state == EICU_ACTIVE) || (eicup->state == EICU_IDLE),
150 | "invalid state");
151 | eicu_lld_disable(eicup);
152 | eicup->state = EICU_READY;
153 | osalSysUnlock();
154 | }
155 |
156 | #endif /* DRIVER_USE_EICU */
--------------------------------------------------------------------------------
/src/iuart_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012,2013 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | ---
21 |
22 | A special exception to the GPL can be applied should you wish to distribute
23 | a combined work that includes ChibiOS/RT, without being obliged to provide
24 | the source code for any proprietary components. See the file exception.txt
25 | for full details of how and when the exception can be applied.
26 | */
27 |
28 | /**
29 | * @file iuart.c
30 | * @brief IUART Driver code.
31 | *
32 | * @addtogroup IUART
33 | * @{
34 | */
35 |
36 | #include "ch.h"
37 | #include "hal.h"
38 |
39 | #include "iuart_driver.h"
40 |
41 | #if DRIVER_USE_IUART || defined(__DOXYGEN__)
42 |
43 | /*===========================================================================*/
44 | /* Driver local definitions. */
45 | /*===========================================================================*/
46 |
47 | /*===========================================================================*/
48 | /* Driver exported variables. */
49 | /*===========================================================================*/
50 |
51 | /*===========================================================================*/
52 | /* Driver local variables and types. */
53 | /*===========================================================================*/
54 |
55 | /*===========================================================================*/
56 | /* Driver local functions. */
57 | /*===========================================================================*/
58 |
59 | /*===========================================================================*/
60 | /* Driver exported functions. */
61 | /*===========================================================================*/
62 |
63 | /**
64 | * @brief IUART Driver initialization.
65 | * @note This function is implicitly invoked by @p halInit(), there is
66 | * no need to explicitly initialize the driver.
67 | *
68 | * @init
69 | */
70 | void iuartInit(void) {
71 |
72 | iuart_lld_init();
73 | }
74 |
75 | /**
76 | * @brief Initializes the standard part of a @p IUARTDriver structure.
77 | *
78 | * @param[out] iuartp pointer to the @p IUARTDriver object
79 | *
80 | * @init
81 | */
82 | void iuartObjectInit(IUARTDriver *iuartp) {
83 |
84 | iuartp->state = IUART_STOP;
85 | iuartp->txstate = IUART_TX_IDLE;
86 | iuartp->rxstate = IUART_RX_IDLE;
87 | iuartp->config = NULL;
88 | /* Optional, user-defined initializer.*/
89 | #if defined(IUART_DRIVER_EXT_INIT_HOOK)
90 | IUART_DRIVER_EXT_INIT_HOOK(iuartp);
91 | #endif
92 | }
93 |
94 | /**
95 | * @brief Configures and activates the IUART peripheral.
96 | *
97 | * @param[in] iuartp pointer to the @p IUARTDriver object
98 | * @param[in] config pointer to the @p IUARTConfig object
99 | *
100 | * @api
101 | */
102 | void iuartStart(IUARTDriver *iuartp, const IUARTConfig *config) {
103 |
104 | osalDbgCheck((iuartp != NULL) && (config != NULL));
105 |
106 | osalSysLock();
107 | osalDbgAssert((iuartp->state == IUART_STOP) || (iuartp->state == IUART_READY),
108 | "invalid state");
109 |
110 | iuartp->config = config;
111 | iuart_lld_start(iuartp);
112 | iuartp->state = IUART_READY;
113 | osalSysUnlock();
114 | }
115 |
116 | /**
117 | * @brief Deactivates the IUART peripheral.
118 | *
119 | * @param[in] iuartp pointer to the @p IUARTDriver object
120 | *
121 | * @api
122 | */
123 | void iuartStop(IUARTDriver *iuartp) {
124 |
125 | osalDbgCheck(iuartp != NULL);
126 |
127 | osalSysLock();
128 | osalDbgAssert((iuartp->state == IUART_STOP) || (iuartp->state == IUART_READY),
129 | "invalid state");
130 |
131 | iuart_lld_stop(iuartp);
132 | iuartp->state = IUART_STOP;
133 | iuartp->txstate = IUART_TX_IDLE;
134 | iuartp->rxstate = IUART_RX_IDLE;
135 | osalSysUnlock();
136 | }
137 |
138 | /**
139 | * @brief Starts a transmission on the IUART peripheral.
140 | * @note The buffers are organized as uint8_t arrays for data sizes below
141 | * or equal to 8 bits else it is organized as uint16_t arrays.
142 | *
143 | * @param[in] iuartp pointer to the @p IUARTDriver object
144 | * @param[in] n number of data frames to send
145 | * @param[in] txbuf the pointer to the transmit buffer
146 | *
147 | * @api
148 | */
149 | void iuartStartSend(IUARTDriver *iuartp, size_t n, const void *txbuf) {
150 |
151 | osalDbgCheck((iuartp != NULL) && (n > 0) && (txbuf != NULL));
152 |
153 | osalSysLock();
154 | osalDbgAssert(iuartp->state == IUART_READY,
155 | "is active");
156 | osalDbgAssert(iuartp->txstate != IUART_TX_ACTIVE,
157 | "tx active");
158 |
159 | iuart_lld_start_send(iuartp, n, txbuf);
160 | iuartp->txstate = IUART_TX_ACTIVE;
161 | osalSysUnlock();
162 | }
163 |
164 | /**
165 | * @brief Starts a transmission on the IUART peripheral.
166 | * @note The buffers are organized as uint8_t arrays for data sizes below
167 | * or equal to 8 bits else it is organized as uint16_t arrays.
168 | * @note This function has to be invoked from a lock zone.
169 | *
170 | * @param[in] iuartp pointer to the @p IUARTDriver object
171 | * @param[in] n number of data frames to send
172 | * @param[in] txbuf the pointer to the transmit buffer
173 | *
174 | * @iclass
175 | */
176 | void iuartStartSendI(IUARTDriver *iuartp, size_t n, const void *txbuf) {
177 |
178 | osalDbgCheckClassI();
179 | osalDbgCheck((iuartp != NULL) && (n > 0) && (txbuf != NULL));
180 | osalDbgAssert(iuartp->state == IUART_READY,
181 | "is active");
182 | osalDbgAssert(iuartp->txstate != IUART_TX_ACTIVE,
183 | "tx active");
184 |
185 | iuart_lld_start_send(iuartp, n, txbuf);
186 | iuartp->txstate = IUART_TX_ACTIVE;
187 | }
188 |
189 | /**
190 | * @brief Stops any ongoing transmission.
191 | * @note Stopping a transmission also suppresses the transmission callbacks.
192 | *
193 | * @param[in] iuartp pointer to the @p IUARTDriver object
194 | *
195 | * @return The number of data frames not transmitted by the
196 | * stopped transmit operation.
197 | * @retval 0 There was no transmit operation in progress.
198 | *
199 | * @api
200 | */
201 | size_t iuartStopSend(IUARTDriver *iuartp) {
202 | size_t n;
203 |
204 | osalDbgCheck(iuartp != NULL);
205 |
206 | osalSysLock();
207 | osalDbgAssert(iuartp->state == IUART_READY, "not active");
208 |
209 | if (iuartp->txstate == IUART_TX_ACTIVE) {
210 | n = iuart_lld_stop_send(iuartp);
211 | iuartp->txstate = IUART_TX_IDLE;
212 | }
213 | else
214 | n = 0;
215 | osalSysUnlock();
216 | return n;
217 | }
218 |
219 | /**
220 | * @brief Stops any ongoing transmission.
221 | * @note Stopping a transmission also suppresses the transmission callbacks.
222 | * @note This function has to be invoked from a lock zone.
223 | *
224 | * @param[in] iuartp pointer to the @p IUARTDriver object
225 | *
226 | * @return The number of data frames not transmitted by the
227 | * stopped transmit operation.
228 | * @retval 0 There was no transmit operation in progress.
229 | *
230 | * @iclass
231 | */
232 | size_t iuartStopSendI(IUARTDriver *iuartp) {
233 |
234 | osalDbgCheckClassI();
235 | osalDbgCheck(iuartp != NULL);
236 | osalDbgAssert(iuartp->state == IUART_READY, "not active");
237 |
238 | if (iuartp->txstate == IUART_TX_ACTIVE) {
239 | size_t n = iuart_lld_stop_send(iuartp);
240 | iuartp->txstate = IUART_TX_IDLE;
241 | return n;
242 | }
243 | return 0;
244 | }
245 |
246 | /**
247 | * @brief Starts a receive operation on the IUART peripheral.
248 | * @note The buffers are organized as uint8_t arrays for data sizes below
249 | * or equal to 8 bits else it is organized as uint16_t arrays.
250 | *
251 | * @param[in] iuartp pointer to the @p IUARTDriver object
252 | * @param[in] n number of data frames to send
253 | * @param[in] rxbuf the pointer to the receive buffer
254 | *
255 | * @api
256 | */
257 | void iuartStartReceive(IUARTDriver *iuartp, size_t n, void *rxbuf) {
258 |
259 | osalDbgCheck((iuartp != NULL) && (n > 0) && (rxbuf != NULL));
260 |
261 | osalSysLock();
262 | osalDbgAssert(iuartp->state == IUART_READY,
263 | "is active");
264 | osalDbgAssert(iuartp->rxstate != IUART_RX_ACTIVE,
265 | "rx active");
266 |
267 | iuart_lld_start_receive(iuartp, n, rxbuf);
268 | iuartp->rxstate = IUART_RX_ACTIVE;
269 | osalSysUnlock();
270 | }
271 |
272 | /**
273 | * @brief Starts a receive operation on the IUART peripheral.
274 | * @note The buffers are organized as uint8_t arrays for data sizes below
275 | * or equal to 8 bits else it is organized as uint16_t arrays.
276 | * @note This function has to be invoked from a lock zone.
277 | *
278 | * @param[in] iuartp pointer to the @p IUARTDriver object
279 | * @param[in] n number of data frames to send
280 | * @param[out] rxbuf the pointer to the receive buffer
281 | *
282 | * @iclass
283 | */
284 | void iuartStartReceiveI(IUARTDriver *iuartp, size_t n, void *rxbuf) {
285 |
286 | osalDbgCheckClassI();
287 | osalDbgCheck((iuartp != NULL) && (n > 0) && (rxbuf != NULL));
288 | osalDbgAssert(iuartp->state == IUART_READY,
289 | "is active");
290 | osalDbgAssert(iuartp->rxstate != IUART_RX_ACTIVE,
291 | "rx active");
292 |
293 | iuart_lld_start_receive(iuartp, n, rxbuf);
294 | iuartp->rxstate = IUART_RX_ACTIVE;
295 | }
296 |
297 | /**
298 | * @brief Stops any ongoing receive operation.
299 | * @note Stopping a receive operation also suppresses the receive callbacks.
300 | *
301 | * @param[in] iuartp pointer to the @p IUARTDriver object
302 | *
303 | * @return The number of data frames not received by the
304 | * stopped receive operation.
305 | * @retval 0 There was no receive operation in progress.
306 | *
307 | * @api
308 | */
309 | size_t iuartStopReceive(IUARTDriver *iuartp) {
310 | size_t n;
311 |
312 | osalDbgCheck(iuartp != NULL);
313 |
314 | osalSysLock();
315 | osalDbgAssert(iuartp->state == IUART_READY,
316 | "not active");
317 |
318 | if (iuartp->rxstate == IUART_RX_ACTIVE) {
319 | n = iuart_lld_stop_receive(iuartp);
320 | iuartp->rxstate = IUART_RX_IDLE;
321 | }
322 | else
323 | n = 0;
324 | osalSysUnlock();
325 | return n;
326 | }
327 |
328 | /**
329 | * @brief Stops any ongoing receive operation.
330 | * @note Stopping a receive operation also suppresses the receive callbacks.
331 | * @note This function has to be invoked from a lock zone.
332 | *
333 | * @param[in] iuartp pointer to the @p IUARTDriver object
334 | *
335 | * @return The number of data frames not received by the
336 | * stopped receive operation.
337 | * @retval 0 There was no receive operation in progress.
338 | *
339 | * @iclass
340 | */
341 | size_t iuartStopReceiveI(IUARTDriver *iuartp) {
342 |
343 | osalDbgCheckClassI();
344 | osalDbgCheck(iuartp != NULL);
345 | osalDbgAssert(iuartp->state == IUART_READY,
346 | "not active");
347 |
348 | if (iuartp->rxstate == IUART_RX_ACTIVE) {
349 | size_t n = iuart_lld_stop_receive(iuartp);
350 | iuartp->rxstate = IUART_RX_IDLE;
351 | return n;
352 | }
353 | return 0;
354 | }
355 |
356 | #endif /* DRIVER_USE_IUART */
357 |
358 | /** @} */
359 |
--------------------------------------------------------------------------------
/src/iwdg_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | ---
21 |
22 | A special exception to the GPL can be applied should you wish to distribute
23 | a combined work that includes ChibiOS/RT, without being obliged to provide
24 | the source code for any proprietary components. See the file exception.txt
25 | for full details of how and when the exception can be applied.
26 | */
27 |
28 | /**
29 | * @file iwdg.c
30 | * @brief IWDG Driver code.
31 | *
32 | * @addtogroup IWDG
33 | * @{
34 | */
35 |
36 | #include "ch.h"
37 | #include "hal.h"
38 | #include "iwdg_driver.h"
39 |
40 | #if DRIVER_USE_IWDG || defined(__DOXYGEN__)
41 |
42 | /*===========================================================================*/
43 | /* Driver local definitions. */
44 | /*===========================================================================*/
45 |
46 | /*===========================================================================*/
47 | /* Driver exported variables. */
48 | /*===========================================================================*/
49 |
50 | /*===========================================================================*/
51 | /* Driver local variables. */
52 | /*===========================================================================*/
53 |
54 | /*===========================================================================*/
55 | /* Driver local functions. */
56 | /*===========================================================================*/
57 |
58 | /*===========================================================================*/
59 | /* Driver exported functions. */
60 | /*===========================================================================*/
61 |
62 | /**
63 | * @brief IWDG Driver initialization.
64 | * @note This function is implicitly invoked by @p halInit(), there is
65 | * no need to explicitly initialize the driver.
66 | *
67 | * @init
68 | */
69 | void iwdgInit(void)
70 | {
71 | iwdg_lld_init();
72 | }
73 |
74 |
75 | /**
76 | * @brief Configures and activates the IWDG peripheral.
77 | *
78 | * @param[in] iwdgp pointer to the @p IWDGDriver object
79 | * @param[in] config pointer to the @p IWDGConfig object
80 | *
81 | * @api
82 | */
83 | void iwdgStart( IWDGDriver *iwdgp, const IWDGConfig *config )
84 | {
85 | osalDbgCheck((iwdgp != NULL) && (config != NULL));
86 |
87 | osalSysLock();
88 | iwdg_lld_start( iwdgp, config );
89 | iwdgp->state = IWDG_READY;
90 | osalSysUnlock();
91 | }
92 |
93 | /**
94 | * @brief Resets IWDG's counter.
95 | *
96 | * @param[in] iwdgp pointer to the @p IWDGDriver object
97 | *
98 | * @api
99 | */
100 | void iwdgReset( IWDGDriver *iwdgp )
101 | {
102 | osalDbgCheck( iwdgp != NULL);
103 |
104 | //osalSysLock();
105 | iwdg_lld_reset( iwdgp );
106 | //osalSysUnlock();
107 | }
108 |
109 | #endif /* DRIVER_USE_IWDG */
110 |
111 | /** @} */
112 |
--------------------------------------------------------------------------------
/src/timcap_driver.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012,2013 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | /**
22 | * @file timcap.c
23 | * @brief TIMCAP Driver code.
24 | *
25 | * @addtogroup TIMCAP
26 | * @{
27 | */
28 |
29 | #include "timcap_driver.h"
30 |
31 | #if DRIVER_USE_TIMCAP || defined(__DOXYGEN__)
32 |
33 |
34 | /*===========================================================================*/
35 | /* Driver local definitions. */
36 | /*===========================================================================*/
37 |
38 | /*===========================================================================*/
39 | /* Driver exported variables. */
40 | /*===========================================================================*/
41 |
42 | /*===========================================================================*/
43 | /* Driver local variables and types. */
44 | /*===========================================================================*/
45 |
46 | /*===========================================================================*/
47 | /* Driver local functions. */
48 | /*===========================================================================*/
49 |
50 | /*===========================================================================*/
51 | /* Driver exported functions. */
52 | /*===========================================================================*/
53 |
54 | /**
55 | * @brief TIMCAP Driver initialization.
56 | * @note This function is implicitly invoked by @p halInit(), there is
57 | * no need to explicitly initialize the driver.
58 | *
59 | * @init
60 | */
61 | void timcapInit(void) {
62 |
63 | timcap_lld_init();
64 | }
65 |
66 | /**
67 | * @brief Initializes the standard part of a @p TIMCAPDriver structure.
68 | *
69 | * @param[out] timcapp pointer to the @p TIMCAPDriver object
70 | *
71 | * @init
72 | */
73 | void timcapObjectInit(TIMCAPDriver *timcapp) {
74 |
75 | timcapp->state = TIMCAP_STOP;
76 | timcapp->config = NULL;
77 | }
78 |
79 | /**
80 | * @brief Configures and activates the TIMCAP peripheral.
81 | *
82 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
83 | * @param[in] config pointer to the @p TIMCAPConfig object
84 | *
85 | * @api
86 | */
87 | void timcapStart(TIMCAPDriver *timcapp, const TIMCAPConfig *config) {
88 |
89 | osalDbgCheck((timcapp != NULL) && (config != NULL));
90 |
91 | osalSysLock();
92 | osalDbgAssert((timcapp->state == TIMCAP_STOP) || (timcapp->state == TIMCAP_READY),
93 | "invalid state");
94 | timcapp->config = config;
95 | timcap_lld_start(timcapp);
96 | timcapp->state = TIMCAP_READY;
97 | osalSysUnlock();
98 | }
99 |
100 | /**
101 | * @brief Deactivates the TIMCAP peripheral.
102 | *
103 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
104 | *
105 | * @api
106 | */
107 | void timcapStop(TIMCAPDriver *timcapp) {
108 |
109 | osalDbgCheck(timcapp != NULL);
110 |
111 | osalSysLock();
112 | osalDbgAssert((timcapp->state == TIMCAP_STOP) || (timcapp->state == TIMCAP_READY),
113 | "invalid state");
114 | timcap_lld_stop(timcapp);
115 | timcapp->state = TIMCAP_STOP;
116 | osalSysUnlock();
117 | }
118 |
119 | /**
120 | * @brief Enables the input capture.
121 | *
122 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
123 | *
124 | * @api
125 | */
126 | void timcapEnable(TIMCAPDriver *timcapp) {
127 |
128 | osalDbgCheck(timcapp != NULL);
129 |
130 | osalSysLock();
131 | osalDbgAssert(timcapp->state == TIMCAP_READY, "invalid state");
132 | timcap_lld_enable(timcapp);
133 | timcapp->state = TIMCAP_WAITING;
134 | osalSysUnlock();
135 | }
136 |
137 | /**
138 | * @brief Disables the input capture.
139 | *
140 | * @param[in] timcapp pointer to the @p TIMCAPDriver object
141 | *
142 | * @api
143 | */
144 | void timcapDisable(TIMCAPDriver *timcapp) {
145 |
146 | osalDbgCheck(timcapp != NULL);
147 |
148 | osalSysLock();
149 | osalDbgAssert((timcapp->state == TIMCAP_READY) || (timcapp->state == TIMCAP_WAITING) ||
150 | (timcapp->state == TIMCAP_ACTIVE) || (timcapp->state == TIMCAP_IDLE),
151 | "invalid state");
152 | timcap_lld_disable(timcapp);
153 | timcapp->state = TIMCAP_READY;
154 | osalSysUnlock();
155 | }
156 |
157 | #endif /* DRIVER_USE_TIMCAP */
158 |
159 | /** @} */
160 |
--------------------------------------------------------------------------------
/stm32/dac_driver_lld.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/HAL - Copyright (C) 2006-2014 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | /**
18 | * @file STM32/DACv1/dac_lld.c
19 | * @brief STM32 DAC subsystem low level driver source.
20 | *
21 | * @addtogroup DAC
22 | * @{
23 | */
24 |
25 | #include "hal.h"
26 | #include "drivers.h"
27 | #include "dac_driver_lld.h"
28 |
29 | #if DRIVER_USE_DAC || defined(__DOXYGEN__)
30 |
31 | /*===========================================================================*/
32 | /* Driver local definitions. */
33 | /*===========================================================================*/
34 |
35 | #if !defined(DAC1)
36 | #define DAC1 DAC
37 | #undef rccEnableDAC1
38 | #undef rccDisableDAC1
39 | #define rccEnableDAC1 rccEnableDAC
40 | #define rccDisableDAC1 rccDisableDAC
41 | #endif
42 |
43 | #define DAC_CHN1_DMA_CHANNEL \
44 | STM32_DMA_GETCHANNEL(STM32_DAC_CHN1_DMA_STREAM, \
45 | STM32_DAC_CHN1_DMA_CHN)
46 |
47 | #define DAC_CHN2_DMA_CHANNEL \
48 | STM32_DMA_GETCHANNEL(STM32_DAC_CHN2_DMA_STREAM, \
49 | STM32_DAC_CHN2_DMA_CHN)
50 |
51 | #define DAC_CHN3_DMA_CHANNEL \
52 | STM32_DMA_GETCHANNEL(STM32_DAC_CHN3_DMA_STREAM, \
53 | STM32_DAC_CHN3_DMA_CHN)
54 |
55 | /*===========================================================================*/
56 | /* Driver exported variables. */
57 | /*===========================================================================*/
58 |
59 | /** @brief CHN1 driver identifier.*/
60 | #if STM32_DAC_USE_CHN1 || defined(__DOXYGEN__)
61 | DACDriver DACD1;
62 | #endif
63 |
64 | /** @brief CHN2 driver identifier.*/
65 | #if STM32_DAC_USE_CHN2 || defined(__DOXYGEN__)
66 | DACDriver DACD2;
67 | #endif
68 |
69 | /** @brief CHN3 driver identifier.*/
70 | #if STM32_DAC_USE_CHN3 || defined(__DOXYGEN__)
71 | DACDriver DACD3;
72 | #endif
73 |
74 | /*===========================================================================*/
75 | /* Driver local variables. */
76 | /*===========================================================================*/
77 |
78 | /*===========================================================================*/
79 | /* Driver local functions. */
80 | /*===========================================================================*/
81 |
82 | /**
83 | * @brief Shared end/half-of-tx service routine.
84 | *
85 | * @param[in] dacp pointer to the @p DACDriver object
86 | * @param[in] flags pre-shifted content of the ISR register
87 | */
88 | static void dac_lld_serve_tx_interrupt(DACDriver *dacp, uint32_t flags) {
89 |
90 | #if defined(STM32_DAC_DMA_ERROR_HOOK)
91 | (void)dacp;
92 | if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
93 | /* DMA errors handling.*/
94 | //~ _dac_isr_error_code(dacp, flags);
95 | }
96 | else {
97 | if ((flags & STM32_DMA_ISR_HTIF) != 0) {
98 | /* Half transfer processing.*/
99 | //~ _dac_isr_half_code(dacp);
100 | }
101 | if ((flags & STM32_DMA_ISR_TCIF) != 0) {
102 | /* Transfer complete processing.*/
103 | //~ _dac_isr_full_code(dacp);
104 | }
105 | }
106 | #else
107 | (void)dacp;
108 | (void)flags;
109 | #endif
110 | }
111 |
112 | /*===========================================================================*/
113 | /* Driver interrupt handlers. */
114 | /*===========================================================================*/
115 |
116 | /*===========================================================================*/
117 | /* Driver exported functions. */
118 | /*===========================================================================*/
119 |
120 | /**
121 | * @brief Low level DAC driver initialization.
122 | *
123 | * @notapi
124 | */
125 | void dac_lld_init(void) {
126 |
127 | #if STM32_DAC_USE_CHN1
128 | dacObjectInit(&DACD1);
129 | DACD1.dac = DAC1;
130 | DACD1.tim = STM32_TIM6;
131 | DACD1.irqprio = STM32_DAC_CHN1_IRQ_PRIORITY;
132 | DACD1.dma = STM32_DMA_STREAM(STM32_DAC_CHN1_DMA_STREAM);
133 | DACD1.dmamode = STM32_DMA_CR_CHSEL(DAC_CHN1_DMA_CHANNEL) | \
134 | STM32_DMA_CR_PL(STM32_DAC_CHN1_DMA_PRIORITY) | \
135 | STM32_DMA_CR_DIR_M2P | \
136 | STM32_DMA_CR_DMEIE | \
137 | STM32_DMA_CR_TEIE | \
138 | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE;
139 | #endif
140 |
141 | #if STM32_DAC_USE_CHN2
142 | dacObjectInit(&DACD2);
143 | DACD2.dac = DAC1;
144 | DACD2.tim = STM32_TIM7;
145 | DACD2.irqprio = STM32_DAC_CHN2_IRQ_PRIORITY;
146 | DACD2.dma = STM32_DMA_STREAM(STM32_DAC_CHN2_DMA_STREAM);
147 | DACD2.dmamode = STM32_DMA_CR_CHSEL(DAC_CHN2_DMA_CHANNEL) | \
148 | STM32_DMA_CR_PL(STM32_DAC_CHN2_DMA_PRIORITY) | \
149 | STM32_DMA_CR_DIR_M2P | \
150 | STM32_DMA_CR_DMEIE | \
151 | STM32_DMA_CR_TEIE | \
152 | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE;
153 | #endif
154 |
155 | #if STM32_DAC_USE_CHN3
156 | dacObjectInit(&DACD3);
157 | DACD3.dac = DAC2;
158 | DACD3.tim = STM32_TIM18;
159 | DACD3.irqprio = STM32_DAC_CHN3_IRQ_PRIORITY;
160 | DACD3.dma = STM32_DMA_STREAM(STM32_DAC_CHN3_DMA_STREAM);
161 | DACD3.dmamode = STM32_DMA_CR_CHSEL(DAC_CHN3_DMA_CHANNEL) | \
162 | STM32_DMA_CR_PL(STM32_DAC_CHN2_DMA_PRIORITY) | \
163 | STM32_DMA_CR_DIR_M2P | \
164 | STM32_DMA_CR_DMEIE | \
165 | STM32_DMA_CR_TEIE | \
166 | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE;
167 | #endif
168 | }
169 |
170 | /**
171 | * @brief Configures and activates the DAC peripheral.
172 | *
173 | * @param[in] dacp pointer to the @p DACDriver object
174 | *
175 | * @notapi
176 | */
177 | void dac_lld_start(DACDriver *dacp) {
178 |
179 | #if STM32_DAC_USE_CHN1
180 | if (&DACD1 == dacp) {
181 | rccEnableDAC1(FALSE);
182 | }
183 | #endif
184 | #if STM32_DAC_USE_CHN2
185 | if (&DACD2 == dacp) {
186 | rccEnableDAC1(FALSE);
187 | }
188 | #endif
189 | #if STM32_DAC_USE_CHN3
190 | if (&DACD3 == dacp) {
191 | rccEnableDAC2(FALSE);
192 | }
193 | #endif
194 | }
195 |
196 | /**
197 | * @brief Deactivates the DAC peripheral.
198 | *
199 | * @param[in] dacp pointer to the @p DACDriver object
200 | *
201 | * @notapi
202 | */
203 | void dac_lld_stop(DACDriver *dacp) {
204 |
205 | #if STM32_DAC_USE_CHN1
206 | if (&DACD1 == dacp) {
207 | dacp->dac->CR &= ~STM32_DAC_CR_EN; /* DAC1 disable.*/
208 | }
209 | #endif
210 | #if STM32_DAC_USE_CHN2
211 | if (&DACD2 == dacp) {
212 | dacp->dac->CR &= ~STM32_DAC_CR_EN << 16; /* DAC1 disable.*/
213 | }
214 | #endif
215 | #if STM32_DAC_USE_CHN3
216 | if (&DACD3 == dacp) {
217 | dacp->dac->CR &= ~STM32_DAC_CR_EN; /* DAC2 disable.*/
218 | rccDisableDAC2(FALSE); /* DAC Clock disable.*/
219 | }
220 | #endif
221 |
222 | if (!(DAC1->CR & (STM32_DAC_CR_EN | STM32_DAC_CR_EN << 16))) {
223 | /* DAC Clock disable only if all channels are off.*/
224 | rccDisableDAC1(FALSE);
225 | }
226 | }
227 |
228 | /**
229 | * @brief Starts a single conversion. Does not require DMA or Timers.
230 | *
231 | * @param[in] dacp pointer to the @p DACDriver object
232 | * @param[in] value the value to output
233 | *
234 | * @notapi
235 | */
236 | void dac_lld_single_convert(DACDriver *dacp, dacsample_t value) {
237 |
238 | uint32_t dataoffset = 0;
239 | uint32_t regshift = 0;
240 | volatile dacsample_t* data = NULL;
241 |
242 | #if STM32_DAC_USE_CHN2
243 | if (&DACD2 == dacp) {
244 | regshift = 16;
245 | dataoffset = 12;
246 | }
247 | #endif
248 |
249 | switch (dacp->config->dhrm) {
250 | /* Sets the DAC data register */
251 | case DAC_DHRM_12BIT_RIGHT:
252 | data = (dacsample_t*)&dacp->dac->DHR12R1 + dataoffset;
253 | break;
254 | case DAC_DHRM_12BIT_LEFT:
255 | data = (dacsample_t*)&dacp->dac->DHR12L1 + dataoffset;
256 | break;
257 | case DAC_DHRM_8BIT_RIGHT:
258 | data = (dacsample_t*)&dacp->dac->DHR8R1 + dataoffset;
259 | break;
260 | #if defined(STM32_HAS_DAC_CHN2) && STM32_HAS_DAC_CHN2
261 | case DAC_DHRM_12BIT_RIGHT_DUAL:
262 | data = (dacsample_t*)&dacp->dac->DHR12RD;
263 | break;
264 | case DAC_DHRM_12BIT_LEFT_DUAL:
265 | data = (dacsample_t*)&dacp->dac->DHR12LD;
266 | break;
267 | case DAC_DHRM_8BIT_RIGHT_DUAL:
268 | data = (dacsample_t*)&dacp->dac->DHR8RD;
269 | break;
270 | #endif
271 | }
272 |
273 | dacp->dac->CR &= ~(STM32_DAC_CR_MASK << regshift);
274 | dacp->dac->CR |= ((STM32_DAC_CR_EN | dacp->config->cr_flags) << regshift);
275 |
276 | if (data != NULL)
277 | *data = value;
278 |
279 | #if STM32_DAC_USE_CHN1
280 | if (&DACD1 == dacp) {
281 | dacp->dac->SWTRIGR = DAC_SWTRIGR_SWTRIG1;
282 | }
283 | #endif
284 | #if STM32_DAC_USE_CHN2
285 | if (&DACD2 == dacp) {
286 | dacp->dac->SWTRIGR = DAC_SWTRIGR_SWTRIG2;
287 | }
288 | #endif
289 | #if STM32_DAC_USE_CHN3
290 | if (&DACD3 == dacp) {
291 | dacp->dac->SWTRIGR = DAC_SWTRIGR_SWTRIG1;
292 | }
293 | #endif
294 |
295 | }
296 |
297 | /**
298 | * @brief Sends data over the DAC bus.
299 | * @details This asynchronous function starts a transmit operation.
300 | * @post At the end of the operation the configured callback is invoked.
301 | *
302 | * @param[in] dacp pointer to the @p DACDriver object
303 | * @param[in] n number of words to send
304 | * @param[in] txbuf the pointer to the transmit buffer
305 | *
306 | * @notapi
307 | */
308 | void dac_lld_start_conversion(DACDriver *dacp) {
309 |
310 | uint32_t arr, psc, regshift, trgo, dataoffset;
311 | bool b;
312 |
313 | osalDbgAssert(dacp->samples,
314 | "dacp->samples is NULL pointer");
315 |
316 | #if STM32_DAC_USE_CHN1
317 | if (&DACD1 == dacp) {
318 | /* DAC1 CR data is at bits 0:15 */
319 | regshift = 0;
320 | dataoffset = 0;
321 | /* Timer setup */
322 | rccEnableTIM6(FALSE);
323 | rccResetTIM6();
324 | trgo = STM32_DAC_CR_TSEL_TIM6;
325 | }
326 | #endif
327 | #if STM32_DAC_USE_CHN2
328 | if (&DACD2 == dacp) {
329 | /* DAC2 CR data is at bits 16:31 */
330 | regshift = 16;
331 | dataoffset = 12;
332 | /* Timer setup */
333 | rccEnableTIM7(FALSE);
334 | rccResetTIM7();
335 | trgo = STM32_DAC_CR_TSEL_TIM7;
336 | }
337 | #endif
338 | #if STM32_DAC_USE_CHN3
339 | if (&DACD3 == dacp) {
340 | /* DAC3 CR data is at bits 0:15 */
341 | regshift = 0;
342 | dataoffset = 0;
343 | /* Timer setup */
344 | rccEnableTIM18(FALSE);
345 | rccResetTIM18();
346 | trgo = STM32_DAC_CR_TSEL_TIM18;
347 | }
348 | #endif
349 | #if STM32_DAC_USE_CHN1 || STM32_DAC_USE_CHN2 || STM32_DAC_USE_CHN3
350 | dacp->clock = STM32_TIMCLK1;
351 |
352 | /* Inscrease the prescaler as long as the auto reload value is above max */
353 | psc = 0;
354 | do
355 | {
356 | psc+=4;
357 | arr = (dacp->clock / dacp->grpp->frequency / psc);
358 | }
359 | while (arr >= 0xFFFF && psc <= 0xFFFF);
360 |
361 | osalDbgAssert((arr <= 0xFFFF && psc <= 0xFFFF), "Invalid frequency");
362 |
363 | /* Timer configuration.*/
364 | dacp->tim->CR1 = 0; /* Initially stopped. */
365 | dacp->tim->PSC = psc -1; /* Prescaler value. */
366 | dacp->tim->DIER = 0;
367 | dacp->tim->ARR = arr;
368 | dacp->tim->EGR = TIM_EGR_UG; /* Update event. */
369 | dacp->tim->CR2 &= (uint16_t)~TIM_CR2_MMS;
370 | dacp->tim->CR2 |= (uint16_t)TIM_CR2_MMS_1; /* Enable TRGO updates. */
371 | dacp->tim->CNT = 0; /* Reset counter. */
372 | dacp->tim->SR = 0; /* Clear pending IRQs. */
373 | /* Update Event IRQ enabled. */
374 |
375 | /* DAC configuration */
376 | dacp->dac->CR &= ~(STM32_DAC_CR_MASK << regshift);
377 | dacp->dac->CR |= (STM32_DAC_CR_DMAEN | dacp->config->cr_flags) << regshift;
378 |
379 | /* DMA setup. */
380 | b = dmaStreamAllocate(dacp->dma,
381 | dacp->irqprio,
382 | (stm32_dmaisr_t)dac_lld_serve_tx_interrupt,
383 | (void *)dacp);
384 | osalDbgAssert(!b, "stream already allocated");
385 | switch (dacp->config->dhrm) {
386 | /* Sets the DAC data register */
387 | case DAC_DHRM_12BIT_RIGHT:
388 | dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR12R1 + dataoffset);
389 | dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
390 | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
391 | break;
392 | case DAC_DHRM_12BIT_LEFT:
393 | dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR12L1 + dataoffset);
394 | dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
395 | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
396 | break;
397 | case DAC_DHRM_8BIT_RIGHT:
398 | dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR8R1 + dataoffset);
399 | dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
400 | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
401 | break;
402 | #if defined(STM32_HAS_DAC_CHN2) && STM32_HAS_DAC_CHN2
403 | case DAC_DHRM_12BIT_RIGHT_DUAL:
404 | dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR12RD);
405 | dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
406 | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
407 | break;
408 | case DAC_DHRM_12BIT_LEFT_DUAL:
409 | dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR12LD);
410 | dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
411 | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
412 | break;
413 | case DAC_DHRM_8BIT_RIGHT_DUAL:
414 | dmaStreamSetPeripheral(dacp->dma, &dacp->dac->DHR8RD);
415 | dacp->dmamode = (dacp->dmamode & ~STM32_DMA_CR_SIZE_MASK) |
416 | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
417 | break;
418 | #endif
419 | }
420 |
421 | dmaStreamSetMemory0(dacp->dma, dacp->samples);
422 | dmaStreamSetTransactionSize(dacp->dma, dacp->depth);
423 | dmaStreamSetMode(dacp->dma, dacp->dmamode | STM32_DMA_CR_EN |
424 | STM32_DMA_CR_CIRC);
425 |
426 | /* Timer start.*/
427 | dacp->dac->CR |= trgo << regshift; /* Enable timer trigger */
428 |
429 | dacp->dac->CR |= STM32_DAC_CR_EN;
430 | dacp->tim->CR1 = TIM_CR1_CEN;
431 | #endif
432 | }
433 |
434 | void dac_lld_stop_conversion(DACDriver *dacp) {
435 |
436 | /* Timer stop. */
437 | dacp->tim->CR1 &= ~TIM_CR1_CEN;
438 |
439 | /* DMA release.*/
440 | dmaStreamRelease(dacp->dma);
441 |
442 | #if STM32_DAC_USE_CHN1
443 | if (&DACD1 == dacp) {
444 | rccDisableTIM6(FALSE);
445 | }
446 | #endif
447 | #if STM32_DAC_USE_CHN2
448 | if (&DACD2 == dacp) {
449 | rccDisableTIM7(FALSE);
450 | }
451 | #endif
452 | #if STM32_DAC_USE_CHN3
453 | if (&DACD3 == dacp) {
454 | rccDisableTIM18(FALSE);
455 | }
456 | #endif
457 | }
458 |
459 | #endif /* DRIVER_USE_DAC */
460 |
461 | /** @} */
462 |
--------------------------------------------------------------------------------
/stm32/dac_driver_lld.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/HAL - Copyright (C) 2006-2014 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | /**
18 | * @file STM32/DACv1/dac_driver_lld.h
19 | * @brief STM32 DAC subsystem low level driver header.
20 | *
21 | * @addtogroup DAC
22 | * @{
23 | */
24 |
25 | #ifndef _DAC_DRIVER_LLD_H_
26 | #define _DAC_DRIVER_LLD_H_
27 |
28 | #if DRIVER_USE_DAC || defined(__DOXYGEN__)
29 |
30 | #include "drivers_conf.h"
31 | #include "stm32_tim.h"
32 | #include "stm32_rcc.h"
33 | #include "extra_registry.h"
34 | #include "extra_rcc.h"
35 |
36 | /*===========================================================================*/
37 | /* Driver constants. */
38 | /*===========================================================================*/
39 |
40 | #define STM32_DAC_CR_EN DAC_CR_EN1
41 | #define STM32_DAC_CR_DMAEN DAC_CR_DMAEN1
42 | #define STM32_DAC_CR_TEN DAC_CR_TEN1
43 |
44 | #define STM32_DAC_CR_MASK (uint32_t)0x00000FFE
45 |
46 | #define STM32_DAC_CR_BOFF_ENABLE (uint32_t)0x00000000
47 | #define STM32_DAC_CR_BOFF_DISABLE DAC_CR_BOFF1
48 |
49 | #define STM32_DAC_CR_TSEL_NONE (uint32_t)0x00000000
50 | #define STM32_DAC_CR_TSEL_TIM2 DAC_CR_TEN1 | DAC_CR_TSEL1_2
51 | #define STM32_DAC_CR_TSEL_TIM4 DAC_CR_TEN1 | DAC_CR_TSEL1_2
52 | #define STM32_DAC_CR_TSEL_TIM5 DAC_CR_TEN1 | DAC_CR_TSEL1_1
53 | #define STM32_DAC_CR_TSEL_TIM6 DAC_CR_TEN1
54 | #define STM32_DAC_CR_TSEL_TIM7 DAC_CR_TEN1 | DAC_CR_TSEL1_1
55 | #define STM32_DAC_CR_TSEL_TIM3 DAC_CR_TEN1 | DAC_CR_TSEL1_0
56 | #define STM32_DAC_CR_TSEL_TIM18 DAC_CR_TEN1 | DAC_CR_TSEL1_0 | DAC_CR_TSEL1_1
57 | #define STM32_DAC_CR_TSEL_EXT_IT9 DAC_CR_TEN1 | DAC_CR_TSEL1_2
58 | #define STM32_DAC_CR_TSEL_SOFT DAC_CR_TEN1 | DAC_CR_TSEL1_1 | DAC_CR_TSEL1_2
59 |
60 | #define STM32_DAC_CR_WAVE_NONE (uint32_t)0x00000000
61 | #define STM32_DAC_CR_WAVE_NOISE DAC_CR_WAVE1_0
62 | #define STM32_DAC_CR_WAVE_TRIANGLE DAC_CR_WAVE1_1
63 |
64 | #define STM32_DAC_MAMP_1 (uint32_t)0x00000000
65 | #define STM32_DAC_MAMP_3 DAC_CR_MAMP1_0
66 | #define STM32_DAC_MAMP_7 DAC_CR_MAMP1_1
67 | #define STM32_DAC_MAMP_15 DAC_CR_MAMP1_0 | DAC_CR_MAMP1_1
68 | #define STM32_DAC_MAMP_31 DAC_CR_MAMP1_2
69 | #define STM32_DAC_MAMP_63 DAC_CR_MAMP1_0 | DAC_CR_MAMP1_2
70 | #define STM32_DAC_MAMP_127 DAC_CR_MAMP1_1 | DAC_CR_MAMP1_2
71 | #define STM32_DAC_MAMP_255 DAC_CR_MAMP1_0 | DAC_CR_MAMP1_1 | DAC_CR_MAMP1_2
72 | #define STM32_DAC_MAMP_511 DAC_CR_MAMP1_3
73 | #define STM32_DAC_MAMP_1023 DAC_CR_MAMP1_0 | DAC_CR_MAMP1_3
74 | #define STM32_DAC_MAMP_2047 DAC_CR_MAMP1_1 | DAC_CR_MAMP1_3
75 | #define STM32_DAC_MAMP_4095 DAC_CR_MAMP1_0 | DAC_CR_MAMP1_1 | DAC_CR_MAMP1_2
76 |
77 | /*===========================================================================*/
78 | /* Driver pre-compile time settings. */
79 | /*===========================================================================*/
80 |
81 | /**
82 | * @name Configuration options
83 | * @{
84 | */
85 | /**
86 | * @brief DAC CHN1 driver enable switch.
87 | * @details If set to @p TRUE the support for DAC CHN1 is included.
88 | * @note The default is @p TRUE.
89 | */
90 | #if !defined(STM32_DAC_USE_CHN1) || defined(__DOXYGEN__)
91 | #define STM32_DAC_USE_CHN1 FALSE
92 | #endif
93 |
94 | /**
95 | * @brief DAC CHN2 driver enable switch.
96 | * @details If set to @p TRUE the support for DAC CHN2 is included.
97 | * @note The default is @p TRUE.
98 | */
99 | #if !defined(STM32_DAC_USE_CHN2) || defined(__DOXYGEN__)
100 | #define STM32_DAC_USE_CHN2 FALSE
101 | #endif
102 |
103 | /**
104 | * @brief DAC CHN3 driver enable switch.
105 | * @details If set to @p TRUE the support for DAC CHN3 is included.
106 | * @note The default is @p TRUE.
107 | */
108 | #if !defined(STM32_DAC_USE_CHN3) || defined(__DOXYGEN__)
109 | #define STM32_DAC_USE_CHN3 FALSE
110 | #endif
111 |
112 | /**
113 | * @brief DAC CHN1 interrupt priority level setting.
114 | */
115 | #if !defined(STM32_DAC_CHN1_IRQ_PRIORITY) || defined(__DOXYGEN__)
116 | #define STM32_DAC_CHN1_IRQ_PRIORITY 10
117 | #endif
118 |
119 | /**
120 | * @brief DAC CHN2 interrupt priority level setting.
121 | */
122 | #if !defined(STM32_DAC_CHN2_IRQ_PRIORITY) || defined(__DOXYGEN__)
123 | #define STM32_DAC_CHN2_IRQ_PRIORITY 10
124 | #endif
125 |
126 | /**
127 | * @brief DAC CHN3 interrupt priority level setting.
128 | */
129 | #if !defined(STM32_DAC_CHN3_IRQ_PRIORITY) || defined(__DOXYGEN__)
130 | #define STM32_DAC_CHN3_IRQ_PRIORITY 10
131 | #endif
132 |
133 | /**
134 | * @brief DAC CHN1 DMA priority (0..3|lowest..highest).
135 | */
136 | #if !defined(STM32_DAC_CHN1_DMA_PRIORITY) || defined(__DOXYGEN__)
137 | #define STM32_DAC_CHN1_DMA_PRIORITY 2
138 | #endif
139 |
140 | /**
141 | * @brief DAC CHN2 DMA priority (0..3|lowest..highest).
142 | */
143 | #if !defined(STM32_DAC_CHN2_DMA_PRIORITY) || defined(__DOXYGEN__)
144 | #define STM32_DAC_CHN2_DMA_PRIORITY 2
145 | #endif
146 |
147 | /**
148 | * @brief DAC CHN3 DMA priority (0..3|lowest..highest).
149 | */
150 | #if !defined(STM32_DAC_CHN3_DMA_PRIORITY) || defined(__DOXYGEN__)
151 | #define STM32_DAC_CHN2_DMA_PRIORITY 2
152 | #endif
153 |
154 | /**
155 | * @brief DAC DMA error hook.
156 | */
157 | #if !defined(STM32_DAC_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
158 | #define STM32_DAC_DMA_ERROR_HOOK(dacp) osalSysHalt()
159 | #endif
160 |
161 | /**
162 | * @brief DMA stream used for DAC CHN1 TX operations.
163 | * @note This option is only available on platforms with enhanced DMA.
164 | */
165 | #if !defined(STM32_DAC_CHN1_DMA_STREAM) || defined(__DOXYGEN__)
166 | #define STM32_DAC_CHN1_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
167 | #endif
168 |
169 | /**
170 | * @brief DMA stream used for DAC CHN2 TX operations.
171 | * @note This option is only available on platforms with enhanced DMA.
172 | */
173 | #if !defined(STM32_DAC_CHN2_DMA_STREAM) || defined(__DOXYGEN__)
174 | #define STM32_DAC_CHN2_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
175 | #endif
176 |
177 | /**
178 | * @brief DMA stream used for DAC CHN3 TX operations.
179 | * @note This option is only available on platforms with enhanced DMA.
180 | */
181 | #if !defined(STM32_DAC_CHN3_DMA_STREAM) || defined(__DOXYGEN__)
182 | #define STM32_DAC_CHN3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
183 | #endif
184 |
185 | /*===========================================================================*/
186 | /* Derived constants and error checks. */
187 | /*===========================================================================*/
188 |
189 | #if STM32_DAC_USE_CHN1 && !STM32_HAS_DAC_CHN1
190 | #error "DAC CHN1 not present in the selected device"
191 | #endif
192 |
193 | #if STM32_DAC_USE_CHN2 && !STM32_HAS_DAC_CHN2
194 | #error "DAC CHN2 not present in the selected device"
195 | #endif
196 |
197 | #if STM32_DAC_USE_CHN3 && !STM32_HAS_DAC_CHN3
198 | #error "DAC CHN3 not present in the selected device"
199 | #endif
200 |
201 | #if !STM32_DAC_USE_CHN1 && !STM32_DAC_USE_CHN2 && !STM32_DAC_USE_CHN3
202 | #error "DAC driver activated but no DAC peripheral assigned"
203 | #endif
204 |
205 | /* The following checks are only required when there is a DMA able to
206 | reassign streams to different channels.*/
207 | #if STM32_ADVANCED_DMA
208 | /* Check on the presence of the DMA streams settings in mcuconf.h.*/
209 | #if STM32_DAC_USE_CHN1 && !defined(STM32_DAC_CHN1_DMA_STREAM)
210 | #error "DAC1 CHN1 DMA stream not defined"
211 | #endif
212 |
213 | #if STM32_DAC_USE_CHN2 && !defined(STM32_DAC_CHN2_DMA_STREAM)
214 | #error "DAC1 CHN2 DMA stream not defined"
215 | #endif
216 |
217 | #if STM32_DAC_USE_CHN3 && !defined(STM32_DAC_CHN3_DMA_STREAM)
218 | #error "DAC1 CHN3 DMA stream not defined"
219 | #endif
220 |
221 | /* Check on the validity of the assigned DMA channels.*/
222 | #if STM32_DAC_USE_CHN1 && \
223 | !STM32_DMA_IS_VALID_ID(STM32_DAC_CHN1_DMA_STREAM, STM32_DAC_CHN1_DMA_MSK)
224 | #error "invalid DMA stream associated to DAC CHN1"
225 | #endif
226 |
227 | #if STM32_DAC_USE_CHN2 && \
228 | !STM32_DMA_IS_VALID_ID(STM32_DAC_CHN2_DMA_STREAM, STM32_DAC_CHN2_DMA_MSK)
229 | #error "invalid DMA stream associated to DAC CHN2"
230 | #endif
231 |
232 | #if STM32_DAC_USE_CHN3 && \
233 | !STM32_DMA_IS_VALID_ID(STM32_DAC_CHN3_DMA_STREAM, STM32_DAC_CHN3_DMA_MSK)
234 | #error "invalid DMA stream associated to DAC CHN3"
235 | #endif
236 | #endif /* STM32_ADVANCED_DMA */
237 |
238 | #if !defined(STM32_DMA_REQUIRED)
239 | #define STM32_DMA_REQUIRED
240 | #endif
241 |
242 | /*===========================================================================*/
243 | /* Driver data structures and types. */
244 | /*===========================================================================*/
245 |
246 | /**
247 | * @brief Type of a structure representing an DAC driver.
248 | */
249 | typedef struct DACDriver DACDriver;
250 |
251 | /**
252 | * @brief Type representing a DAC sample.
253 | */
254 | typedef uint16_t dacsample_t;
255 |
256 | /**
257 | * @brief DAC notification callback type.
258 | *
259 | * @param[in] dacp pointer to the @p DACDriver object triggering the
260 | * callback
261 | */
262 | typedef void (*daccallback_t)(DACDriver *dacp);
263 |
264 | typedef enum {
265 | DAC_DHRM_12BIT_RIGHT = 0,
266 | DAC_DHRM_12BIT_LEFT = 1,
267 | DAC_DHRM_8BIT_RIGHT = 2,
268 | #if STM32_HAS_DAC_CHN2 && !defined(__DOXYGEN__)
269 | DAC_DHRM_12BIT_RIGHT_DUAL = 3,
270 | DAC_DHRM_12BIT_LEFT_DUAL = 4,
271 | DAC_DHRM_8BIT_RIGHT_DUAL = 5
272 | #endif
273 | } dacdhrmode_t;
274 |
275 | /**
276 | * @brief DAC Conversion group structure.
277 | */
278 | typedef struct {
279 | /**
280 | * @brief Timer frequency in Hz.
281 | */
282 | uint32_t frequency;
283 | /**
284 | * @brief Number of DAC channels.
285 | */
286 | uint32_t num_channels;
287 | /**
288 | * @brief Operation complete callback or @p NULL.
289 | */
290 | daccallback_t end_cb;
291 | /**
292 | * @brief Error handling callback or @p NULL.
293 | */
294 | daccallback_t error_cb;
295 |
296 | } DACConversionGroup;
297 |
298 | /**
299 | * @brief Driver configuration structure.
300 | */
301 | typedef struct {
302 | /**
303 | * @brief DAC data holding register mode.
304 | */
305 | dacdhrmode_t dhrm;
306 | /* End of the mandatory fields.*/
307 | /**
308 | * @brief DAC initialization data.
309 | */
310 | uint32_t cr_flags;
311 | } DACConfig;
312 |
313 | /**
314 | * @brief Structure representing a DAC driver.
315 | */
316 | struct DACDriver {
317 | /**
318 | * @brief Driver state.
319 | */
320 | dacstate_t state;
321 | /**
322 | * @brief Conversion group.
323 | */
324 | const DACConversionGroup *grpp;
325 | /**
326 | * @brief Samples buffer pointer.
327 | */
328 | const dacsample_t *samples;
329 | /**
330 | * @brief Samples buffer size.
331 | */
332 | uint16_t depth;
333 | /**
334 | * @brief Current configuration data.
335 | */
336 | const DACConfig *config;
337 | #if DAC_USE_WAIT || defined(__DOXYGEN__)
338 | /**
339 | * @brief Waiting thread.
340 | */
341 | thread_reference_t thread;
342 | #endif /* DAC_USE_WAIT */
343 | #if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
344 | /**
345 | * @brief Mutex protecting the bus.
346 | */
347 | mutex_t mutex;
348 | #endif /* DAC_USE_MUTUAL_EXCLUSION */
349 | #if defined(DAC_DRIVER_EXT_FIELDS)
350 | DAC_DRIVER_EXT_FIELDS
351 | #endif
352 | /* End of the mandatory fields.*/
353 | /**
354 | * @brief Pointer to the DAC registers block.
355 | */
356 | DAC_TypeDef *dac;
357 | /**
358 | * @brief Pointer to the TIMx registers block.
359 | */
360 | stm32_tim_t *tim;
361 | /**
362 | * @brief The Timer IRQ priority.
363 | */
364 | uint32_t irqprio;
365 | /**
366 | * @brief Transmit DMA stream.
367 | */
368 | const stm32_dma_stream_t *dma;
369 | /**
370 | * @brief TX DMA mode bit mask.
371 | */
372 | uint32_t dmamode;
373 | /**
374 | * @brief Timer base clock.
375 | */
376 | uint32_t clock;
377 | };
378 |
379 | /*===========================================================================*/
380 | /* Driver macros. */
381 | /*===========================================================================*/
382 |
383 | /*===========================================================================*/
384 | /* External declarations. */
385 | /*===========================================================================*/
386 |
387 | #if STM32_DAC_USE_CHN1 && !defined(__DOXYGEN__)
388 | extern DACDriver DACD1;
389 | #endif
390 |
391 | #if STM32_DAC_USE_CHN2 && !defined(__DOXYGEN__)
392 | extern DACDriver DACD2;
393 | #endif
394 |
395 | #if STM32_DAC_USE_CHN3 && !defined(__DOXYGEN__)
396 | extern DACDriver DACD3;
397 | #endif
398 |
399 | #ifdef __cplusplus
400 | extern "C" {
401 | #endif
402 | void dac_lld_init(void);
403 | void dac_lld_start(DACDriver *dacp);
404 | void dac_lld_stop(DACDriver *dacp);
405 | void dac_lld_single_convert(DACDriver *dacp, dacsample_t value);
406 | void dac_lld_start_conversion(DACDriver *dacp);
407 | void dac_lld_stop_conversion(DACDriver *dacp);
408 | #ifdef __cplusplus
409 | }
410 | #endif
411 |
412 | #endif /* DRIVER_USE_DAC */
413 |
414 | #endif /* _DAC_DRIVER_LLD_H_ */
415 |
416 | /** @} */
417 |
--------------------------------------------------------------------------------
/stm32/eicu_driver_lld.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | /*
17 | Rewritten by Emil Fresk (1/5 - 2014) for extended input capture
18 | functionallity. And fix for spourious callbacks in the interrupt handler.
19 | */
20 |
21 | #ifndef __EICU_LLD_H
22 | #define __EICU_LLD_H
23 |
24 | #include "stm32_tim.h"
25 |
26 | #if DRIVER_USE_EICU || defined(__DOXYGEN__)
27 |
28 | /*===========================================================================*/
29 | /* Driver constants. */
30 | /*===========================================================================*/
31 |
32 | /*===========================================================================*/
33 | /* Driver pre-compile time settings. */
34 | /*===========================================================================*/
35 |
36 | /**
37 | * @name Configuration options
38 | * @{
39 | */
40 | /**
41 | * @brief EICUD1 driver enable switch.
42 | * @details If set to @p TRUE the support for EICUD1 is included.
43 | * @note The default is @p TRUE.
44 | */
45 | #if !defined(STM32_EICU_USE_TIM1) || defined(__DOXYGEN__)
46 | #define STM32_EICU_USE_TIM1 FALSE
47 | #endif
48 |
49 | /**
50 | * @brief EICUD2 driver enable switch.
51 | * @details If set to @p TRUE the support for EICUD2 is included.
52 | * @note The default is @p TRUE.
53 | */
54 | #if !defined(STM32_EICU_USE_TIM2) || defined(__DOXYGEN__)
55 | #define STM32_EICU_USE_TIM2 FALSE
56 | #endif
57 |
58 | /**
59 | * @brief EICUD3 driver enable switch.
60 | * @details If set to @p TRUE the support for EICUD3 is included.
61 | * @note The default is @p TRUE.
62 | */
63 | #if !defined(STM32_EICU_USE_TIM3) || defined(__DOXYGEN__)
64 | #define STM32_EICU_USE_TIM3 FALSE
65 | #endif
66 |
67 | /**
68 | * @brief EICUD4 driver enable switch.
69 | * @details If set to @p TRUE the support for EICUD4 is included.
70 | * @note The default is @p TRUE.
71 | */
72 | #if !defined(STM32_EICU_USE_TIM4) || defined(__DOXYGEN__)
73 | #define STM32_EICU_USE_TIM4 FALSE
74 | #endif
75 |
76 | /**
77 | * @brief EICUD5 driver enable switch.
78 | * @details If set to @p TRUE the support for EICUD5 is included.
79 | * @note The default is @p TRUE.
80 | */
81 | #if !defined(STM32_EICU_USE_TIM5) || defined(__DOXYGEN__)
82 | #define STM32_EICU_USE_TIM5 FALSE
83 | #endif
84 |
85 | /**
86 | * @brief EICUD8 driver enable switch.
87 | * @details If set to @p TRUE the support for EICUD8 is included.
88 | * @note The default is @p TRUE.
89 | */
90 | #if !defined(STM32_EICU_USE_TIM8) || defined(__DOXYGEN__)
91 | #define STM32_EICU_USE_TIM8 FALSE
92 | #endif
93 |
94 | /**
95 | * @brief EICUD9 driver enable switch.
96 | * @details If set to @p TRUE the support for EICUD9 is included.
97 | * @note The default is @p TRUE.
98 | */
99 | #if !defined(STM32_EICU_USE_TIM9) || defined(__DOXYGEN__)
100 | #define STM32_EICU_USE_TIM9 FALSE
101 | #endif
102 |
103 | /**
104 | * @brief EICUD12 driver enable switch.
105 | * @details If set to @p TRUE the support for EICUD12 is included.
106 | * @note The default is @p TRUE.
107 | */
108 | #if !defined(STM32_EICU_USE_TIM12) || defined(__DOXYGEN__)
109 | #define STM32_EICU_USE_TIM12 FALSE
110 | #endif
111 |
112 | /**
113 | * @brief EICUD1 interrupt priority level setting.
114 | */
115 | #if !defined(STM32_EICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
116 | #define STM32_EICU_TIM1_IRQ_PRIORITY 7
117 | #endif
118 |
119 | /**
120 | * @brief EICUD2 interrupt priority level setting.
121 | */
122 | #if !defined(STM32_EICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
123 | #define STM32_EICU_TIM2_IRQ_PRIORITY 7
124 | #endif
125 |
126 | /**
127 | * @brief EICUD3 interrupt priority level setting.
128 | */
129 | #if !defined(STM32_EICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
130 | #define STM32_EICU_TIM3_IRQ_PRIORITY 7
131 | #endif
132 |
133 | /**
134 | * @brief EICUD4 interrupt priority level setting.
135 | */
136 | #if !defined(STM32_EICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
137 | #define STM32_EICU_TIM4_IRQ_PRIORITY 7
138 | #endif
139 |
140 | /**
141 | * @brief EICUD5 interrupt priority level setting.
142 | */
143 | #if !defined(STM32_EICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
144 | #define STM32_EICU_TIM5_IRQ_PRIORITY 7
145 | #endif
146 |
147 | /**
148 | * @brief EICUD8 interrupt priority level setting.
149 | */
150 | #if !defined(STM32_EICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
151 | #define STM32_EICU_TIM8_IRQ_PRIORITY 7
152 | #endif
153 |
154 | /**
155 | * @brief EICUD9 interrupt priority level setting.
156 | */
157 | #if !defined(STM32_EICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__)
158 | #define STM32_EICU_TIM9_IRQ_PRIORITY 7
159 | #endif
160 |
161 | /**
162 | * @brief EICUD12 interrupt priority level setting.
163 | */
164 | #if !defined(STM32_EICU_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__)
165 | #define STM32_EICU_TIM12_IRQ_PRIORITY 7
166 | #endif
167 | /** @} */
168 |
169 | /*===========================================================================*/
170 | /* Derived constants and error checks. */
171 | /*===========================================================================*/
172 |
173 | #if STM32_EICU_USE_TIM1 && !STM32_HAS_TIM1
174 | #error "TIM1 not present in the selected device"
175 | #endif
176 |
177 | #if STM32_EICU_USE_TIM2 && !STM32_HAS_TIM2
178 | #error "TIM2 not present in the selected device"
179 | #endif
180 |
181 | #if STM32_EICU_USE_TIM3 && !STM32_HAS_TIM3
182 | #error "TIM3 not present in the selected device"
183 | #endif
184 |
185 | #if STM32_EICU_USE_TIM4 && !STM32_HAS_TIM4
186 | #error "TIM4 not present in the selected device"
187 | #endif
188 |
189 | #if STM32_EICU_USE_TIM5 && !STM32_HAS_TIM5
190 | #error "TIM5 not present in the selected device"
191 | #endif
192 |
193 | #if STM32_EICU_USE_TIM8 && !STM32_HAS_TIM8
194 | #error "TIM8 not present in the selected device"
195 | #endif
196 |
197 | #if STM32_EICU_USE_TIM9 && !STM32_HAS_TIM9
198 | #error "TIM9 not present in the selected device"
199 | #endif
200 |
201 | #if STM32_EICU_USE_TIM12 && !STM32_HAS_TIM12
202 | #error "TIM12 not present in the selected device"
203 | #endif
204 |
205 | #if !STM32_EICU_USE_TIM1 && !STM32_EICU_USE_TIM2 && \
206 | !STM32_EICU_USE_TIM3 && !STM32_EICU_USE_TIM4 && \
207 | !STM32_EICU_USE_TIM5 && !STM32_EICU_USE_TIM8 && \
208 | !STM32_EICU_USE_TIM9 && !STM32_EICU_USE_TIM12
209 | #error "EICU driver activated but no TIM peripheral assigned"
210 | #endif
211 |
212 | #if STM32_EICU_USE_TIM1 && \
213 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM1_IRQ_PRIORITY)
214 | #error "Invalid IRQ priority assigned to TIM1"
215 | #endif
216 |
217 | #if STM32_EICU_USE_TIM2 && \
218 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM2_IRQ_PRIORITY)
219 | #error "Invalid IRQ priority assigned to TIM2"
220 | #endif
221 |
222 | #if STM32_EICU_USE_TIM3 && \
223 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM3_IRQ_PRIORITY)
224 | #error "Invalid IRQ priority assigned to TIM3"
225 | #endif
226 |
227 | #if STM32_EICU_USE_TIM4 && \
228 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM4_IRQ_PRIORITY)
229 | #error "Invalid IRQ priority assigned to TIM4"
230 | #endif
231 |
232 | #if STM32_EICU_USE_TIM5 && \
233 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM5_IRQ_PRIORITY)
234 | #error "Invalid IRQ priority assigned to TIM5"
235 | #endif
236 |
237 | #if STM32_EICU_USE_TIM8 && \
238 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM8_IRQ_PRIORITY)
239 | #error "Invalid IRQ priority assigned to TIM8"
240 | #endif
241 |
242 | #if STM32_EICU_USE_TIM9 && \
243 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM9_IRQ_PRIORITY)
244 | #error "Invalid IRQ priority assigned to TIM9"
245 | #endif
246 |
247 | #if STM32_EICU_USE_TIM12 && \
248 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_EICU_TIM12_IRQ_PRIORITY)
249 | #error "Invalid IRQ priority assigned to TIM12"
250 | #endif
251 |
252 | /*===========================================================================*/
253 | /* Driver data structures and types. */
254 | /*===========================================================================*/
255 |
256 | /**
257 | * @brief EICU driver mode.
258 | */
259 | typedef enum {
260 | /**
261 | * @brief Trigger on rising edge.
262 | */
263 | EICU_INPUT_ACTIVE_HIGH = 0,
264 | /**
265 | * @brief Trigger on falling edge.
266 | */
267 | EICU_INPUT_ACTIVE_LOW = 1,
268 | } eicumode_t;
269 |
270 | /**
271 | * @brief Input type selector.
272 | */
273 | typedef enum {
274 | /**
275 | * @brief Triggers on the edge of the input.
276 | */
277 | EICU_INPUT_EDGE = 0,
278 | /**
279 | * @brief Triggers on detected pulse.
280 | */
281 | EICU_INPUT_PULSE = 1,
282 | /**
283 | * @brief Triggers on detected PWM period and width.
284 | */
285 | EICU_INPUT_PWM = 2
286 | } eicuinput_t;
287 |
288 | /**
289 | * @brief EICU frequency type.
290 | */
291 | typedef uint32_t eicufreq_t;
292 |
293 | /**
294 | * @brief EICU counter type.
295 | */
296 | typedef uint16_t eicucnt_t;
297 |
298 | /**
299 | * @brief EICU Input Capture Settings structure definition.
300 | */
301 | typedef struct
302 | {
303 | /**
304 | * @brief Specifies the active edge of the input signal.
305 | */
306 | eicumode_t mode;
307 | /**
308 | * @brief Capture event callback. Used for PWM width, pulse width and
309 | * normal capture event.
310 | */
311 | eicucallback_t width_cb;
312 | } EICU_IC_Settings;
313 |
314 | /**
315 | * @brief EICU Input Capture Config structure definition.
316 | */
317 | typedef struct
318 | {
319 | /**
320 | * @brief Select which input type the driver will be configured for.
321 | */
322 | eicuinput_t input_type;
323 | /**
324 | * @brief Specifies the Timer clock in Hz.
325 | */
326 | eicufreq_t frequency;
327 | /**
328 | * @brief Pointer to each Input Capture channel configuration.
329 | * @note A NULL parameter indicates the channel as unused.
330 | * @note In PWM mode, only Channel 1 OR Channel 2 may be used.
331 | */
332 | const EICU_IC_Settings *iccfgp[4];
333 | /**
334 | * @brief Period capture event callback.
335 | * @note Only used when in PWM measuremtent mode
336 | */
337 | eicucallback_t period_cb;
338 | /**
339 | * @brief Timer overflow event callback.
340 | */
341 | eicucallback_t overflow_cb;
342 | /**
343 | * @brief TIM DIER register initialization data.
344 | */
345 | uint32_t dier;
346 | } EICUConfig;
347 |
348 | /**
349 | * @brief EICU Input Capture Driver structure definition
350 | */
351 | struct EICUDriver
352 | {
353 | /**
354 | * @brief STM32 timer peripheral for Input Capture.
355 | */
356 | stm32_tim_t *tim;
357 | /**
358 | * @brief Driver state for the interal state machine.
359 | */
360 | eicustate_t state;
361 | /**
362 | * @brief Temporary width holder during pulse measurement.
363 | */
364 | eicucnt_t last_count[4];
365 | /**
366 | * @brief Timer base clock.
367 | */
368 | uint32_t clock;
369 | /**
370 | * @brief Pointer to configuration for the driver.
371 | */
372 | const EICUConfig *config;
373 | /**
374 | * @brief CCR registers for width capture.
375 | */
376 | volatile uint32_t *wccrp[4];
377 | /**
378 | * @brief CCR register for period capture.
379 | * @note Only one is needed since only one PWM input per timer is allowed.
380 | */
381 | volatile uint32_t *pccrp;
382 | };
383 |
384 | /*===========================================================================*/
385 | /* Driver macros. */
386 | /*===========================================================================*/
387 |
388 | /**
389 | * @brief Returns the width of the latest cycle.
390 | * @details The cycle width is defined as number of ticks between a start
391 | * edge and the next start edge.
392 | *
393 | * @param[in] eicup Pointer to the EICUDriver object.
394 | * @return The number of ticks.
395 | *
396 | * @notapi
397 | */
398 | #define eicu_lld_get_period(eicup) (*((eicup)->pccrp) + 1)
399 |
400 | /**
401 | * @brief Returns the compare value of the latest cycle.
402 | *
403 | * @param[in] eicup Pointer to the EICUDriver object.
404 | * @param[in] channel The timer channel that fired the interrupt.
405 | * @return The number of ticks.
406 | *
407 | * @notapi
408 | */
409 | #define eicu_lld_get_compare(eicup, channel) (*((eicup)->wccrp[(channel)]) + 1)
410 |
411 | /**
412 | * @brief Inverts the polarity for the given channel.
413 | *
414 | * @param[in] eicup Pointer to the EICUDriver object.
415 | * @param[in] channel The timer channel to invert.
416 | *
417 | * @notapi
418 | */
419 | #define eicu_lld_invert_polarity(eicup, channel) \
420 | (eicup)->tim->CCER ^= ((uint16_t)(STM32_TIM_CCER_CC1P << ((channel) * 4)))
421 | /*===========================================================================*/
422 | /* External declarations. */
423 | /*===========================================================================*/
424 | #if STM32_EICU_USE_TIM1 && !defined(__DOXYGEN__)
425 | extern EICUDriver EICUD1;
426 | #endif
427 |
428 | #if STM32_EICU_USE_TIM2 && !defined(__DOXYGEN__)
429 | extern EICUDriver EICUD2;
430 | #endif
431 |
432 | #if STM32_EICU_USE_TIM3 && !defined(__DOXYGEN__)
433 | extern EICUDriver EICUD3;
434 | #endif
435 |
436 | #if STM32_EICU_USE_TIM4 && !defined(__DOXYGEN__)
437 | extern EICUDriver EICUD4;
438 | #endif
439 |
440 | #if STM32_EICU_USE_TIM5 && !defined(__DOXYGEN__)
441 | extern EICUDriver EICUD5;
442 | #endif
443 |
444 | #if STM32_EICU_USE_TIM8 && !defined(__DOXYGEN__)
445 | extern EICUDriver EICUD8;
446 | #endif
447 |
448 | #if STM32_EICU_USE_TIM9 && !defined(__DOXYGEN__)
449 | extern EICUDriver EICUD9;
450 | #endif
451 |
452 | #if STM32_EICU_USE_TIM12 && !defined(__DOXYGEN__)
453 | extern EICUDriver EICUD12;
454 | #endif
455 |
456 | #ifdef __cplusplus
457 | extern "C" {
458 | #endif
459 | void eicu_lld_init(void);
460 | void eicu_lld_start(EICUDriver *eicup);
461 | void eicu_lld_stop(EICUDriver *eicup);
462 | void eicu_lld_enable(EICUDriver *eicup);
463 | void eicu_lld_disable(EICUDriver *eicup);
464 | uint16_t eicu_lld_get_width(EICUDriver *eicup, uint16_t channel);
465 | #ifdef __cplusplus
466 | }
467 | #endif
468 |
469 | #endif /* DRIVER_USE_EICU */
470 |
471 | #endif /* __EICU_LLD_H */
472 |
--------------------------------------------------------------------------------
/stm32/extra_rcc.h:
--------------------------------------------------------------------------------
1 | #ifndef _EXTRA_RCC_
2 | #define _EXTRA_RCC_
3 |
4 | #include "stm32_rcc.h"
5 |
6 | #ifndef rccEnableDAC
7 | #define rccEnableDAC(lp) rccEnableAPB1(RCC_APB1ENR_DACEN, lp)
8 | #define rccDisableDAC(lp) rccDisableAPB1(RCC_APB1ENR_DACEN, lp)
9 | #define rccResetDAC() rccResetAPB1(RCC_APB1RSTR_DACRST)
10 | #endif
11 |
12 | #ifndef rccEnableDAC1
13 | #define rccEnableDAC1(lp) rccEnableAPB1(RCC_APB1ENR_DAC1EN, lp)
14 | #define rccDisableDAC1(lp) rccDisableAPB1(RCC_APB1ENR_DAC1EN, lp)
15 | #define rccResetDAC1() rccResetAPB1(RCC_APB1RSTR_DAC1RST)
16 | #endif
17 |
18 | #ifndef rccEnableDAC2
19 | #define rccEnableDAC2(lp) rccEnableAPB1(RCC_APB1ENR_DAC2EN, lp)
20 | #define rccDisableDAC2(lp) rccDisableAPB1(RCC_APB1ENR_DAC2EN, lp)
21 | #define rccResetDAC2() rccResetAPB1(RCC_APB1RSTR_DAC2RST)
22 | #endif
23 |
24 | #ifndef rccEnableTIM6
25 | #define rccEnableTIM6(lp) rccEnableAPB1(RCC_APB1ENR_TIM6EN, lp)
26 | #define rccDisableTIM6(lp) rccDisableAPB1(RCC_APB1ENR_TIM6EN, lp)
27 | #define rccResetTIM6() rccResetAPB1(RCC_APB1RSTR_TIM6RST)
28 | #endif
29 |
30 | #ifndef rccEnableTIM7
31 | #define rccEnableTIM7(lp) rccEnableAPB1(RCC_APB1ENR_TIM7EN, lp)
32 | #define rccDisableTIM7(lp) rccDisableAPB1(RCC_APB1ENR_TIM7EN, lp)
33 | #define rccResetTIM7() rccResetAPB1(RCC_APB1RSTR_TIM7RST)
34 | #endif
35 |
36 | #ifndef rccEnableTIM15
37 | #define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp)
38 | #define rccDisableTIM15(lp) rccDisableAPB2(RCC_APB2ENR_TIM15EN, lp)
39 | #define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST)
40 | #endif
41 |
42 | #ifndef rccEnableTIM16
43 | #define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp)
44 | #define rccDisableTIM16(lp) rccDisableAPB2(RCC_APB2ENR_TIM16EN, lp)
45 | #define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST)
46 | #endif
47 |
48 | #ifndef rccEnableTIM17
49 | #define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp)
50 | #define rccDisableTIM17(lp) rccDisableAPB2(RCC_APB2ENR_TIM17EN, lp)
51 | #define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST)
52 | #endif
53 |
54 | #ifndef rccEnableTIM18
55 | #define rccEnableTIM18(lp) rccEnableAPB1(RCC_APB1ENR_TIM18EN, lp)
56 | #define rccDisableTIM18(lp) rccDisableAPB1(RCC_APB1ENR_TIM18EN, lp)
57 | #define rccResetTIM18() rccResetAPB1(RCC_APB1RSTR_TIM18RST)
58 | #endif
59 |
60 | #endif /* _EXTRA_RCC_ */
--------------------------------------------------------------------------------
/stm32/extra_registry.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _EXTRA_REGISTRY_H_
3 | #define _EXTRA_REGISTRY_H_
4 |
5 |
6 | /* DAC attributes.*/
7 | #define STM32_HAS_DAC TRUE
8 |
9 | #define STM32_HAS_DAC_CHN1 TRUE
10 | #define STM32_DAC_CHN1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) | STM32_DMA_STREAM_ID_MSK(2, 3))
11 | #define STM32_DAC_CHN1_DMA_CHN 0x00000000
12 |
13 | #define STM32_HAS_DAC_CHN2 TRUE
14 | #define STM32_DAC_CHN2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) | STM32_DMA_STREAM_ID_MSK(2, 4))
15 | #define STM32_DAC_CHN2_DMA_CHN 0x00000000
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/stm32/iuart_driver_lld.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 |
17 | */
18 |
19 | /**
20 | * @file STM32/USARTv2/iuart_lld.c
21 | * @brief STM32 low level IUART driver code.
22 | *
23 | * @addtogroup IUART
24 | * @{
25 | */
26 |
27 | /**
28 | * Allows selection between DMA (the default) and interrupts for data transfer
29 | *
30 | * To enable interrupt handling, add to mcuconf.h:
31 | * #define STM32_IUART_USE_INTERRUPTS TRUE
32 | *
33 | * This enables interrupt handling for all defined IUART channels, releasing DMA
34 | * channels for other purposes.
35 | */
36 | #include "hal.h"
37 |
38 | #include "iuart_driver.h"
39 |
40 | #if DRIVER_USE_IUART || defined(__DOXYGEN__)
41 |
42 | /*===========================================================================*/
43 | /* Driver local definitions. */
44 | /*===========================================================================*/
45 |
46 | /*===========================================================================*/
47 | /* Driver exported variables. */
48 | /*===========================================================================*/
49 |
50 | /** @brief USART1 IUART driver identifier.*/
51 | #if STM32_IUART_USE_USART1 || defined(__DOXYGEN__)
52 | IUARTDriver IUARTD1;
53 | #endif
54 |
55 | /** @brief USART2 IUART driver identifier.*/
56 | #if STM32_IUART_USE_USART2 || defined(__DOXYGEN__)
57 | IUARTDriver IUARTD2;
58 | #endif
59 |
60 | /** @brief USART3 IUART driver identifier.*/
61 | #if STM32_IUART_USE_USART3 || defined(__DOXYGEN__)
62 | IUARTDriver IUARTD3;
63 | #endif
64 |
65 | /*===========================================================================*/
66 | /* Driver local variables and types. */
67 | /*===========================================================================*/
68 |
69 | /*===========================================================================*/
70 | /* Driver local functions. */
71 | /*===========================================================================*/
72 |
73 | /**
74 | * @brief Status bits translation.
75 | *
76 | * @param[in] sr USART SR register value
77 | *
78 | * @return The error flags.
79 | */
80 | static iuartflags_t translate_errors(uint32_t isr)
81 | {
82 | iuartflags_t sts = 0;
83 |
84 | if (isr & USART_ISR_ORE)
85 | sts |= IUART_OVERRUN_ERROR;
86 | if (isr & USART_ISR_PE)
87 | sts |= IUART_PARITY_ERROR;
88 | if (isr & USART_ISR_FE)
89 | sts |= IUART_FRAMING_ERROR;
90 | if (isr & USART_ISR_NE)
91 | sts |= IUART_NOISE_ERROR;
92 | if (isr & USART_ISR_LBDF)
93 | sts |= IUART_BREAK_DETECTED;
94 | return sts;
95 | }
96 |
97 | /**
98 | * @brief USART de-initialization.
99 | * @details This function must be invoked with interrupts disabled.
100 | *
101 | * @param[in] iuartp pointer to the @p IUARTDriver object
102 | */
103 | static void usart_stop(IUARTDriver *iuartp)
104 | {
105 | /* Stops USART operations.*/
106 | iuartp->usart->CR1 = 0;
107 | iuartp->usart->CR2 = 0;
108 | iuartp->usart->CR3 = 0;
109 | }
110 |
111 |
112 | /**
113 | * @brief USART initialization.
114 | * @details This function must be invoked with interrupts disabled.
115 | *
116 | * @param[in] iuartp pointer to the @p IUARTDriver object
117 | */
118 | static void usart_start(IUARTDriver *iuartp)
119 | {
120 | USART_TypeDef *u = iuartp->usart;
121 |
122 | /* Defensive programming, starting from a clean state.*/
123 | usart_stop(iuartp);
124 |
125 | /* Baud rate setting.*/
126 | #if defined(STM32F0XX)
127 | if (iuartp->usart == USART1)
128 | u->BRR = STM32_USART1CLK / iuartp->config->speed;
129 | else
130 | u->BRR = STM32_PCLK / iuartp->config->speed;
131 | #else /* !defined(STM32F0XX) */
132 | if (iuartp->usart == USART1)
133 | u->BRR = STM32_PCLK2 / iuartp->config->speed;
134 | else
135 | u->BRR = STM32_PCLK1 / iuartp->config->speed;
136 | #endif /* !defined(STM32F0XX) */
137 |
138 | /* Resetting eventual pending status flags.*/
139 | u->ICR = 0xFFFFFFFF;
140 |
141 | /* Note that some bits are enforced because required for correct driver
142 | operations.*/
143 | u->CR2 = iuartp->config->cr2 | USART_CR2_LBDIE;
144 |
145 | u->CR3 = iuartp->config->cr3 | USART_CR3_EIE;
146 | u->CR1 = iuartp->config->cr1 | USART_CR1_UE | USART_CR1_PEIE |
147 | USART_CR1_RXNEIE | USART_CR1_TE |
148 | USART_CR1_RE; // Enable receive interrupts straight away
149 | }
150 |
151 |
152 | /**
153 | * @brief USART common service routine.
154 | *
155 | * @param[in] iuartp pointer to the @p IUARTDriver object
156 | */
157 | static void serve_usart_irq(IUARTDriver *iuartp) {
158 |
159 | uint32_t isr;
160 | USART_TypeDef *u = iuartp->usart;
161 |
162 | /* Reading and clearing status.*/
163 | isr = u->ISR;
164 | u->ICR = isr;
165 |
166 | /* Error condition detection.*/
167 | if (isr & (USART_ISR_LBDF | USART_ISR_ORE | USART_ISR_NE |
168 | USART_ISR_FE | USART_ISR_PE)) {
169 | if (iuartp->config->rxerr_cb != NULL)
170 | iuartp->config->rxerr_cb(iuartp, translate_errors(isr)); // Receive error callback
171 | }
172 |
173 | uint32_t cr1 = u->CR1;
174 |
175 | /* Data available (receive). */
176 | if (isr & USART_ISR_RXNE)
177 | {
178 | iuartp->rxbuf = (uint16_t)u->RDR; // Get the character
179 | if (iuartp->rxCount > 0)
180 | { // Must be a block receive
181 | *iuartp->rxBuffer++ = iuartp->rxbuf; // Problem with >8-bit data here - @TODO: needs handling
182 | (iuartp->rxCount)--;
183 | if (iuartp->rxCount == 0)
184 | {
185 | /* Receiver in active state, a callback is generated, if enabled, after
186 | a completed transfer.*/
187 | iuartp->rxstate = IUART_RX_COMPLETE;
188 | if (iuartp->config->rxend_cb != NULL)
189 | iuartp->config->rxend_cb(iuartp);
190 |
191 | /* If the callback didn't explicitly change state then the receiver
192 | automatically returns to the idle state.*/
193 | if (iuartp->rxstate == IUART_RX_COMPLETE) {
194 | iuartp->rxstate = IUART_RX_IDLE;
195 | }
196 | }
197 | }
198 | else
199 | { // Receive character while in IUART_RX_IDLE mode
200 | if (iuartp->config->rxchar_cb != NULL)
201 | iuartp->config->rxchar_cb(iuartp, iuartp->rxbuf); // Receive character callback
202 | }
203 | }
204 |
205 | /* Transmission buffer empty.*/
206 | if ((cr1 & USART_CR1_TXEIE) && (isr & USART_ISR_TXE))
207 | {
208 | u->TDR = *iuartp->txBuf++; // Next character to transmit output buffer
209 | if (--(iuartp->txCount) == 0)
210 | {
211 | iuartp->txBuf = NULL;
212 | /* A callback is generated, if enabled, after a completed transfer.*/
213 | iuartp->txstate = IUART_TX_COMPLETE;
214 | if (iuartp->config->txend1_cb != NULL)
215 | iuartp->config->txend1_cb(iuartp); // Signal that Tx buffer finished with
216 |
217 | /* If the callback didn't explicitly change state then the transmitter
218 | automatically returns to the idle state.*/
219 | if (iuartp->txstate == IUART_TX_COMPLETE)
220 | iuartp->txstate = IUART_TX_IDLE;
221 | u->CR1 = (cr1 & ~USART_CR1_TXEIE) | USART_CR1_TCIE; // Disable transmit data interrupt, enable TxBuffer empty
222 | }
223 | }
224 | /* Physical transmission end.*/
225 | if (isr & USART_ISR_TC)
226 | {
227 | if (iuartp->config->txend2_cb != NULL)
228 | iuartp->config->txend2_cb(iuartp); // Signal that whole transmit message gone
229 | u->CR1 = cr1 & ~USART_CR1_TCIE; // Disable transmit buffer empty interrupt
230 | }
231 | }
232 |
233 |
234 |
235 | /*===========================================================================*/
236 | /* Driver interrupt handlers. */
237 | /*===========================================================================*/
238 |
239 | #if STM32_IUART_USE_USART1 || defined(__DOXYGEN__)
240 | #if !defined(STM32_USART1_HANDLER)
241 | #error "STM32_USART1_HANDLER not defined"
242 | #endif
243 | /**
244 | * @brief USART1 IRQ handler.
245 | *
246 | * @isr
247 | */
248 | CH_IRQ_HANDLER(STM32_USART1_HANDLER) {
249 |
250 | CH_IRQ_PROLOGUE();
251 |
252 | serve_usart_irq(&IUARTD1);
253 |
254 | CH_IRQ_EPILOGUE();
255 | }
256 | #endif /* STM32_IUART_USE_USART1 */
257 |
258 | #if STM32_IUART_USE_USART2 || defined(__DOXYGEN__)
259 | #if !defined(STM32_USART2_HANDLER)
260 | #error "STM32_USART2_HANDLER not defined"
261 | #endif
262 | /**
263 | * @brief USART2 IRQ handler.
264 | *
265 | * @isr
266 | */
267 | CH_IRQ_HANDLER(STM32_USART2_HANDLER) {
268 |
269 | CH_IRQ_PROLOGUE();
270 |
271 | serve_usart_irq(&IUARTD2);
272 |
273 | CH_IRQ_EPILOGUE();
274 | }
275 | #endif /* STM32_IUART_USE_USART2 */
276 |
277 | #if STM32_IUART_USE_USART3 || defined(__DOXYGEN__)
278 | #if !defined(STM32_USART3_HANDLER)
279 | #error "STM32_USART3_HANDLER not defined"
280 | #endif
281 | /**
282 | * @brief USART3 IRQ handler.
283 | *
284 | * @isr
285 | */
286 | CH_IRQ_HANDLER(STM32_USART3_HANDLER) {
287 |
288 | CH_IRQ_PROLOGUE();
289 |
290 | serve_usart_irq(&IUARTD3);
291 |
292 | CH_IRQ_EPILOGUE();
293 | }
294 | #endif /* STM32_IUART_USE_USART3 */
295 |
296 | /*===========================================================================*/
297 | /* Driver exported functions. */
298 | /*===========================================================================*/
299 |
300 | /**
301 | * @brief Low level IUART driver initialization.
302 | *
303 | * @notapi
304 | */
305 | void iuart_lld_init(void) {
306 |
307 | #if STM32_IUART_USE_USART1
308 | iuartObjectInit(&IUARTD1);
309 | IUARTD1.usart = USART1;
310 | #endif
311 |
312 | #if STM32_IUART_USE_USART2
313 | iuartObjectInit(&IUARTD2);
314 | IUARTD2.usart = USART2;
315 | #endif
316 |
317 | #if STM32_IUART_USE_USART3
318 | iuartObjectInit(&IUARTD3);
319 | IUARTD3.usart = USART3;
320 | #endif
321 | }
322 |
323 | /**
324 | * @brief Configures and activates the IUART peripheral.
325 | *
326 | * @param[in] iuartp pointer to the @p IUARTDriver object
327 | *
328 | * @notapi
329 | */
330 | void iuart_lld_start(IUARTDriver *iuartp) {
331 |
332 | if (iuartp->state == IUART_STOP) {
333 | #if STM32_IUART_USE_USART1
334 | if (&IUARTD1 == iuartp)
335 | {
336 | rccEnableUSART1(FALSE);
337 | nvicEnableVector(STM32_USART1_NUMBER, STM32_IUART_USART1_IRQ_PRIORITY);
338 | }
339 | #endif
340 |
341 | #if STM32_IUART_USE_USART2
342 | if (&IUARTD2 == iuartp) {
343 |
344 | rccEnableUSART2(FALSE);
345 | nvicEnableVector(STM32_USART2_NUMBER, STM32_IUART_USART2_IRQ_PRIORITY);
346 | }
347 | #endif
348 |
349 | #if STM32_IUART_USE_USART3
350 | if (&IUARTD3 == iuartp) {
351 | bool b;
352 | rccEnableUSART3(FALSE);
353 | nvicEnableVector(STM32_USART3_NUMBER, STM32_IUART_USART3_IRQ_PRIORITY);
354 | }
355 | #endif
356 |
357 | iuartp->rxbuf = 0;
358 | iuartp->rxCount = 0;
359 | iuartp->rxBuffer = NULL;
360 | }
361 |
362 | iuartp->rxstate = IUART_RX_IDLE;
363 | iuartp->txstate = IUART_TX_IDLE;
364 | usart_start(iuartp);
365 | }
366 |
367 | /**
368 | * @brief Deactivates the IUART peripheral.
369 | *
370 | * @param[in] iuartp pointer to the @p IUARTDriver object
371 | *
372 | * @notapi
373 | */
374 | void iuart_lld_stop(IUARTDriver *iuartp) {
375 |
376 | if (iuartp->state == IUART_READY) {
377 | usart_stop(iuartp);
378 |
379 | #if STM32_IUART_USE_USART1
380 | if (&IUARTD1 == iuartp) {
381 | nvicDisableVector(STM32_USART1_NUMBER);
382 | rccDisableUSART1(FALSE);
383 | return;
384 | }
385 | #endif
386 |
387 | #if STM32_IUART_USE_USART2
388 | if (&IUARTD2 == iuartp) {
389 | nvicDisableVector(STM32_USART2_NUMBER);
390 | rccDisableUSART2(FALSE);
391 | return;
392 | }
393 | #endif
394 |
395 | #if STM32_IUART_USE_USART3
396 | if (&IUARTD3 == iuartp) {
397 | nvicDisableVector(STM32_USART3_NUMBER);
398 | rccDisableUSART3(FALSE);
399 | return;
400 | }
401 | #endif
402 | }
403 | }
404 |
405 | /**
406 | * @brief Starts a transmission on the IUART peripheral.
407 | * @note The buffers are organized as uint8_t arrays for data sizes below
408 | * or equal to 8 bits else it is organized as uint16_t arrays.
409 | *
410 | * @param[in] iuartp pointer to the @p IUARTDriver object
411 | * @param[in] n number of data frames to send
412 | * @param[in] txbuf the pointer to the transmit buffer
413 | *
414 | * @notapi
415 | */
416 | void iuart_lld_start_send(IUARTDriver *iuartp, size_t n, const void *txbuf) {
417 |
418 | if (iuartp->txCount)
419 | {
420 | return; // Already transmission in progress - not much we can do
421 | }
422 | iuartp->txBuf = (uint8_t *)txbuf;
423 | if (0)
424 | {
425 | iuartp->txCount = 2*n; // 16-bit data - @TODO: How do we determine this?
426 | }
427 | else
428 | {
429 | iuartp->txCount = n; // 8-bit data
430 | }
431 |
432 | // Now enable transmit interrupts - just the data interrupt
433 | iuartp->usart->CR1 |= USART_CR1_TXEIE;
434 | }
435 |
436 | /**
437 | * @brief Stops any ongoing transmission.
438 | * @note Stopping a transmission also suppresses the transmission callbacks.
439 | *
440 | * @param[in] iuartp pointer to the @p IUARTDriver object
441 | *
442 | * @return The number of data frames not transmitted by the
443 | * stopped transmit operation.
444 | *
445 | * @notapi
446 | */
447 | size_t iuart_lld_stop_send(IUARTDriver *iuartp) {
448 |
449 | size_t rem = iuartp->txCount;
450 | iuartp->usart->CR1 &= ~(USART_CR1_TXEIE | USART_CR1_TCIE);
451 | iuartp->txCount = 0; // Clear character count and buffer reference
452 | iuartp->txBuf = NULL;
453 | return rem;
454 | }
455 |
456 | /**
457 | * @brief Starts a receive operation on the IUART peripheral.
458 | * @note The buffers are organized as uint8_t arrays for data sizes below
459 | * or equal to 8 bits else it is organized as uint16_t arrays.
460 | *
461 | * @param[in] iuartp pointer to the @p IUARTDriver object
462 | * @param[in] n number of data frames to receive
463 | * @param[out] rxbuf the pointer to the receive buffer
464 | *
465 | * @notapi
466 | */
467 | void iuart_lld_start_receive(IUARTDriver *iuartp, size_t n, void *rxbuf) {
468 |
469 |
470 | /* Just copy across new info - abandon any previous receive in progress */
471 | osalSysLock();
472 | iuartp->rxBuffer = rxbuf;
473 | iuartp->rxCount = n;
474 | iuartp->rxstate = IUART_RX_ACTIVE;
475 | osalSysUnlock();
476 | }
477 |
478 | /**
479 | * @brief Stops any ongoing receive operation.
480 | * @note Stopping a receive operation also suppresses the receive callbacks.
481 | *
482 | * @param[in] iuartp pointer to the @p IUARTDriver object
483 | *
484 | * @return The number of data frames not received by the
485 | * stopped receive operation.
486 | *
487 | * @notapi
488 | */
489 | size_t iuart_lld_stop_receive(IUARTDriver *iuartp) {
490 | size_t n;
491 |
492 | osalSysLock();
493 | iuartp->rxBuffer = NULL;
494 | n = iuartp->rxCount;
495 | iuartp->rxCount = 0;
496 | iuartp->rxstate = IUART_RX_IDLE;
497 | osalSysUnlock();
498 |
499 | return n;
500 | }
501 |
502 | #endif /* DRIVER_USE_IUART */
503 |
504 | /** @} */
505 |
--------------------------------------------------------------------------------
/stm32/iuart_driver_lld.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 |
17 | IUART Driver modified to use interrupts throughout, as an option; just define:
18 | STM32_IUART_USE_INTERRUPTS TRUE
19 | or STM32_IUART_USE_DMA TRUE
20 | */
21 |
22 | /**
23 | * @file STM32/USARTv2/iuart_lld.h
24 | * @brief STM32 low level IUART driver header.
25 | *
26 | * @addtogroup IUART
27 | * @{
28 | */
29 | /**
30 | * Allows selection between DMA (the default) and interrupts for data transfer
31 | *
32 | * To enable interrupt handling, add to mcuconf.h:
33 | * #define STM32_IUART_USE_INTERRUPTS TRUE
34 | *
35 | * This enables interrupt handling for all defined IUART channels, releasing DMA
36 | * channels for other purposes.
37 | */
38 |
39 | #ifndef _IUART_LLD_H_
40 | #define _IUART_LLD_H_
41 |
42 | #if DRIVER_USE_IUART || defined(__DOXYGEN__)
43 |
44 | /*===========================================================================*/
45 | /* Driver constants. */
46 | /*===========================================================================*/
47 |
48 | /*===========================================================================*/
49 | /* Driver pre-compile time settings. */
50 | /*===========================================================================*/
51 |
52 | /**
53 | * @name Configuration options
54 | * @{
55 | */
56 | /**
57 | * @brief IUART driver on USART1 enable switch.
58 | * @details If set to @p TRUE the support for USART1 is included.
59 | * @note The default is @p FALSE.
60 | */
61 | #if !defined(STM32_IUART_USE_USART1) || defined(__DOXYGEN__)
62 | #define STM32_IUART_USE_USART1 FALSE
63 | #endif
64 |
65 | /**
66 | * @brief IUART driver on USART2 enable switch.
67 | * @details If set to @p TRUE the support for USART2 is included.
68 | * @note The default is @p FALSE.
69 | */
70 | #if !defined(STM32_IUART_USE_USART2) || defined(__DOXYGEN__)
71 | #define STM32_IUART_USE_USART2 FALSE
72 | #endif
73 |
74 | /**
75 | * @brief IUART driver on USART3 enable switch.
76 | * @details If set to @p TRUE the support for USART3 is included.
77 | * @note The default is @p FALSE.
78 | */
79 | #if !defined(STM32_IUART_USE_USART3) || defined(__DOXYGEN__)
80 | #define STM32_IUART_USE_USART3 FALSE
81 | #endif
82 |
83 | /**
84 | * @brief USART1 interrupt priority level setting.
85 | */
86 | #if !defined(STM32_IUART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
87 | #define STM32_IUART_USART1_IRQ_PRIORITY 12
88 | #endif
89 |
90 | /**
91 | * @brief USART2 interrupt priority level setting.
92 | */
93 | #if !defined(STM32_IUART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
94 | #define STM32_IUART_USART2_IRQ_PRIORITY 12
95 | #endif
96 |
97 | /**
98 | * @brief USART3 interrupt priority level setting.
99 | */
100 | #if !defined(STM32_IUART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
101 | #define STM32_IUART_USART3_IRQ_PRIORITY 12
102 | #endif
103 |
104 | /*===========================================================================*/
105 | /* Derived constants and error checks. */
106 | /*===========================================================================*/
107 |
108 | #if STM32_IUART_USE_USART1 && !STM32_HAS_USART1
109 | #error "USART1 not present in the selected device"
110 | #endif
111 |
112 | #if STM32_IUART_USE_USART2 && !STM32_HAS_USART2
113 | #error "USART2 not present in the selected device"
114 | #endif
115 |
116 | #if STM32_IUART_USE_USART3 && !STM32_HAS_USART3
117 | #error "USART3 not present in the selected device"
118 | #endif
119 |
120 | #if !STM32_IUART_USE_USART1 && !STM32_IUART_USE_USART2 && \
121 | !STM32_IUART_USE_USART3
122 | #error "IUART driver activated but no USART/IUART peripheral assigned"
123 | #endif
124 |
125 | #if STM32_IUART_USE_USART1 && \
126 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_IUART_USART1_IRQ_PRIORITY)
127 | #error "Invalid IRQ priority assigned to USART1"
128 | #endif
129 |
130 | #if STM32_IUART_USE_USART2 && \
131 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_IUART_USART2_IRQ_PRIORITY)
132 | #error "Invalid IRQ priority assigned to USART2"
133 | #endif
134 |
135 | #if STM32_IUART_USE_USART3 && \
136 | !CORTEX_IS_VALID_KERNEL_PRIORITY(STM32_IUART_USART3_IRQ_PRIORITY)
137 | #error "Invalid IRQ priority assigned to USART3"
138 | #endif
139 |
140 | /*===========================================================================*/
141 | /* Driver data structures and types. */
142 | /*===========================================================================*/
143 |
144 | /**
145 | * @brief IUART driver condition flags type.
146 | */
147 | typedef uint32_t iuartflags_t;
148 |
149 | /**
150 | * @brief Structure representing an IUART driver.
151 | */
152 | typedef struct IUARTDriver IUARTDriver;
153 |
154 | /**
155 | * @brief Generic IUART notification callback type.
156 | *
157 | * @param[in] iuartp pointer to the @p IUARTDriver object
158 | */
159 | typedef void (*iuartcb_t)(IUARTDriver *iuartp);
160 |
161 | /**
162 | * @brief Character received IUART notification callback type.
163 | *
164 | * @param[in] iuartp pointer to the @p IUARTDriver object
165 | * @param[in] c received character
166 | */
167 | typedef void (*iuartccb_t)(IUARTDriver *iuartp, uint16_t c);
168 |
169 | /**
170 | * @brief Receive error IUART notification callback type.
171 | *
172 | * @param[in] iuartp pointer to the @p IUARTDriver object
173 | * @param[in] e receive error mask
174 | */
175 | typedef void (*iuartecb_t)(IUARTDriver *iuartp, iuartflags_t e);
176 |
177 | /**
178 | * @brief Driver configuration structure.
179 | * @note It could be empty on some architectures.
180 | */
181 | typedef struct {
182 | /**
183 | * @brief End of transmission buffer callback.
184 | */
185 | iuartcb_t txend1_cb;
186 | /**
187 | * @brief Physical end of transmission callback.
188 | */
189 | iuartcb_t txend2_cb;
190 | /**
191 | * @brief Receive buffer filled callback.
192 | */
193 | iuartcb_t rxend_cb;
194 | /**
195 | * @brief Character received while out if the @p IUART_RECEIVE state.
196 | */
197 | iuartccb_t rxchar_cb;
198 | /**
199 | * @brief Receive error callback.
200 | */
201 | iuartecb_t rxerr_cb;
202 | /* End of the mandatory fields.*/
203 | /**
204 | * @brief Bit rate.
205 | */
206 | uint32_t speed;
207 | /**
208 | * @brief Initialization value for the CR1 register.
209 | */
210 | uint32_t cr1;
211 | /**
212 | * @brief Initialization value for the CR2 register.
213 | */
214 | uint32_t cr2;
215 | /**
216 | * @brief Initialization value for the CR3 register.
217 | */
218 | uint32_t cr3;
219 | } IUARTConfig;
220 |
221 | /**
222 | * @brief Structure representing an IUART driver.
223 | */
224 | struct IUARTDriver {
225 | /**
226 | * @brief Driver state.
227 | */
228 | iuartstate_t state;
229 | /**
230 | * @brief Transmitter state.
231 | */
232 | iuarttxstate_t txstate;
233 | /**
234 | * @brief Receiver state.
235 | */
236 | iuartrxstate_t rxstate;
237 | /**
238 | * @brief Current configuration data.
239 | */
240 | const IUARTConfig *config;
241 | #if defined(IUART_DRIVER_EXT_FIELDS)
242 | IUART_DRIVER_EXT_FIELDS
243 | #endif
244 | /* End of the mandatory fields.*/
245 | /**
246 | * @brief Pointer to the USART registers block.
247 | */
248 | USART_TypeDef *usart;
249 |
250 | /**
251 | * @brief Default receive buffer while into @p IUART_RX_IDLE state.
252 | */
253 | volatile uint16_t rxbuf;
254 |
255 | volatile uint16_t txCount; // Number of bytes in transmit buffer
256 | volatile uint8_t *txBuf; // Pointer to current transmit buffer
257 | volatile uint16_t rxCount; // Number of bytes for 'active' receive
258 | volatile uint8_t *rxBuffer; // Pointer to receive buffer if block receive active
259 | };
260 |
261 | /*===========================================================================*/
262 | /* Driver macros. */
263 | /*===========================================================================*/
264 |
265 | /*===========================================================================*/
266 | /* External declarations. */
267 | /*===========================================================================*/
268 |
269 | #if STM32_IUART_USE_USART1 && !defined(__DOXYGEN__)
270 | extern IUARTDriver IUARTD1;
271 | #endif
272 |
273 | #if STM32_IUART_USE_USART2 && !defined(__DOXYGEN__)
274 | extern IUARTDriver IUARTD2;
275 | #endif
276 |
277 | #if STM32_IUART_USE_USART3 && !defined(__DOXYGEN__)
278 | extern IUARTDriver IUARTD3;
279 | #endif
280 |
281 | #ifdef __cplusplus
282 | extern "C" {
283 | #endif
284 | void iuart_lld_init(void);
285 | void iuart_lld_start(IUARTDriver *iuartp);
286 | void iuart_lld_stop(IUARTDriver *iuartp);
287 | void iuart_lld_start_send(IUARTDriver *iuartp, size_t n, const void *txbuf);
288 | size_t iuart_lld_stop_send(IUARTDriver *iuartp);
289 | void iuart_lld_start_receive(IUARTDriver *iuartp, size_t n, void *rxbuf);
290 | size_t iuart_lld_stop_receive(IUARTDriver *iuartp);
291 | #ifdef __cplusplus
292 | }
293 | #endif
294 |
295 | #endif /* DRIVER_USE_IUART */
296 |
297 | #endif /* _IUART_LLD_H_ */
298 |
299 | /** @} */
300 |
--------------------------------------------------------------------------------
/stm32/iwdg_driver_lld.c:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | ---
21 |
22 | A special exception to the GPL can be applied should you wish to distribute
23 | a combined work that includes ChibiOS/RT, without being obliged to provide
24 | the source code for any proprietary components. See the file exception.txt
25 | for full details of how and when the exception can be applied.
26 | */
27 |
28 | /**
29 | * @file templates/xxx_lld.c
30 | * @brief IWDG Driver subsystem low level driver source template.
31 | *
32 | * @addtogroup IWDG
33 | * @{
34 | */
35 |
36 | #include "ch.h"
37 | #include "hal.h"
38 |
39 | #include "iwdg_driver.h"
40 |
41 | #if DRIVER_USE_IWDG || defined(__DOXYGEN__)
42 |
43 | /*===========================================================================*/
44 | /* Driver local definitions. */
45 | /*===========================================================================*/
46 | #define KR_KEY_Reload ((uint16_t)0xAAAA)
47 | #define KR_KEY_Enable ((uint16_t)0xCCCC)
48 | #define KR_KEY_Write ((uint16_t)0x5555)
49 | #define KR_KEY_Protect ((uint16_t)0x0000)
50 |
51 | /*===========================================================================*/
52 | /* Driver exported variables. */
53 | /*===========================================================================*/
54 | IWDGDriver IWDGD;
55 | /*===========================================================================*/
56 | /* Driver local variables. */
57 | /*===========================================================================*/
58 |
59 | /*===========================================================================*/
60 | /* Driver local functions. */
61 | /*===========================================================================*/
62 |
63 | /*===========================================================================*/
64 | /* Driver interrupt handlers. */
65 | /*===========================================================================*/
66 |
67 | /*===========================================================================*/
68 | /* Driver exported functions. */
69 | /*===========================================================================*/
70 |
71 | /**
72 | * @brief Low level IWDG driver initialization.
73 | *
74 | * @notapi
75 | */
76 | void iwdg_lld_init(void) {
77 | IWDGD.state = IWDG_STOP;
78 | IWDGD.iwdg = IWDG;
79 | }
80 |
81 | /**
82 | * @brief Configures and activates the IWDG peripheral.
83 | *
84 | * @param[in] iwdgp pointer to the @p IWDGDriver object
85 | * @param[in] ms IWDG reload time in milliseconds.
86 | *
87 | * @notapi
88 | */
89 | void iwdg_lld_start( IWDGDriver *iwdgp, const IWDGConfig *cfg )
90 | {
91 | // Clock speed is 40'000Hz
92 | // Max counter value is 2^12-1.
93 |
94 | IWDG_TypeDef * d = iwdgp->iwdg;
95 | d->KR = KR_KEY_Write;
96 | d->PR = cfg->div;
97 | d->RLR = (cfg->counter <= IWDG_COUNTER_MAX) ? cfg->counter : IWDG_COUNTER_MAX;
98 | d->KR = KR_KEY_Reload;
99 | d->KR = KR_KEY_Enable;
100 | }
101 |
102 | /**
103 | * @brief Reloads IWDG's counter.
104 | *
105 | * @param[in] idwgp pointer to the @p IWDGDriver object
106 | *
107 | * @notapi
108 | */
109 | void iwdg_lld_reset( IWDGDriver * iwdgp )
110 | {
111 | iwdgp->iwdg->KR = KR_KEY_Reload;
112 | }
113 |
114 | #endif /* DRIVER_USE_XXX */
115 |
116 | /** @} */
117 |
--------------------------------------------------------------------------------
/stm32/iwdg_driver_lld.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
3 | 2011,2012 Giovanni Di Sirio.
4 |
5 | This file is part of ChibiOS/RT.
6 |
7 | ChibiOS/RT is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | ChibiOS/RT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | ---
21 |
22 | A special exception to the GPL can be applied should you wish to distribute
23 | a combined work that includes ChibiOS/RT, without being obliged to provide
24 | the source code for any proprietary components. See the file exception.txt
25 | for full details of how and when the exception can be applied.
26 | */
27 |
28 | /**
29 | * @file templates/xxx_lld.h
30 | * @brief IWDG Driver subsystem low level driver header template.
31 | *
32 | * @addtogroup IWDG
33 | * @{
34 | */
35 |
36 | #ifndef _IWDG_LLD_H_
37 | #define _IWDG_LLD_H_
38 |
39 | #if DRIVER_USE_IWDG || defined(__DOXYGEN__)
40 |
41 | /*===========================================================================*/
42 | /* Driver constants. */
43 | /*===========================================================================*/
44 | #define IWDG_COUNTER_MAX ( (1<<12)-1 )
45 | #define IWDG_DIV_4 0
46 | #define IWDG_DIV_8 1
47 | #define IWDG_DIV_16 2
48 | #define IWDG_DIV_32 3
49 | #define IWDG_DIV_64 4
50 | #define IWDG_DIV_128 5
51 | #define IWDG_DIV_256 6
52 | /*===========================================================================*/
53 | /* Driver pre-compile time settings. */
54 | /*===========================================================================*/
55 |
56 | /*===========================================================================*/
57 | /* Derived constants and error checks. */
58 | /*===========================================================================*/
59 |
60 | /*===========================================================================*/
61 | /* Driver data structures and types. */
62 | /*===========================================================================*/
63 |
64 | /**
65 | * @brief Type of a structure representing an IWDG driver.
66 | */
67 | //typedef struct IWDGDriver IWDGDriver;
68 |
69 | /**
70 | * @brief Driver configuration structure.
71 | * @note It could be empty on some architectures.
72 | */
73 | typedef struct {
74 | uint16_t counter;
75 | uint8_t div;
76 | } IWDGConfig;
77 |
78 | /**
79 | * @brief Structure representing an IWDG driver.
80 | */
81 | struct IWDGDriver {
82 | /**
83 | * @brief Driver state.
84 | */
85 | iwdgstate_t state;
86 | /* End of the mandatory fields.*/
87 | IWDG_TypeDef *iwdg;
88 | };
89 |
90 | typedef struct IWDGDriver IWDGDriver;
91 |
92 | extern IWDGDriver IWDGD;
93 |
94 | /*===========================================================================*/
95 | /* Driver macros. */
96 | /*===========================================================================*/
97 |
98 | /*===========================================================================*/
99 | /* External declarations. */
100 | /*===========================================================================*/
101 |
102 | #ifdef __cplusplus
103 | extern "C" {
104 | #endif
105 | void iwdg_lld_init(void);
106 | void iwdg_lld_start( IWDGDriver *iwdgp, const IWDGConfig *cfg );
107 | void iwdg_lld_reset( IWDGDriver *iwdgp );
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /* DRIVER_USE_IWDG */
113 |
114 | #endif /* _IWDG_LLD_H_ */
115 |
116 | /** @} */
117 |
--------------------------------------------------------------------------------
/stm32/timcap_driver_lld.h:
--------------------------------------------------------------------------------
1 | /*
2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | /**
18 | * @file STM32/timcap_lld.h
19 | * @brief STM32 TIMCAP subsystem low level driver header.
20 | *
21 | * @addtogroup TIMCAP
22 | * @{
23 | */
24 |
25 | #ifndef _TIMCAP_LLD_H_
26 | #define _TIMCAP_LLD_H_
27 |
28 | #include "ch.h"
29 | #include "hal.h"
30 | #include "stm32_tim.h"
31 |
32 |
33 | #if DRIVER_USE_TIMCAP || defined(__DOXYGEN__)
34 |
35 | /*===========================================================================*/
36 | /* Driver constants. */
37 | /*===========================================================================*/
38 |
39 | /*===========================================================================*/
40 | /* Driver pre-compile time settings. */
41 | /*===========================================================================*/
42 |
43 | /**
44 | * @name Configuration options
45 | * @{
46 | */
47 | /**
48 | * @brief TIMCAPD1 driver enable switch.
49 | * @details If set to @p TRUE the support for TIMCAPD1 is included.
50 | * @note The default is @p TRUE.
51 | */
52 | #if !defined(STM32_TIMCAP_USE_TIM1) || defined(__DOXYGEN__)
53 | #define STM32_TIMCAP_USE_TIM1 FALSE
54 | #endif
55 |
56 | /**
57 | * @brief TIMCAPD2 driver enable switch.
58 | * @details If set to @p TRUE the support for TIMCAPD2 is included.
59 | * @note The default is @p TRUE.
60 | */
61 | #if !defined(STM32_TIMCAP_USE_TIM2) || defined(__DOXYGEN__)
62 | #define STM32_TIMCAP_USE_TIM2 FALSE
63 | #endif
64 |
65 | /**
66 | * @brief TIMCAPD3 driver enable switch.
67 | * @details If set to @p TRUE the support for TIMCAPD3 is included.
68 | * @note The default is @p TRUE.
69 | */
70 | #if !defined(STM32_TIMCAP_USE_TIM3) || defined(__DOXYGEN__)
71 | #define STM32_TIMCAP_USE_TIM3 FALSE
72 | #endif
73 |
74 | /**
75 | * @brief TIMCAPD4 driver enable switch.
76 | * @details If set to @p TRUE the support for TIMCAPD4 is included.
77 | * @note The default is @p TRUE.
78 | */
79 | #if !defined(STM32_TIMCAP_USE_TIM4) || defined(__DOXYGEN__)
80 | #define STM32_TIMCAP_USE_TIM4 FALSE
81 | #endif
82 |
83 | /**
84 | * @brief TIMCAPD5 driver enable switch.
85 | * @details If set to @p TRUE the support for TIMCAPD5 is included.
86 | * @note The default is @p TRUE.
87 | */
88 | #if !defined(STM32_TIMCAP_USE_TIM5) || defined(__DOXYGEN__)
89 | #define STM32_TIMCAP_USE_TIM5 FALSE
90 | #endif
91 |
92 | /**
93 | * @brief TIMCAPD8 driver enable switch.
94 | * @details If set to @p TRUE the support for TIMCAPD8 is included.
95 | * @note The default is @p TRUE.
96 | */
97 | #if !defined(STM32_TIMCAP_USE_TIM8) || defined(__DOXYGEN__)
98 | #define STM32_TIMCAP_USE_TIM8 FALSE
99 | #endif
100 |
101 | /**
102 | * @brief TIMCAPD9 driver enable switch.
103 | * @details If set to @p TRUE the support for TIMCAPD9 is included.
104 | * @note The default is @p TRUE.
105 | */
106 | #if !defined(STM32_TIMCAP_USE_TIM9) || defined(__DOXYGEN__)
107 | #define STM32_TIMCAP_USE_TIM9 FALSE
108 | #endif
109 |
110 | /**
111 | * @brief TIMCAPD1 interrupt priority level setting.
112 | */
113 | #if !defined(STM32_TIMCAP_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
114 | #define STM32_TIMCAP_TIM1_IRQ_PRIORITY 7
115 | #endif
116 |
117 | /**
118 | * @brief TIMCAPD2 interrupt priority level setting.
119 | */
120 | #if !defined(STM32_TIMCAP_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
121 | #define STM32_TIMCAP_TIM2_IRQ_PRIORITY 7
122 | #endif
123 |
124 | /**
125 | * @brief TIMCAPD3 interrupt priority level setting.
126 | */
127 | #if !defined(STM32_TIMCAP_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
128 | #define STM32_TIMCAP_TIM3_IRQ_PRIORITY 7
129 | #endif
130 |
131 | /**
132 | * @brief TIMCAPD4 interrupt priority level setting.
133 | */
134 | #if !defined(STM32_TIMCAP_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
135 | #define STM32_TIMCAP_TIM4_IRQ_PRIORITY 7
136 | #endif
137 |
138 | /**
139 | * @brief TIMCAPD5 interrupt priority level setting.
140 | */
141 | #if !defined(STM32_TIMCAP_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
142 | #define STM32_TIMCAP_TIM5_IRQ_PRIORITY 7
143 | #endif
144 |
145 | /**
146 | * @brief TIMCAPD8 interrupt priority level setting.
147 | */
148 | #if !defined(STM32_TIMCAP_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
149 | #define STM32_TIMCAP_TIM8_IRQ_PRIORITY 7
150 | #endif
151 |
152 | /**
153 | * @brief TIMCAPD9 interrupt priority level setting.
154 | */
155 | #if !defined(STM32_TIMCAP_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__)
156 | #define STM32_TIMCAP_TIM9_IRQ_PRIORITY 7
157 | #endif
158 | /** @} */
159 |
160 | /*===========================================================================*/
161 | /* Derived constants and error checks. */
162 | /*===========================================================================*/
163 |
164 | #if STM32_TIMCAP_USE_TIM1 && !STM32_HAS_TIM1
165 | #error "TIM1 not present in the selected device"
166 | #endif
167 |
168 | #if STM32_TIMCAP_USE_TIM2 && !STM32_HAS_TIM2
169 | #error "TIM2 not present in the selected device"
170 | #endif
171 |
172 | #if STM32_TIMCAP_USE_TIM3 && !STM32_HAS_TIM3
173 | #error "TIM3 not present in the selected device"
174 | #endif
175 |
176 | #if STM32_TIMCAP_USE_TIM4 && !STM32_HAS_TIM4
177 | #error "TIM4 not present in the selected device"
178 | #endif
179 |
180 | #if STM32_TIMCAP_USE_TIM5 && !STM32_HAS_TIM5
181 | #error "TIM5 not present in the selected device"
182 | #endif
183 |
184 | #if STM32_TIMCAP_USE_TIM8 && !STM32_HAS_TIM8
185 | #error "TIM8 not present in the selected device"
186 | #endif
187 |
188 | #if STM32_TIMCAP_USE_TIM9 && !STM32_HAS_TIM9
189 | #error "TIM9 not present in the selected device"
190 | #endif
191 |
192 | #if !STM32_TIMCAP_USE_TIM1 && !STM32_TIMCAP_USE_TIM2 && \
193 | !STM32_TIMCAP_USE_TIM3 && !STM32_TIMCAP_USE_TIM4 && \
194 | !STM32_TIMCAP_USE_TIM5 && !STM32_TIMCAP_USE_TIM8 && \
195 | !STM32_TIMCAP_USE_TIM9
196 | #error "TIMCAP driver activated but no TIM peripheral assigned"
197 | #endif
198 |
199 | #if STM32_TIMCAP_USE_TIM1 && \
200 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM1_IRQ_PRIORITY)
201 | #error "Invalid IRQ priority assigned to TIM1"
202 | #endif
203 |
204 | #if STM32_TIMCAP_USE_TIM2 && \
205 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM2_IRQ_PRIORITY)
206 | #error "Invalid IRQ priority assigned to TIM2"
207 | #endif
208 |
209 | #if STM32_TIMCAP_USE_TIM3 && \
210 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM3_IRQ_PRIORITY)
211 | #error "Invalid IRQ priority assigned to TIM3"
212 | #endif
213 |
214 | #if STM32_TIMCAP_USE_TIM4 && \
215 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM4_IRQ_PRIORITY)
216 | #error "Invalid IRQ priority assigned to TIM4"
217 | #endif
218 |
219 | #if STM32_TIMCAP_USE_TIM5 && \
220 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM5_IRQ_PRIORITY)
221 | #error "Invalid IRQ priority assigned to TIM5"
222 | #endif
223 |
224 | #if STM32_TIMCAP_USE_TIM8 && \
225 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM8_IRQ_PRIORITY)
226 | #error "Invalid IRQ priority assigned to TIM8"
227 | #endif
228 |
229 | #if STM32_TIMCAP_USE_TIM9 && \
230 | !OSAL_IRQ_IS_VALID_PRIORITY(STM32_TIMCAP_TIM9_IRQ_PRIORITY)
231 | #error "Invalid IRQ priority assigned to TIM9"
232 | #endif
233 |
234 | /*===========================================================================*/
235 | /* Driver data structures and types. */
236 | /*===========================================================================*/
237 |
238 | /**
239 | * @brief TIMCAP driver mode.
240 | */
241 | typedef enum {
242 | TIMCAP_INPUT_DISABLED = 0,
243 | TIMCAP_INPUT_ACTIVE_HIGH = 1, /**< Trigger on rising edge. */
244 | TIMCAP_INPUT_ACTIVE_LOW = 2, /**< Trigger on falling edge. */
245 | } timcapmode_t;
246 |
247 | /**
248 | * @brief TIMCAP frequency type.
249 | */
250 | typedef uint32_t timcapfreq_t;
251 |
252 | /**
253 | * @brief TIMCAP channel type.
254 | */
255 | typedef enum {
256 | TIMCAP_CHANNEL_1 = 0, /**< Use TIMxCH1. */
257 | TIMCAP_CHANNEL_2 = 1, /**< Use TIMxCH2. */
258 | TIMCAP_CHANNEL_3 = 2, /**< Use TIMxCH3. */
259 | TIMCAP_CHANNEL_4 = 3, /**< Use TIMxCH4. */
260 | } timcapchannel_t;
261 |
262 |
263 | /**
264 | * @brief Driver configuration structure.
265 | * @note It could be empty on some architectures.
266 | */
267 | typedef struct {
268 | /**
269 | * @brief Driver mode.
270 | */
271 | timcapmode_t modes[4];
272 | /**
273 | * @brief Timer clock in Hz.
274 | * @note The low level can use assertions in order to catch invalid
275 | * frequency specifications.
276 | */
277 | timcapfreq_t frequency;
278 |
279 | /**
280 | * @brief Callback when a capture occurs
281 | */
282 | timcapcallback_t capture_cb_array[4];
283 |
284 | /**
285 | * @brief Callback for timer overflow.
286 | */
287 | timcapcallback_t overflow_cb;
288 |
289 | /* End of the mandatory fields.*/
290 |
291 | /**
292 | * @brief TIM DIER register initialization data.
293 | * @note The value of this field should normally be equal to zero.
294 | * @note Only the DMA-related bits can be specified in this field.
295 | */
296 | uint32_t dier;
297 |
298 | /**
299 | * @brief TIM CR1 register initialization data.
300 | * @note The value of this field should normally be equal to zero.
301 | */
302 | uint32_t cr1;
303 | } TIMCAPConfig;
304 |
305 | /**
306 | * @brief Structure representing an TIMCAP driver.
307 | */
308 | struct TIMCAPDriver {
309 | /**
310 | * @brief Driver state.
311 | */
312 | timcapstate_t state;
313 | /**
314 | * @brief Current configuration data.
315 | */
316 | const TIMCAPConfig *config;
317 | #if defined(TIMCAP_DRIVER_EXT_FIELDS)
318 | TIMCAP_DRIVER_EXT_FIELDS
319 | #endif
320 | /* End of the mandatory fields.*/
321 | /**
322 | * @brief Timer base clock.
323 | */
324 | uint32_t clock;
325 | /**
326 | * @brief Pointer to the TIMx registers block.
327 | */
328 | stm32_tim_t *tim;
329 | /**
330 | * @brief CCR register used for capture.
331 | */
332 | volatile uint32_t *ccr_p[4];
333 | };
334 |
335 | /*===========================================================================*/
336 | /* Driver macros. */
337 | /*===========================================================================*/
338 |
339 | //FIXME document this
340 | #define timcap_lld_get_ccr(timcapp, channel) (*((timcapp)->ccr_p[channel]) + 1)
341 |
342 | /*===========================================================================*/
343 | /* External declarations. */
344 | /*===========================================================================*/
345 |
346 | #if STM32_TIMCAP_USE_TIM1 && !defined(__DOXYGEN__)
347 | extern TIMCAPDriver TIMCAPD1;
348 | #endif
349 |
350 | #if STM32_TIMCAP_USE_TIM2 && !defined(__DOXYGEN__)
351 | extern TIMCAPDriver TIMCAPD2;
352 | #endif
353 |
354 | #if STM32_TIMCAP_USE_TIM3 && !defined(__DOXYGEN__)
355 | extern TIMCAPDriver TIMCAPD3;
356 | #endif
357 |
358 | #if STM32_TIMCAP_USE_TIM4 && !defined(__DOXYGEN__)
359 | extern TIMCAPDriver TIMCAPD4;
360 | #endif
361 |
362 | #if STM32_TIMCAP_USE_TIM5 && !defined(__DOXYGEN__)
363 | extern TIMCAPDriver TIMCAPD5;
364 | #endif
365 |
366 | #if STM32_TIMCAP_USE_TIM8 && !defined(__DOXYGEN__)
367 | extern TIMCAPDriver TIMCAPD8;
368 | #endif
369 |
370 | #if STM32_TIMCAP_USE_TIM9 && !defined(__DOXYGEN__)
371 | extern TIMCAPDriver TIMCAPD9;
372 | #endif
373 |
374 | #ifdef __cplusplus
375 | extern "C" {
376 | #endif
377 | void timcap_lld_init(void);
378 | void timcap_lld_start(TIMCAPDriver *timcapp);
379 | void timcap_lld_stop(TIMCAPDriver *timcapp);
380 | void timcap_lld_enable(TIMCAPDriver *timcapp);
381 | void timcap_lld_disable(TIMCAPDriver *timcapp);
382 | #ifdef __cplusplus
383 | }
384 | #endif
385 |
386 | #endif /* DRIVER_USE_TIMCAP */
387 |
388 | #endif /* _TIMCAP_LLD_H_ */
389 |
390 | /** @} */
391 |
--------------------------------------------------------------------------------