├── 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 | --------------------------------------------------------------------------------