From 4edc5aeca7251e69dfa772dfdd5b2e012375a809 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Wed, 23 Mar 2016 12:36:05 +0000 Subject: Mass renaming of HAL files. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9151 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/ports/ARM/chcore_timer.h | 2 +- os/common/ports/ARMCMx/chcore_timer.h | 2 +- os/common/ports/AVR/chcore_timer.h | 2 +- os/hal/hal.mk | 86 +-- os/hal/include/adc.h | 278 --------- os/hal/include/can.h | 156 ----- os/hal/include/dac.h | 267 --------- os/hal/include/ext.h | 150 ----- os/hal/include/gpt.h | 141 ----- os/hal/include/hal.h | 49 +- os/hal/include/hal_adc.h | 278 +++++++++ os/hal/include/hal_can.h | 156 +++++ os/hal/include/hal_dac.h | 267 +++++++++ os/hal/include/hal_ext.h | 150 +++++ os/hal/include/hal_gpt.h | 141 +++++ os/hal/include/hal_i2c.h | 166 ++++++ os/hal/include/hal_i2s.h | 167 ++++++ os/hal/include/hal_icu.h | 238 ++++++++ os/hal/include/hal_mac.h | 204 +++++++ os/hal/include/hal_mmc_spi.h | 195 +++++++ os/hal/include/hal_pal.h | 642 +++++++++++++++++++++ os/hal/include/hal_pwm.h | 308 ++++++++++ os/hal/include/hal_rtc.h | 144 +++++ os/hal/include/hal_sdc.h | 195 +++++++ os/hal/include/hal_serial.h | 286 ++++++++++ os/hal/include/hal_serial_usb.h | 195 +++++++ os/hal/include/hal_spi.h | 291 ++++++++++ os/hal/include/hal_st.h | 97 ++++ os/hal/include/hal_uart.h | 342 +++++++++++ os/hal/include/hal_usb.h | 633 +++++++++++++++++++++ os/hal/include/hal_wdg.h | 89 +++ os/hal/include/i2c.h | 166 ------ os/hal/include/i2s.h | 167 ------ os/hal/include/icu.h | 238 -------- os/hal/include/mac.h | 202 ------- os/hal/include/mmc_spi.h | 195 ------- os/hal/include/pal.h | 642 --------------------- os/hal/include/pwm.h | 308 ---------- os/hal/include/rtc.h | 144 ----- os/hal/include/sdc.h | 195 ------- os/hal/include/serial.h | 286 ---------- os/hal/include/serial_usb.h | 195 ------- os/hal/include/spi.h | 291 ---------- os/hal/include/st.h | 97 ---- os/hal/include/uart.h | 342 ----------- os/hal/include/usb.h | 633 --------------------- os/hal/include/wdg.h | 89 --- os/hal/src/adc.c | 321 ----------- os/hal/src/can.c | 361 ------------ os/hal/src/dac.c | 349 ------------ os/hal/src/ext.c | 202 ------- os/hal/src/gpt.c | 262 --------- os/hal/src/hal.c | 144 ----- os/hal/src/hal_adc.c | 321 +++++++++++ os/hal/src/hal_can.c | 361 ++++++++++++ os/hal/src/hal_dac.c | 349 ++++++++++++ os/hal/src/hal_ext.c | 202 +++++++ os/hal/src/hal_gpt.c | 262 +++++++++ os/hal/src/hal_hal.c | 144 +++++ os/hal/src/hal_i2c.c | 283 ++++++++++ os/hal/src/hal_i2s.c | 155 +++++ os/hal/src/hal_icu.c | 225 ++++++++ os/hal/src/hal_mac.c | 268 +++++++++ os/hal/src/hal_mmc_spi.c | 918 ++++++++++++++++++++++++++++++ os/hal/src/hal_pal.c | 122 ++++ os/hal/src/hal_pwm.c | 309 ++++++++++ os/hal/src/hal_rtc.c | 321 +++++++++++ os/hal/src/hal_sdc.c | 1005 +++++++++++++++++++++++++++++++++ os/hal/src/hal_serial.c | 289 ++++++++++ os/hal/src/hal_serial_usb.c | 502 ++++++++++++++++ os/hal/src/hal_spi.c | 416 ++++++++++++++ os/hal/src/hal_st.c | 130 +++++ os/hal/src/hal_uart.c | 515 +++++++++++++++++ os/hal/src/hal_usb.c | 950 +++++++++++++++++++++++++++++++ os/hal/src/hal_wdg.c | 120 ++++ os/hal/src/i2c.c | 283 ---------- os/hal/src/i2s.c | 155 ----- os/hal/src/icu.c | 225 -------- os/hal/src/mac.c | 268 --------- os/hal/src/mmc_spi.c | 918 ------------------------------ os/hal/src/pal.c | 122 ---- os/hal/src/pwm.c | 309 ---------- os/hal/src/rtc.c | 321 ----------- os/hal/src/sdc.c | 1005 --------------------------------- os/hal/src/serial.c | 289 ---------- os/hal/src/serial_usb.c | 502 ---------------- os/hal/src/spi.c | 416 -------------- os/hal/src/st.c | 130 ----- os/hal/src/uart.c | 515 ----------------- os/hal/src/usb.c | 950 ------------------------------- os/hal/src/wdg.c | 120 ---- 91 files changed, 13421 insertions(+), 13420 deletions(-) delete mode 100644 os/hal/include/adc.h delete mode 100644 os/hal/include/can.h delete mode 100644 os/hal/include/dac.h delete mode 100644 os/hal/include/ext.h delete mode 100644 os/hal/include/gpt.h create mode 100644 os/hal/include/hal_adc.h create mode 100644 os/hal/include/hal_can.h create mode 100644 os/hal/include/hal_dac.h create mode 100644 os/hal/include/hal_ext.h create mode 100644 os/hal/include/hal_gpt.h create mode 100644 os/hal/include/hal_i2c.h create mode 100644 os/hal/include/hal_i2s.h create mode 100644 os/hal/include/hal_icu.h create mode 100644 os/hal/include/hal_mac.h create mode 100644 os/hal/include/hal_mmc_spi.h create mode 100644 os/hal/include/hal_pal.h create mode 100644 os/hal/include/hal_pwm.h create mode 100644 os/hal/include/hal_rtc.h create mode 100644 os/hal/include/hal_sdc.h create mode 100644 os/hal/include/hal_serial.h create mode 100644 os/hal/include/hal_serial_usb.h create mode 100644 os/hal/include/hal_spi.h create mode 100644 os/hal/include/hal_st.h create mode 100644 os/hal/include/hal_uart.h create mode 100644 os/hal/include/hal_usb.h create mode 100644 os/hal/include/hal_wdg.h delete mode 100644 os/hal/include/i2c.h delete mode 100644 os/hal/include/i2s.h delete mode 100644 os/hal/include/icu.h delete mode 100644 os/hal/include/mac.h delete mode 100644 os/hal/include/mmc_spi.h delete mode 100644 os/hal/include/pal.h delete mode 100644 os/hal/include/pwm.h delete mode 100644 os/hal/include/rtc.h delete mode 100644 os/hal/include/sdc.h delete mode 100644 os/hal/include/serial.h delete mode 100644 os/hal/include/serial_usb.h delete mode 100644 os/hal/include/spi.h delete mode 100644 os/hal/include/st.h delete mode 100644 os/hal/include/uart.h delete mode 100644 os/hal/include/usb.h delete mode 100644 os/hal/include/wdg.h delete mode 100644 os/hal/src/adc.c delete mode 100644 os/hal/src/can.c delete mode 100644 os/hal/src/dac.c delete mode 100644 os/hal/src/ext.c delete mode 100644 os/hal/src/gpt.c delete mode 100644 os/hal/src/hal.c create mode 100644 os/hal/src/hal_adc.c create mode 100644 os/hal/src/hal_can.c create mode 100644 os/hal/src/hal_dac.c create mode 100644 os/hal/src/hal_ext.c create mode 100644 os/hal/src/hal_gpt.c create mode 100644 os/hal/src/hal_hal.c create mode 100644 os/hal/src/hal_i2c.c create mode 100644 os/hal/src/hal_i2s.c create mode 100644 os/hal/src/hal_icu.c create mode 100644 os/hal/src/hal_mac.c create mode 100644 os/hal/src/hal_mmc_spi.c create mode 100644 os/hal/src/hal_pal.c create mode 100644 os/hal/src/hal_pwm.c create mode 100644 os/hal/src/hal_rtc.c create mode 100644 os/hal/src/hal_sdc.c create mode 100644 os/hal/src/hal_serial.c create mode 100644 os/hal/src/hal_serial_usb.c create mode 100644 os/hal/src/hal_spi.c create mode 100644 os/hal/src/hal_st.c create mode 100644 os/hal/src/hal_uart.c create mode 100644 os/hal/src/hal_usb.c create mode 100644 os/hal/src/hal_wdg.c delete mode 100644 os/hal/src/i2c.c delete mode 100644 os/hal/src/i2s.c delete mode 100644 os/hal/src/icu.c delete mode 100644 os/hal/src/mac.c delete mode 100644 os/hal/src/mmc_spi.c delete mode 100644 os/hal/src/pal.c delete mode 100644 os/hal/src/pwm.c delete mode 100644 os/hal/src/rtc.c delete mode 100644 os/hal/src/sdc.c delete mode 100644 os/hal/src/serial.c delete mode 100644 os/hal/src/serial_usb.c delete mode 100644 os/hal/src/spi.c delete mode 100644 os/hal/src/st.c delete mode 100644 os/hal/src/uart.c delete mode 100644 os/hal/src/usb.c delete mode 100644 os/hal/src/wdg.c (limited to 'os') diff --git a/os/common/ports/ARM/chcore_timer.h b/os/common/ports/ARM/chcore_timer.h index 76161602b..3da4bb01e 100644 --- a/os/common/ports/ARM/chcore_timer.h +++ b/os/common/ports/ARM/chcore_timer.h @@ -29,7 +29,7 @@ #define _CHCORE_TIMER_H_ /* This is the only header in the HAL designed to be include-able alone.*/ -#include "st.h" +#include "hal_st.h" /*===========================================================================*/ /* Module constants. */ diff --git a/os/common/ports/ARMCMx/chcore_timer.h b/os/common/ports/ARMCMx/chcore_timer.h index 1fb16888b..eec7dcf79 100644 --- a/os/common/ports/ARMCMx/chcore_timer.h +++ b/os/common/ports/ARMCMx/chcore_timer.h @@ -29,7 +29,7 @@ #define _CHCORE_TIMER_H_ /* This is the only header in the HAL designed to be include-able alone.*/ -#include "st.h" +#include "hal_st.h" /*===========================================================================*/ /* Module constants. */ diff --git a/os/common/ports/AVR/chcore_timer.h b/os/common/ports/AVR/chcore_timer.h index 3e719da90..3d99af347 100644 --- a/os/common/ports/AVR/chcore_timer.h +++ b/os/common/ports/AVR/chcore_timer.h @@ -29,7 +29,7 @@ #define _CHCORE_TIMER_H_ /* This is the only header in the HAL designed to be include-able alone.*/ -#include "st.h" +#include "hal_st.h" /*===========================================================================*/ /* Module constants. */ diff --git a/os/hal/hal.mk b/os/hal/hal.mk index ed2ac4d03..dd6f4af84 100644 --- a/os/hal/hal.mk +++ b/os/hal/hal.mk @@ -3,97 +3,97 @@ ifeq ($(USE_SMART_BUILD),yes) HALCONF := $(strip $(shell cat halconf.h | egrep -e "define")) -HALSRC := $(CHIBIOS)/os/hal/src/hal.c \ - $(CHIBIOS)/os/hal/src/st.c \ +HALSRC := $(CHIBIOS)/os/hal/src/hal_hal.c \ + $(CHIBIOS)/os/hal/src/hal_st.c \ $(CHIBIOS)/os/hal/src/hal_buffers.c \ $(CHIBIOS)/os/hal/src/hal_queues.c \ $(CHIBIOS)/os/hal/src/hal_mmcsd.c ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/adc.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_adc.c endif ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/can.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_can.c endif ifneq ($(findstring HAL_USE_DAC TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/dac.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_dac.c endif ifneq ($(findstring HAL_USE_EXT TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/ext.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_ext.c endif ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/gpt.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_gpt.c endif ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/i2c.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_i2c.c endif ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/i2s.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_i2s.c endif ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/icu.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_icu.c endif ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/mac.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_mac.c endif ifneq ($(findstring HAL_USE_MMC_SPI TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/mmc_spi.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_mmc_spi.c endif ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/pal.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_pal.c endif ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/pwm.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_pwm.c endif ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/rtc.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_rtc.c endif ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/sdc.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_sdc.c endif ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/serial.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_serial.c endif ifneq ($(findstring HAL_USE_SERIAL_USB TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/serial_usb.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_serial_usb.c endif ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/spi.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_spi.c endif ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/uart.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_uart.c endif ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/usb.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_usb.c endif ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),) -HALSRC += $(CHIBIOS)/os/hal/src/wdg.c +HALSRC += $(CHIBIOS)/os/hal/src/hal_wdg.c endif else HALSRC = $(CHIBIOS)/os/hal/src/hal.c \ $(CHIBIOS)/os/hal/src/hal_buffers.c \ $(CHIBIOS)/os/hal/src/hal_queues.c \ $(CHIBIOS)/os/hal/src/hal_mmcsd.c \ - $(CHIBIOS)/os/hal/src/adc.c \ - $(CHIBIOS)/os/hal/src/can.c \ - $(CHIBIOS)/os/hal/src/dac.c \ - $(CHIBIOS)/os/hal/src/ext.c \ - $(CHIBIOS)/os/hal/src/gpt.c \ - $(CHIBIOS)/os/hal/src/i2c.c \ - $(CHIBIOS)/os/hal/src/i2s.c \ - $(CHIBIOS)/os/hal/src/icu.c \ - $(CHIBIOS)/os/hal/src/mac.c \ - $(CHIBIOS)/os/hal/src/mmc_spi.c \ - $(CHIBIOS)/os/hal/src/pal.c \ - $(CHIBIOS)/os/hal/src/pwm.c \ - $(CHIBIOS)/os/hal/src/rtc.c \ - $(CHIBIOS)/os/hal/src/sdc.c \ - $(CHIBIOS)/os/hal/src/serial.c \ - $(CHIBIOS)/os/hal/src/serial_usb.c \ - $(CHIBIOS)/os/hal/src/spi.c \ - $(CHIBIOS)/os/hal/src/st.c \ - $(CHIBIOS)/os/hal/src/uart.c \ - $(CHIBIOS)/os/hal/src/usb.c \ - $(CHIBIOS)/os/hal/src/wdg.c + $(CHIBIOS)/os/hal/src/hal_adc.c \ + $(CHIBIOS)/os/hal/src/hal_can.c \ + $(CHIBIOS)/os/hal/src/hal_dac.c \ + $(CHIBIOS)/os/hal/src/hal_ext.c \ + $(CHIBIOS)/os/hal/src/hal_gpt.c \ + $(CHIBIOS)/os/hal/src/hal_i2c.c \ + $(CHIBIOS)/os/hal/src/hal_i2s.c \ + $(CHIBIOS)/os/hal/src/hal_icu.c \ + $(CHIBIOS)/os/hal/src/hal_mac.c \ + $(CHIBIOS)/os/hal/src/hal_mmc_spi.c \ + $(CHIBIOS)/os/hal/src/hal_pal.c \ + $(CHIBIOS)/os/hal/src/hal_pwm.c \ + $(CHIBIOS)/os/hal/src/hal_rtc.c \ + $(CHIBIOS)/os/hal/src/hal_sdc.c \ + $(CHIBIOS)/os/hal/src/hal_serial.c \ + $(CHIBIOS)/os/hal/src/hal_serial_usb.c \ + $(CHIBIOS)/os/hal/src/hal_spi.c \ + $(CHIBIOS)/os/hal/src/hal_st.c \ + $(CHIBIOS)/os/hal/src/hal_uart.c \ + $(CHIBIOS)/os/hal/src/hal_usb.c \ + $(CHIBIOS)/os/hal/src/hal_wdg.c endif # Required include directories diff --git a/os/hal/include/adc.h b/os/hal/include/adc.h deleted file mode 100644 index 142ddfda7..000000000 --- a/os/hal/include/adc.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file adc.h - * @brief ADC Driver macros and structures. - * - * @addtogroup ADC - * @{ - */ - -#ifndef _ADC_H_ -#define _ADC_H_ - -#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name ADC configuration options - * @{ - */ -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) -#define ADC_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define ADC_USE_MUTUAL_EXCLUSION TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - ADC_UNINIT = 0, /**< Not initialized. */ - ADC_STOP = 1, /**< Stopped. */ - ADC_READY = 2, /**< Ready. */ - ADC_ACTIVE = 3, /**< Converting. */ - ADC_COMPLETE = 4, /**< Conversion complete. */ - ADC_ERROR = 5 /**< Conversion complete. */ -} adcstate_t; - -#include "adc_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Low level driver helper macros - * @{ - */ -#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Resumes a thread waiting for a conversion completion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -#define _adc_reset_i(adcp) \ - osalThreadResumeI(&(adcp)->thread, MSG_RESET) - -/** - * @brief Resumes a thread waiting for a conversion completion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -#define _adc_reset_s(adcp) \ - osalThreadResumeS(&(adcp)->thread, MSG_RESET) - -/** - * @brief Wakes up the waiting thread. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -#define _adc_wakeup_isr(adcp) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(adcp)->thread, MSG_OK); \ - osalSysUnlockFromISR(); \ -} - -/** - * @brief Wakes up the waiting thread with a timeout message. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -#define _adc_timeout_isr(adcp) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(adcp)->thread, MSG_TIMEOUT); \ - osalSysUnlockFromISR(); \ -} - -#else /* !ADC_USE_WAIT */ -#define _adc_reset_i(adcp) -#define _adc_reset_s(adcp) -#define _adc_wakeup_isr(adcp) -#define _adc_timeout_isr(adcp) -#endif /* !ADC_USE_WAIT */ - -/** - * @brief Common ISR code, half buffer event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -#define _adc_isr_half_code(adcp) { \ - if ((adcp)->grpp->end_cb != NULL) { \ - (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth / 2); \ - } \ -} - -/** - * @brief Common ISR code, full buffer event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @notapi - */ -#define _adc_isr_full_code(adcp) { \ - if ((adcp)->grpp->circular) { \ - /* Callback handling.*/ \ - if ((adcp)->grpp->end_cb != NULL) { \ - if ((adcp)->depth > 1) { \ - /* Invokes the callback passing the 2nd half of the buffer.*/ \ - size_t half = (adcp)->depth / 2; \ - size_t half_index = half * (adcp)->grpp->num_channels; \ - (adcp)->grpp->end_cb(adcp, (adcp)->samples + half_index, half); \ - } \ - else { \ - /* Invokes the callback passing the whole buffer.*/ \ - (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth); \ - } \ - } \ - } \ - else { \ - /* End conversion.*/ \ - adc_lld_stop_conversion(adcp); \ - if ((adcp)->grpp->end_cb != NULL) { \ - (adcp)->state = ADC_COMPLETE; \ - /* Invoke the callback passing the whole buffer.*/ \ - (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth); \ - if ((adcp)->state == ADC_COMPLETE) { \ - (adcp)->state = ADC_READY; \ - (adcp)->grpp = NULL; \ - } \ - } \ - else { \ - (adcp)->state = ADC_READY; \ - (adcp)->grpp = NULL; \ - } \ - _adc_wakeup_isr(adcp); \ - } \ -} - -/** - * @brief Common ISR code, error event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread timeout signaling, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] err platform dependent error code - * - * @notapi - */ -#define _adc_isr_error_code(adcp, err) { \ - adc_lld_stop_conversion(adcp); \ - if ((adcp)->grpp->error_cb != NULL) { \ - (adcp)->state = ADC_ERROR; \ - (adcp)->grpp->error_cb(adcp, err); \ - if ((adcp)->state == ADC_ERROR) \ - (adcp)->state = ADC_READY; \ - } \ - (adcp)->grpp = NULL; \ - _adc_timeout_isr(adcp); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void adcInit(void); - void adcObjectInit(ADCDriver *adcp); - void adcStart(ADCDriver *adcp, const ADCConfig *config); - void adcStop(ADCDriver *adcp); - void adcStartConversion(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth); - void adcStartConversionI(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth); - void adcStopConversion(ADCDriver *adcp); - void adcStopConversionI(ADCDriver *adcp); -#if ADC_USE_WAIT == TRUE - msg_t adcConvert(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth); -#endif -#if ADC_USE_MUTUAL_EXCLUSION == TRUE - void adcAcquireBus(ADCDriver *adcp); - void adcReleaseBus(ADCDriver *adcp); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ADC == TRUE */ - -#endif /* _ADC_H_ */ - -/** @} */ diff --git a/os/hal/include/can.h b/os/hal/include/can.h deleted file mode 100644 index 9947b9960..000000000 --- a/os/hal/include/can.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file can.h - * @brief CAN Driver macros and structures. - * - * @addtogroup CAN - * @{ - */ - -#ifndef _CAN_H_ -#define _CAN_H_ - -#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name CAN status flags - * @{ - */ -/** - * @brief Errors rate warning. - */ -#define CAN_LIMIT_WARNING 1U -/** - * @brief Errors rate error. - */ -#define CAN_LIMIT_ERROR 2U -/** - * @brief Bus off condition reached. - */ -#define CAN_BUS_OFF_ERROR 4U -/** - * @brief Framing error of some kind on the CAN bus. - */ -#define CAN_FRAMING_ERROR 8U -/** - * @brief Overflow in receive queue. - */ -#define CAN_OVERFLOW_ERROR 16U -/** @} */ - -/** - * @brief Special mailbox identifier. - */ -#define CAN_ANY_MAILBOX 0 - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name CAN configuration options - * @{ - */ -/** - * @brief Sleep mode related APIs inclusion switch. - * @details This option can only be enabled if the CAN implementation supports - * the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by - * the underlying implementation. - */ -#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) -#define CAN_USE_SLEEP_MODE TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - CAN_UNINIT = 0, /**< Not initialized. */ - CAN_STOP = 1, /**< Stopped. */ - CAN_STARTING = 2, /**< Starting. */ - CAN_READY = 3, /**< Ready. */ - CAN_SLEEP = 4 /**< Sleep state. */ -} canstate_t; - -#include "can_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Converts a mailbox index to a bit mask. - */ -#define CAN_MAILBOX_TO_MASK(mbx) (1U << ((mbx) - 1U)) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void canInit(void); - void canObjectInit(CANDriver *canp); - void canStart(CANDriver *canp, const CANConfig *config); - void canStop(CANDriver *canp); - bool canTryTransmitI(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp); - bool canTryReceiveI(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp); - msg_t canTransmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp, - systime_t timeout); - msg_t canReceive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp, - systime_t timeout); -#if CAN_USE_SLEEP_MODE - void canSleep(CANDriver *canp); - void canWakeup(CANDriver *canp); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_CAN == TRUE */ - -#endif /* _CAN_H_ */ - -/** @} */ diff --git a/os/hal/include/dac.h b/os/hal/include/dac.h deleted file mode 100644 index 19325b61d..000000000 --- a/os/hal/include/dac.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file dac.h - * @brief DAC Driver macros and structures. - * - * @addtogroup DAC - * @{ - */ - -#ifndef _DAC_H_ -#define _DAC_H_ - -#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name DAC configuration options - * @{ - */ -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) -#define DAC_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define DAC_USE_MUTUAL_EXCLUSION TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - DAC_UNINIT = 0, /**< Not initialized. */ - DAC_STOP = 1, /**< Stopped. */ - DAC_READY = 2, /**< Ready. */ - DAC_ACTIVE = 3, /**< Exchanging data. */ - DAC_COMPLETE = 4, /**< Asynchronous operation complete. */ - DAC_ERROR = 5 /**< Error. */ -} dacstate_t; - -#include "dac_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Low level driver helper macros - * @{ - */ -#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Waits for operation completion. - * @details This function waits for the driver to complete the current - * operation. - * @pre An operation must be running while the function is invoked. - * @note No more than one thread can wait on a DAC driver using - * this function. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_wait_s(dacp) osalThreadSuspendS(&(dacp)->thread) - -/** - * @brief Resumes a thread waiting for a conversion completion. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_reset_i(dacp) osalThreadResumeI(&(dacp)->thread, MSG_RESET) - -/** - * @brief Resumes a thread waiting for a conversion completion. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_reset_s(dacp) osalThreadResumeS(&(dacp)->thread, MSG_RESET) - -/** - * @brief Wakes up the waiting thread. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_wakeup_isr(dacp) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(dacp)->thread, MSG_OK); \ - osalSysUnlockFromISR(); \ -} - -/** - * @brief Wakes up the waiting thread with a timeout message. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_timeout_isr(dacp) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(dacp)->thread, MSG_TIMEOUT); \ - osalSysUnlockFromISR(); \ -} - -#else /* !DAC_USE_WAIT */ -#define _dac_wait_s(dacp) -#define _dac_reset_i(dacp) -#define _dac_reset_s(dacp) -#define _dac_wakeup_isr(dacp) -#define _dac_timeout_isr(dacp) -#endif /* !DAC_USE_WAIT */ - -/** - * @brief Common ISR code, half buffer event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_isr_half_code(dacp) { \ - if ((dacp)->grpp->end_cb != NULL) { \ - (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth / 2); \ - } \ -} - -/** - * @brief Common ISR code, full buffer event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @notapi - */ -#define _dac_isr_full_code(dacp) { \ - if ((dacp)->grpp->end_cb != NULL) { \ - if ((dacp)->depth > 1) { \ - /* Invokes the callback passing the 2nd half of the buffer.*/ \ - size_t half = (dacp)->depth / 2; \ - size_t half_index = half * (dacp)->grpp->num_channels; \ - (dacp)->grpp->end_cb(dacp, (dacp)->samples + half_index, half); \ - } \ - else { \ - /* Invokes the callback passing the whole buffer.*/ \ - (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth); \ - } \ - } \ -} - -/** - * @brief Common ISR code, error event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread timeout signaling, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] err platform dependent error code - * - * @notapi - */ -#define _dac_isr_error_code(dacp, err) { \ - dac_lld_stop_conversion(dacp); \ - if ((dacp)->grpp->error_cb != NULL) { \ - (dacp)->state = DAC_ERROR; \ - (dacp)->grpp->error_cb(dacp, err); \ - if ((dacp)->state == DAC_ERROR) \ - (dacp)->state = DAC_READY; \ - } \ - (dacp)->grpp = NULL; \ - _dac_timeout_isr(dacp); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void dacInit(void); - void dacObjectInit(DACDriver *dacp); - void dacStart(DACDriver *dacp, const DACConfig *config); - void dacStop(DACDriver *dacp); - void dacPutChannelX(DACDriver *dacp, - dacchannel_t channel, - dacsample_t sample); - void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp, - const dacsample_t *samples, size_t depth); - void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp, - const dacsample_t *samples, size_t depth); - void dacStopConversion(DACDriver *dacp); - void dacStopConversionI(DACDriver *dacp); -#if DAC_USE_WAIT - msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp, - const dacsample_t *samples, size_t depth); -#endif -#if DAC_USE_MUTUAL_EXCLUSION - void dacAcquireBus(DACDriver *dacp); - void dacReleaseBus(DACDriver *dacp); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_DAC == TRUE */ - -#endif /* _DAC_H_ */ - -/** @} */ diff --git a/os/hal/include/ext.h b/os/hal/include/ext.h deleted file mode 100644 index 282178e79..000000000 --- a/os/hal/include/ext.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ext.h - * @brief EXT Driver macros and structures. - * - * @addtogroup EXT - * @{ - */ - -#ifndef _EXT_H_ -#define _EXT_H_ - -#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name EXT channel modes - * @{ - */ -#define EXT_CH_MODE_EDGES_MASK 3U /**< @brief Mask of edges field. */ -#define EXT_CH_MODE_DISABLED 0U /**< @brief Channel disabled. */ -#define EXT_CH_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */ -#define EXT_CH_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */ -#define EXT_CH_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */ - -#define EXT_CH_MODE_AUTOSTART 4U /**< @brief Channel started - automatically on driver start. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - EXT_UNINIT = 0, /**< Not initialized. */ - EXT_STOP = 1, /**< Stopped. */ - EXT_ACTIVE = 2 /**< Active. */ -} extstate_t; - -/** - * @brief Type of a structure representing a EXT driver. - */ -typedef struct EXTDriver EXTDriver; - -#include "ext_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Enables an EXT channel. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be enabled - * - * @iclass - */ -#define extChannelEnableI(extp, channel) ext_lld_channel_enable(extp, channel) - -/** - * @brief Disables an EXT channel. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be disabled - * - * @iclass - */ -#define extChannelDisableI(extp, channel) ext_lld_channel_disable(extp, channel) - -/** - * @brief Changes the operation mode of a channel. - * @note This function attempts to write over the current configuration - * structure that must have been not declared constant. This - * violates the @p const qualifier in @p extStart() but it is - * intentional. This function cannot be used if the configuration - * structure is declared @p const. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be changed - * @param[in] extcp new configuration for the channel - * - * @api - */ -#define extSetChannelMode(extp, channel, extcp) { \ - osalSysLock(); \ - extSetChannelModeI(extp, channel, extcp); \ - osalSysUnlock(); \ -} - -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void extInit(void); - void extObjectInit(EXTDriver *extp); - void extStart(EXTDriver *extp, const EXTConfig *config); - void extStop(EXTDriver *extp); - void extChannelEnable(EXTDriver *extp, expchannel_t channel); - void extChannelDisable(EXTDriver *extp, expchannel_t channel); - void extSetChannelModeI(EXTDriver *extp, - expchannel_t channel, - const EXTChannelConfig *extcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_EXT == TRUE */ - -#endif /* _EXT_H_ */ - -/** @} */ diff --git a/os/hal/include/gpt.h b/os/hal/include/gpt.h deleted file mode 100644 index 38e906bd3..000000000 --- a/os/hal/include/gpt.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file gpt.h - * @brief GPT Driver macros and structures. - * - * @addtogroup GPT - * @{ - */ - -#ifndef _GPT_H_ -#define _GPT_H_ - -#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - GPT_UNINIT = 0, /**< Not initialized. */ - GPT_STOP = 1, /**< Stopped. */ - GPT_READY = 2, /**< Ready. */ - GPT_CONTINUOUS = 3, /**< Active in continuous mode. */ - GPT_ONESHOT = 4 /**< Active in one shot mode. */ -} gptstate_t; - -/** - * @brief Type of a structure representing a GPT driver. - */ -typedef struct GPTDriver GPTDriver; - -/** - * @brief GPT notification callback type. - * - * @param[in] gptp pointer to a @p GPTDriver object - */ -typedef void (*gptcallback_t)(GPTDriver *gptp); - -#include "gpt_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Changes the interval of GPT peripheral. - * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must be running in continuous mode. - * @post The GPT unit interval is changed to the new value. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @param[in] interval new cycle time in timer ticks - * - * @iclass - */ -#define gptChangeIntervalI(gptp, interval) { \ - gpt_lld_change_interval(gptp, interval); \ -} - -/** - * @brief Returns the interval of GPT peripheral. - * @pre The GPT unit must be running in continuous mode. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @return The current interval. - * - * @xclass - */ -#define gptGetIntervalX(gptp) gpt_lld_get_interval(gptp) - -/** - * @brief Returns the counter value of GPT peripheral. - * @pre The GPT unit must be running in continuous mode. - * @note The nature of the counter is not defined, it may count upward - * or downward, it could be continuously running or not. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @return The current counter value. - * - * @xclass - */ -#define gptGetCounterX(gptp) gpt_lld_get_counter(gptp) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void gptInit(void); - void gptObjectInit(GPTDriver *gptp); - void gptStart(GPTDriver *gptp, const GPTConfig *config); - void gptStop(GPTDriver *gptp); - void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval); - void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval); - void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval); - void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval); - void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval); - void gptStopTimer(GPTDriver *gptp); - void gptStopTimerI(GPTDriver *gptp); - void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_GPT == TRUE */ - -#endif /* _GPT_H_ */ - -/** @} */ diff --git a/os/hal/include/hal.h b/os/hal/include/hal.h index 2ffd9ab0d..ba7c2c591 100644 --- a/os/hal/include/hal.h +++ b/os/hal/include/hal.h @@ -43,37 +43,36 @@ #include "hal_queues.h" /* Normal drivers.*/ -#include "pal.h" -#include "adc.h" -#include "can.h" -#include "dac.h" -#include "ext.h" -#include "gpt.h" -#include "i2c.h" -#include "i2s.h" -#include "icu.h" -#include "mac.h" -#include "mii.h" -#include "pwm.h" -#include "rtc.h" -#include "serial.h" -#include "sdc.h" -#include "spi.h" -#include "uart.h" -#include "usb.h" -#include "wdg.h" +#include "hal_pal.h" +#include "hal_adc.h" +#include "hal_can.h" +#include "hal_dac.h" +#include "hal_ext.h" +#include "hal_gpt.h" +#include "hal_i2c.h" +#include "hal_i2s.h" +#include "hal_icu.h" +#include "hal_mac.h" +#include "hal_pwm.h" +#include "hal_rtc.h" +#include "hal_serial.h" +#include "hal_sdc.h" +#include "hal_spi.h" +#include "hal_uart.h" +#include "hal_usb.h" +#include "hal_wdg.h" /* * The ST driver is a special case, it is only included if the OSAL is * configured to require it. */ #if OSAL_ST_MODE != OSAL_ST_MODE_NONE -#include "st.h" +#include "hal_st.h" #endif /* Complex drivers.*/ -#include "mmc_spi.h" -#include "serial_usb.h" +#include "hal_mmc_spi.h" +#include "hal_serial_usb.h" /* Community drivers.*/ #if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__) @@ -103,17 +102,17 @@ /** * @brief HAL version string. */ -#define HAL_VERSION "4.1.0" +#define HAL_VERSION "5.0.0" /** * @brief HAL version major number. */ -#define CH_HAL_MAJOR 4 +#define CH_HAL_MAJOR 5 /** * @brief HAL version minor number. */ -#define CH_HAL_MINOR 1 +#define CH_HAL_MINOR 0 /** * @brief HAL version patch number. diff --git a/os/hal/include/hal_adc.h b/os/hal/include/hal_adc.h new file mode 100644 index 000000000..142ddfda7 --- /dev/null +++ b/os/hal/include/hal_adc.h @@ -0,0 +1,278 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file adc.h + * @brief ADC Driver macros and structures. + * + * @addtogroup ADC + * @{ + */ + +#ifndef _ADC_H_ +#define _ADC_H_ + +#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name ADC configuration options + * @{ + */ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + ADC_UNINIT = 0, /**< Not initialized. */ + ADC_STOP = 1, /**< Stopped. */ + ADC_READY = 2, /**< Ready. */ + ADC_ACTIVE = 3, /**< Converting. */ + ADC_COMPLETE = 4, /**< Conversion complete. */ + ADC_ERROR = 5 /**< Conversion complete. */ +} adcstate_t; + +#include "adc_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Low level driver helper macros + * @{ + */ +#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Resumes a thread waiting for a conversion completion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +#define _adc_reset_i(adcp) \ + osalThreadResumeI(&(adcp)->thread, MSG_RESET) + +/** + * @brief Resumes a thread waiting for a conversion completion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +#define _adc_reset_s(adcp) \ + osalThreadResumeS(&(adcp)->thread, MSG_RESET) + +/** + * @brief Wakes up the waiting thread. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +#define _adc_wakeup_isr(adcp) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(adcp)->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} + +/** + * @brief Wakes up the waiting thread with a timeout message. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +#define _adc_timeout_isr(adcp) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(adcp)->thread, MSG_TIMEOUT); \ + osalSysUnlockFromISR(); \ +} + +#else /* !ADC_USE_WAIT */ +#define _adc_reset_i(adcp) +#define _adc_reset_s(adcp) +#define _adc_wakeup_isr(adcp) +#define _adc_timeout_isr(adcp) +#endif /* !ADC_USE_WAIT */ + +/** + * @brief Common ISR code, half buffer event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +#define _adc_isr_half_code(adcp) { \ + if ((adcp)->grpp->end_cb != NULL) { \ + (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth / 2); \ + } \ +} + +/** + * @brief Common ISR code, full buffer event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @notapi + */ +#define _adc_isr_full_code(adcp) { \ + if ((adcp)->grpp->circular) { \ + /* Callback handling.*/ \ + if ((adcp)->grpp->end_cb != NULL) { \ + if ((adcp)->depth > 1) { \ + /* Invokes the callback passing the 2nd half of the buffer.*/ \ + size_t half = (adcp)->depth / 2; \ + size_t half_index = half * (adcp)->grpp->num_channels; \ + (adcp)->grpp->end_cb(adcp, (adcp)->samples + half_index, half); \ + } \ + else { \ + /* Invokes the callback passing the whole buffer.*/ \ + (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth); \ + } \ + } \ + } \ + else { \ + /* End conversion.*/ \ + adc_lld_stop_conversion(adcp); \ + if ((adcp)->grpp->end_cb != NULL) { \ + (adcp)->state = ADC_COMPLETE; \ + /* Invoke the callback passing the whole buffer.*/ \ + (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth); \ + if ((adcp)->state == ADC_COMPLETE) { \ + (adcp)->state = ADC_READY; \ + (adcp)->grpp = NULL; \ + } \ + } \ + else { \ + (adcp)->state = ADC_READY; \ + (adcp)->grpp = NULL; \ + } \ + _adc_wakeup_isr(adcp); \ + } \ +} + +/** + * @brief Common ISR code, error event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread timeout signaling, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] err platform dependent error code + * + * @notapi + */ +#define _adc_isr_error_code(adcp, err) { \ + adc_lld_stop_conversion(adcp); \ + if ((adcp)->grpp->error_cb != NULL) { \ + (adcp)->state = ADC_ERROR; \ + (adcp)->grpp->error_cb(adcp, err); \ + if ((adcp)->state == ADC_ERROR) \ + (adcp)->state = ADC_READY; \ + } \ + (adcp)->grpp = NULL; \ + _adc_timeout_isr(adcp); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void adcInit(void); + void adcObjectInit(ADCDriver *adcp); + void adcStart(ADCDriver *adcp, const ADCConfig *config); + void adcStop(ADCDriver *adcp); + void adcStartConversion(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth); + void adcStartConversionI(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth); + void adcStopConversion(ADCDriver *adcp); + void adcStopConversionI(ADCDriver *adcp); +#if ADC_USE_WAIT == TRUE + msg_t adcConvert(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth); +#endif +#if ADC_USE_MUTUAL_EXCLUSION == TRUE + void adcAcquireBus(ADCDriver *adcp); + void adcReleaseBus(ADCDriver *adcp); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ADC == TRUE */ + +#endif /* _ADC_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_can.h b/os/hal/include/hal_can.h new file mode 100644 index 000000000..9947b9960 --- /dev/null +++ b/os/hal/include/hal_can.h @@ -0,0 +1,156 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file can.h + * @brief CAN Driver macros and structures. + * + * @addtogroup CAN + * @{ + */ + +#ifndef _CAN_H_ +#define _CAN_H_ + +#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name CAN status flags + * @{ + */ +/** + * @brief Errors rate warning. + */ +#define CAN_LIMIT_WARNING 1U +/** + * @brief Errors rate error. + */ +#define CAN_LIMIT_ERROR 2U +/** + * @brief Bus off condition reached. + */ +#define CAN_BUS_OFF_ERROR 4U +/** + * @brief Framing error of some kind on the CAN bus. + */ +#define CAN_FRAMING_ERROR 8U +/** + * @brief Overflow in receive queue. + */ +#define CAN_OVERFLOW_ERROR 16U +/** @} */ + +/** + * @brief Special mailbox identifier. + */ +#define CAN_ANY_MAILBOX 0 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name CAN configuration options + * @{ + */ +/** + * @brief Sleep mode related APIs inclusion switch. + * @details This option can only be enabled if the CAN implementation supports + * the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by + * the underlying implementation. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + CAN_UNINIT = 0, /**< Not initialized. */ + CAN_STOP = 1, /**< Stopped. */ + CAN_STARTING = 2, /**< Starting. */ + CAN_READY = 3, /**< Ready. */ + CAN_SLEEP = 4 /**< Sleep state. */ +} canstate_t; + +#include "can_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Converts a mailbox index to a bit mask. + */ +#define CAN_MAILBOX_TO_MASK(mbx) (1U << ((mbx) - 1U)) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void canInit(void); + void canObjectInit(CANDriver *canp); + void canStart(CANDriver *canp, const CANConfig *config); + void canStop(CANDriver *canp); + bool canTryTransmitI(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp); + bool canTryReceiveI(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp); + msg_t canTransmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp, + systime_t timeout); + msg_t canReceive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp, + systime_t timeout); +#if CAN_USE_SLEEP_MODE + void canSleep(CANDriver *canp); + void canWakeup(CANDriver *canp); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_CAN == TRUE */ + +#endif /* _CAN_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_dac.h b/os/hal/include/hal_dac.h new file mode 100644 index 000000000..19325b61d --- /dev/null +++ b/os/hal/include/hal_dac.h @@ -0,0 +1,267 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file dac.h + * @brief DAC Driver macros and structures. + * + * @addtogroup DAC + * @{ + */ + +#ifndef _DAC_H_ +#define _DAC_H_ + +#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name DAC configuration options + * @{ + */ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +#define DAC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define DAC_USE_MUTUAL_EXCLUSION TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + DAC_UNINIT = 0, /**< Not initialized. */ + DAC_STOP = 1, /**< Stopped. */ + DAC_READY = 2, /**< Ready. */ + DAC_ACTIVE = 3, /**< Exchanging data. */ + DAC_COMPLETE = 4, /**< Asynchronous operation complete. */ + DAC_ERROR = 5 /**< Error. */ +} dacstate_t; + +#include "dac_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Low level driver helper macros + * @{ + */ +#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Waits for operation completion. + * @details This function waits for the driver to complete the current + * operation. + * @pre An operation must be running while the function is invoked. + * @note No more than one thread can wait on a DAC driver using + * this function. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_wait_s(dacp) osalThreadSuspendS(&(dacp)->thread) + +/** + * @brief Resumes a thread waiting for a conversion completion. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_reset_i(dacp) osalThreadResumeI(&(dacp)->thread, MSG_RESET) + +/** + * @brief Resumes a thread waiting for a conversion completion. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_reset_s(dacp) osalThreadResumeS(&(dacp)->thread, MSG_RESET) + +/** + * @brief Wakes up the waiting thread. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_wakeup_isr(dacp) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(dacp)->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} + +/** + * @brief Wakes up the waiting thread with a timeout message. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_timeout_isr(dacp) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(dacp)->thread, MSG_TIMEOUT); \ + osalSysUnlockFromISR(); \ +} + +#else /* !DAC_USE_WAIT */ +#define _dac_wait_s(dacp) +#define _dac_reset_i(dacp) +#define _dac_reset_s(dacp) +#define _dac_wakeup_isr(dacp) +#define _dac_timeout_isr(dacp) +#endif /* !DAC_USE_WAIT */ + +/** + * @brief Common ISR code, half buffer event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_isr_half_code(dacp) { \ + if ((dacp)->grpp->end_cb != NULL) { \ + (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth / 2); \ + } \ +} + +/** + * @brief Common ISR code, full buffer event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @notapi + */ +#define _dac_isr_full_code(dacp) { \ + if ((dacp)->grpp->end_cb != NULL) { \ + if ((dacp)->depth > 1) { \ + /* Invokes the callback passing the 2nd half of the buffer.*/ \ + size_t half = (dacp)->depth / 2; \ + size_t half_index = half * (dacp)->grpp->num_channels; \ + (dacp)->grpp->end_cb(dacp, (dacp)->samples + half_index, half); \ + } \ + else { \ + /* Invokes the callback passing the whole buffer.*/ \ + (dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth); \ + } \ + } \ +} + +/** + * @brief Common ISR code, error event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread timeout signaling, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] err platform dependent error code + * + * @notapi + */ +#define _dac_isr_error_code(dacp, err) { \ + dac_lld_stop_conversion(dacp); \ + if ((dacp)->grpp->error_cb != NULL) { \ + (dacp)->state = DAC_ERROR; \ + (dacp)->grpp->error_cb(dacp, err); \ + if ((dacp)->state == DAC_ERROR) \ + (dacp)->state = DAC_READY; \ + } \ + (dacp)->grpp = NULL; \ + _dac_timeout_isr(dacp); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void dacInit(void); + void dacObjectInit(DACDriver *dacp); + void dacStart(DACDriver *dacp, const DACConfig *config); + void dacStop(DACDriver *dacp); + void dacPutChannelX(DACDriver *dacp, + dacchannel_t channel, + dacsample_t sample); + void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp, + const dacsample_t *samples, size_t depth); + void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp, + const dacsample_t *samples, size_t depth); + void dacStopConversion(DACDriver *dacp); + void dacStopConversionI(DACDriver *dacp); +#if DAC_USE_WAIT + msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp, + const dacsample_t *samples, size_t depth); +#endif +#if DAC_USE_MUTUAL_EXCLUSION + void dacAcquireBus(DACDriver *dacp); + void dacReleaseBus(DACDriver *dacp); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_DAC == TRUE */ + +#endif /* _DAC_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_ext.h b/os/hal/include/hal_ext.h new file mode 100644 index 000000000..282178e79 --- /dev/null +++ b/os/hal/include/hal_ext.h @@ -0,0 +1,150 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ext.h + * @brief EXT Driver macros and structures. + * + * @addtogroup EXT + * @{ + */ + +#ifndef _EXT_H_ +#define _EXT_H_ + +#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name EXT channel modes + * @{ + */ +#define EXT_CH_MODE_EDGES_MASK 3U /**< @brief Mask of edges field. */ +#define EXT_CH_MODE_DISABLED 0U /**< @brief Channel disabled. */ +#define EXT_CH_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */ +#define EXT_CH_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */ +#define EXT_CH_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */ + +#define EXT_CH_MODE_AUTOSTART 4U /**< @brief Channel started + automatically on driver start. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + EXT_UNINIT = 0, /**< Not initialized. */ + EXT_STOP = 1, /**< Stopped. */ + EXT_ACTIVE = 2 /**< Active. */ +} extstate_t; + +/** + * @brief Type of a structure representing a EXT driver. + */ +typedef struct EXTDriver EXTDriver; + +#include "ext_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Enables an EXT channel. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be enabled + * + * @iclass + */ +#define extChannelEnableI(extp, channel) ext_lld_channel_enable(extp, channel) + +/** + * @brief Disables an EXT channel. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be disabled + * + * @iclass + */ +#define extChannelDisableI(extp, channel) ext_lld_channel_disable(extp, channel) + +/** + * @brief Changes the operation mode of a channel. + * @note This function attempts to write over the current configuration + * structure that must have been not declared constant. This + * violates the @p const qualifier in @p extStart() but it is + * intentional. This function cannot be used if the configuration + * structure is declared @p const. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be changed + * @param[in] extcp new configuration for the channel + * + * @api + */ +#define extSetChannelMode(extp, channel, extcp) { \ + osalSysLock(); \ + extSetChannelModeI(extp, channel, extcp); \ + osalSysUnlock(); \ +} + +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void extInit(void); + void extObjectInit(EXTDriver *extp); + void extStart(EXTDriver *extp, const EXTConfig *config); + void extStop(EXTDriver *extp); + void extChannelEnable(EXTDriver *extp, expchannel_t channel); + void extChannelDisable(EXTDriver *extp, expchannel_t channel); + void extSetChannelModeI(EXTDriver *extp, + expchannel_t channel, + const EXTChannelConfig *extcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_EXT == TRUE */ + +#endif /* _EXT_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_gpt.h b/os/hal/include/hal_gpt.h new file mode 100644 index 000000000..38e906bd3 --- /dev/null +++ b/os/hal/include/hal_gpt.h @@ -0,0 +1,141 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file gpt.h + * @brief GPT Driver macros and structures. + * + * @addtogroup GPT + * @{ + */ + +#ifndef _GPT_H_ +#define _GPT_H_ + +#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + GPT_UNINIT = 0, /**< Not initialized. */ + GPT_STOP = 1, /**< Stopped. */ + GPT_READY = 2, /**< Ready. */ + GPT_CONTINUOUS = 3, /**< Active in continuous mode. */ + GPT_ONESHOT = 4 /**< Active in one shot mode. */ +} gptstate_t; + +/** + * @brief Type of a structure representing a GPT driver. + */ +typedef struct GPTDriver GPTDriver; + +/** + * @brief GPT notification callback type. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +typedef void (*gptcallback_t)(GPTDriver *gptp); + +#include "gpt_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must be running in continuous mode. + * @post The GPT unit interval is changed to the new value. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * + * @iclass + */ +#define gptChangeIntervalI(gptp, interval) { \ + gpt_lld_change_interval(gptp, interval); \ +} + +/** + * @brief Returns the interval of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current interval. + * + * @xclass + */ +#define gptGetIntervalX(gptp) gpt_lld_get_interval(gptp) + +/** + * @brief Returns the counter value of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * @note The nature of the counter is not defined, it may count upward + * or downward, it could be continuously running or not. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current counter value. + * + * @xclass + */ +#define gptGetCounterX(gptp) gpt_lld_get_counter(gptp) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void gptInit(void); + void gptObjectInit(GPTDriver *gptp); + void gptStart(GPTDriver *gptp, const GPTConfig *config); + void gptStop(GPTDriver *gptp); + void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval); + void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval); + void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval); + void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval); + void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval); + void gptStopTimer(GPTDriver *gptp); + void gptStopTimerI(GPTDriver *gptp); + void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT == TRUE */ + +#endif /* _GPT_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_i2c.h b/os/hal/include/hal_i2c.h new file mode 100644 index 000000000..fb8cabad7 --- /dev/null +++ b/os/hal/include/hal_i2c.h @@ -0,0 +1,166 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file i2c.h + * @brief I2C Driver macros and structures. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/* TODO: To be reviewed, too STM32-centric.*/ +/** + * @name I2C bus error conditions + * @{ + */ +#define I2C_NO_ERROR 0x00 /**< @brief No error. */ +#define I2C_BUS_ERROR 0x01 /**< @brief Bus Error. */ +#define I2C_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */ +#define I2C_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */ +#define I2C_OVERRUN 0x08 /**< @brief Overrun/Underrun. */ +#define I2C_PEC_ERROR 0x10 /**< @brief PEC Error in + reception. */ +#define I2C_TIMEOUT 0x20 /**< @brief Hardware timeout. */ +#define I2C_SMB_ALERT 0x40 /**< @brief SMBus Alert. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + I2C_UNINIT = 0, /**< Not initialized. */ + I2C_STOP = 1, /**< Stopped. */ + I2C_READY = 2, /**< Ready. */ + I2C_ACTIVE_TX = 3, /**< Transmitting. */ + I2C_ACTIVE_RX = 4, /**< Receiving. */ + I2C_LOCKED = 5 /**> Bus or driver locked. */ +} i2cstate_t; + +#include "i2c_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Wakes up the waiting thread notifying no errors. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_wakeup_isr(i2cp) do { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(i2cp)->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} while(0) + +/** + * @brief Wakes up the waiting thread notifying errors. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_wakeup_error_isr(i2cp) do { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(i2cp)->thread, MSG_RESET); \ + osalSysUnlockFromISR(); \ +} while(0) + +/** + * @brief Wrap i2cMasterTransmitTimeout function with TIME_INFINITE timeout. + * @api + */ +#define i2cMasterTransmit(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes) \ + (i2cMasterTransmitTimeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, \ + TIME_INFINITE)) + +/** + * @brief Wrap i2cMasterReceiveTimeout function with TIME_INFINITE timeout. + * @api + */ +#define i2cMasterReceive(i2cp, addr, rxbuf, rxbytes) \ + (i2cMasterReceiveTimeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void i2cInit(void); + void i2cObjectInit(I2CDriver *i2cp); + void i2cStart(I2CDriver *i2cp, const I2CConfig *config); + void i2cStop(I2CDriver *i2cp); + i2cflags_t i2cGetErrors(I2CDriver *i2cp); + msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, + i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, + i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); +#if I2C_USE_MUTUAL_EXCLUSION == TRUE + void i2cAcquireBus(I2CDriver *i2cp); + void i2cReleaseBus(I2CDriver *i2cp); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C == TRUE */ + +#endif /* _I2C_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_i2s.h b/os/hal/include/hal_i2s.h new file mode 100644 index 000000000..a759b8455 --- /dev/null +++ b/os/hal/include/hal_i2s.h @@ -0,0 +1,167 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file i2s.h + * @brief I2S Driver macros and structures. + * + * @addtogroup I2S + * @{ + */ + +#ifndef _I2S_H_ +#define _I2S_H_ + +#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name I2S modes + * @{ + */ +#define I2S_MODE_SLAVE 0 +#define I2S_MODE_MASTER 1 +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + I2S_UNINIT = 0, /**< Not initialized. */ + I2S_STOP = 1, /**< Stopped. */ + I2S_READY = 2, /**< Ready. */ + I2S_ACTIVE = 3, /**< Active. */ + I2S_COMPLETE = 4 /**< Transmission complete. */ +} i2sstate_t; + +#include "i2s_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Starts a I2S data exchange. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @iclass + */ +#define i2sStartExchangeI(i2sp) { \ + i2s_lld_start_exchange(i2sp); \ + (i2sp)->state = I2S_ACTIVE; \ +} + +/** + * @brief Stops the ongoing data exchange. + * @details The ongoing data exchange, if any, is stopped, if the driver + * was not active the function does nothing. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @iclass + */ +#define i2sStopExchangeI(i2sp) { \ + i2s_lld_stop_exchange(i2sp); \ + (i2sp)->state = I2S_READY; \ +} + +/** + * @brief Common ISR code, half buffer event. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] i2sp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2s_isr_half_code(i2sp) { \ + if ((i2sp)->config->end_cb != NULL) { \ + (i2sp)->config->end_cb(i2sp, 0, (i2sp)->config->size / 2); \ + } \ +} + +/** + * @brief Common ISR code. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] i2sp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2s_isr_full_code(i2sp) { \ + if ((i2sp)->config->end_cb) { \ + (i2sp)->state = I2S_COMPLETE; \ + (i2sp)->config->end_cb(i2sp, \ + (i2sp)->config->size / 2, \ + (i2sp)->config->size / 2); \ + if ((i2sp)->state == I2S_COMPLETE) \ + (i2sp)->state = I2S_READY; \ + } \ + else \ + (i2sp)->state = I2S_READY; \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void i2sInit(void); + void i2sObjectInit(I2SDriver *i2sp); + void i2sStart(I2SDriver *i2sp, const I2SConfig *config); + void i2sStop(I2SDriver *i2sp); + void i2sStartExchange(I2SDriver *i2sp); + void i2sStopExchange(I2SDriver *i2sp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2S == TRUE */ + +#endif /* _I2S_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_icu.h b/os/hal/include/hal_icu.h new file mode 100644 index 000000000..262b646fd --- /dev/null +++ b/os/hal/include/hal_icu.h @@ -0,0 +1,238 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file icu.h + * @brief ICU Driver macros and structures. + * + * @addtogroup ICU + * @{ + */ + +#ifndef _ICU_H_ +#define _ICU_H_ + +#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + ICU_UNINIT = 0, /**< Not initialized. */ + ICU_STOP = 1, /**< Stopped. */ + ICU_READY = 2, /**< Ready. */ + ICU_WAITING = 3, /**< Waiting for first front. */ + ICU_ACTIVE = 4 /**< First front detected. */ +} icustate_t; + +/** + * @brief Type of a structure representing an ICU driver. + */ +typedef struct ICUDriver ICUDriver; + +/** + * @brief ICU notification callback type. + * + * @param[in] icup pointer to a @p ICUDriver object + */ +typedef void (*icucallback_t)(ICUDriver *icup); + +#include "icu_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Starts the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @iclass + */ +#define icuStartCaptureI(icup) do { \ + icu_lld_start_capture(icup); \ + (icup)->state = ICU_WAITING; \ +} while (false) + +/** + * @brief Stops the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @iclass + */ +#define icuStopCaptureI(icup) do { \ + icu_lld_stop_capture(icup); \ + (icup)->state = ICU_READY; \ +} while (false) + +/** + * @brief Enables notifications. + * @pre The ICU unit must have been activated using @p icuStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @iclass + */ +#define icuEnableNotificationsI(icup) icu_lld_enable_notifications(icup) + +/** + * @brief Disables notifications. + * @pre The ICU unit must have been activated using @p icuStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @iclass + */ +#define icuDisableNotificationsI(icup) icu_lld_disable_notifications(icup) + +/** + * @brief Check on notifications status. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The notifications status. + * @retval false if notifications are not enabled. + * @retval true if notifications are enabled. + * + * @notapi + */ +#define icuAreNotificationsEnabledX(icup) \ + icu_lld_are_notifications_enabled(icup) + +/** + * @brief Returns the width of the latest pulse. + * @details The pulse width is defined as number of ticks between the start + * edge and the stop edge. + * @note This function is meant to be invoked from the width capture + * callback. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @xclass + */ +#define icuGetWidthX(icup) icu_lld_get_width(icup) + +/** + * @brief Returns the width of the latest cycle. + * @details The cycle width is defined as number of ticks between a start + * edge and the next start edge. + * @note This function is meant to be invoked from the width capture + * callback. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The number of ticks. + * + * @xclass + */ +#define icuGetPeriodX(icup) icu_lld_get_period(icup) +/** @} */ + +/** + * @name Low level driver helper macros + * @{ + */ +/** + * @brief Common ISR code, ICU width event. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +#define _icu_isr_invoke_width_cb(icup) do { \ + if (((icup)->state == ICU_ACTIVE) && \ + ((icup)->config->width_cb != NULL)) \ + (icup)->config->width_cb(icup); \ +} while (0) + +/** + * @brief Common ISR code, ICU period event. + * @note A period event brings the driver into the @p ICU_ACTIVE state. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +#define _icu_isr_invoke_period_cb(icup) do { \ + if (((icup)->state == ICU_ACTIVE) && \ + ((icup)->config->period_cb != NULL)) \ + (icup)->config->period_cb(icup); \ + (icup)->state = ICU_ACTIVE; \ +} while (0) + +/** + * @brief Common ISR code, ICU timer overflow event. + * @note An overflow always brings the driver back to the @p ICU_WAITING + * state. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @notapi + */ +#define _icu_isr_invoke_overflow_cb(icup) do { \ + (icup)->config->overflow_cb(icup); \ + (icup)->state = ICU_WAITING; \ +} while (0) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void icuInit(void); + void icuObjectInit(ICUDriver *icup); + void icuStart(ICUDriver *icup, const ICUConfig *config); + void icuStop(ICUDriver *icup); + void icuStartCapture(ICUDriver *icup); + bool icuWaitCapture(ICUDriver *icup); + void icuStopCapture(ICUDriver *icup); + void icuEnableNotifications(ICUDriver *icup); + void icuDisableNotifications(ICUDriver *icup); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_ICU == TRUE */ + +#endif /* _ICU_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_mac.h b/os/hal/include/hal_mac.h new file mode 100644 index 000000000..b5c49d01c --- /dev/null +++ b/os/hal/include/hal_mac.h @@ -0,0 +1,204 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file mac.h + * @brief MAC Driver macros and structures. + * @addtogroup MAC + * @{ + */ + +#ifndef _MAC_H_ +#define _MAC_H_ + +#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__) + +#include "mii.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name MAC configuration options + * @{ + */ +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + MAC_UNINIT = 0, /**< Not initialized. */ + MAC_STOP = 1, /**< Stopped. */ + MAC_ACTIVE = 2 /**< Active. */ +} macstate_t; + +/** + * @brief Type of a structure representing a MAC driver. + */ +typedef struct MACDriver MACDriver; + +#include "mac_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the received frames event source. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The pointer to the @p EventSource structure. + * + * @api + */ +#if (MAC_USE_EVENTS == TRUE) || defined(__DOXYGEN__) +#define macGetReceiveEventSource(macp) (&(macp)->rdevent) +#endif + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if the maximum frame + * size is reached. + * + * @api + */ +#define macWriteTransmitDescriptor(tdp, buf, size) \ + mac_lld_write_transmit_descriptor(tdp, buf, size) + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's stream, + * this value can be less than the amount specified in the + * parameter @p size if there are no more bytes to read. + * + * @api + */ +#define macReadReceiveDescriptor(rdp, buf, size) \ + mac_lld_read_receive_descriptor(rdp, buf, size) + +#if (MAC_USE_ZERO_COPY == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns a pointer to the next transmit buffer in the descriptor + * chain. + * @note The API guarantees that enough buffers can be requested to fill + * a whole frame. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] size size of the requested buffer. Specify the frame size + * on the first call then scale the value down subtracting + * the amount of data already copied into the previous + * buffers. + * @param[out] sizep pointer to variable receiving the real buffer size. + * The returned value can be less than the amount + * requested, this means that more buffers must be + * requested in order to fill the frame data entirely. + * @return Pointer to the returned buffer. + * + * @api + */ +#define macGetNextTransmitBuffer(tdp, size, sizep) \ + mac_lld_get_next_transmit_buffer(tdp, size, sizep) + +/** + * @brief Returns a pointer to the next receive buffer in the descriptor + * chain. + * @note The API guarantees that the descriptor chain contains a whole + * frame. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @api + */ +#define macGetNextReceiveBuffer(rdp, sizep) \ + mac_lld_get_next_receive_buffer(rdp, sizep) +#endif /* MAC_USE_ZERO_COPY */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void macInit(void); + void macObjectInit(MACDriver *macp); + void macStart(MACDriver *macp, const MACConfig *config); + void macStop(MACDriver *macp); + void macSetAddress(MACDriver *macp, const uint8_t *p); + msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t timeout); + void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp); + msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t timeout); + void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp); + bool macPollLinkStatus(MACDriver *macp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_MAC == TRUE */ + +#endif /* _MAC_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_mmc_spi.h b/os/hal/include/hal_mmc_spi.h new file mode 100644 index 000000000..7c9a60cae --- /dev/null +++ b/os/hal/include/hal_mmc_spi.h @@ -0,0 +1,195 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file mmc_spi.h + * @brief MMC over SPI driver header. + * + * @addtogroup MMC_SPI + * @{ + */ + +#ifndef _MMC_SPI_H_ +#define _MMC_SPI_H_ + +#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define MMC_CMD0_RETRY 10U +#define MMC_CMD1_RETRY 100U +#define MMC_ACMD41_RETRY 100U +#define MMC_WAIT_DATA 10000U + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name MMC_SPI configuration options + * @{ + */ +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if (HAL_USE_SPI == FALSE) || (SPI_USE_WAIT == FALSE) +#error "MMC_SPI driver requires HAL_USE_SPI and SPI_USE_WAIT" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief MMC/SD over SPI driver configuration structure. + */ +typedef struct { + /** + * @brief SPI driver associated to this MMC driver. + */ + SPIDriver *spip; + /** + * @brief SPI low speed configuration used during initialization. + */ + const SPIConfig *lscfg; + /** + * @brief SPI high speed configuration used during transfers. + */ + const SPIConfig *hscfg; +} MMCConfig; + +/** + * @brief @p MMCDriver specific methods. + */ +#define _mmc_driver_methods \ + _mmcsd_block_device_methods + +/** + * @extends MMCSDBlockDeviceVMT + * + * @brief @p MMCDriver virtual methods table. + */ +struct MMCDriverVMT { + _mmc_driver_methods +}; + +/** + * @extends MMCSDBlockDevice + * + * @brief Structure representing a MMC/SD over SPI driver. + */ +typedef struct { + /** + * @brief Virtual Methods Table. + */ + const struct MMCDriverVMT *vmt; + _mmcsd_block_device_data + /** + * @brief Current configuration data. + */ + const MMCConfig *config; + /*** + * @brief Addresses use blocks instead of bytes. + */ + bool block_addresses; +} MMCDriver; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the card insertion status. + * @note This macro wraps a low level function named + * @p sdc_lld_is_card_inserted(), this function must be + * provided by the application because it is not part of the + * SDC driver. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The card state. + * @retval FALSE card not inserted. + * @retval TRUE card inserted. + * + * @api + */ +#define mmcIsCardInserted(mmcp) mmc_lld_is_card_inserted(mmcp) + +/** + * @brief Returns the write protect status. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The card state. + * @retval FALSE card not inserted. + * @retval TRUE card inserted. + * + * @api + */ +#define mmcIsWriteProtected(mmcp) mmc_lld_is_write_protected(mmcp) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void mmcInit(void); + void mmcObjectInit(MMCDriver *mmcp); + void mmcStart(MMCDriver *mmcp, const MMCConfig *config); + void mmcStop(MMCDriver *mmcp); + bool mmcConnect(MMCDriver *mmcp); + bool mmcDisconnect(MMCDriver *mmcp); + bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk); + bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer); + bool mmcStopSequentialRead(MMCDriver *mmcp); + bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk); + bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer); + bool mmcStopSequentialWrite(MMCDriver *mmcp); + bool mmcSync(MMCDriver *mmcp); + bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip); + bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk); + bool mmc_lld_is_card_inserted(MMCDriver *mmcp); + bool mmc_lld_is_write_protected(MMCDriver *mmcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_MMC_SPI == TRUE */ + +#endif /* _MMC_SPI_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_pal.h b/os/hal/include/hal_pal.h new file mode 100644 index 000000000..df22f3e94 --- /dev/null +++ b/os/hal/include/hal_pal.h @@ -0,0 +1,642 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file pal.h + * @brief I/O Ports Abstraction Layer macros, types and structures. + * + * @addtogroup PAL + * @{ + */ + +#ifndef _PAL_H_ +#define _PAL_H_ + +#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Pads mode constants + * @{ + */ +/** + * @brief After reset state. + * @details The state itself is not specified and is architecture dependent, + * it is guaranteed to be equal to the after-reset state. It is + * usually an input state. + */ +#define PAL_MODE_RESET 0U + +/** + * @brief Safe state for unconnected pads. + * @details The state itself is not specified and is architecture dependent, + * it may be mapped on @p PAL_MODE_INPUT_PULLUP, + * @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL for + * example. + */ +#define PAL_MODE_UNCONNECTED 1U + +/** + * @brief Regular input high-Z pad. + */ +#define PAL_MODE_INPUT 2U + +/** + * @brief Input pad with weak pull up resistor. + */ +#define PAL_MODE_INPUT_PULLUP 3U + +/** + * @brief Input pad with weak pull down resistor. + */ +#define PAL_MODE_INPUT_PULLDOWN 4U + +/** + * @brief Analog input mode. + */ +#define PAL_MODE_INPUT_ANALOG 5U + +/** + * @brief Push-pull output pad. + */ +#define PAL_MODE_OUTPUT_PUSHPULL 6U + +/** + * @brief Open-drain output pad. + */ +#define PAL_MODE_OUTPUT_OPENDRAIN 7U +/** @} */ + +/** + * @name Logic level constants + * @{ + */ +/** + * @brief Logical low state. + */ +#define PAL_LOW 0U + +/** + * @brief Logical high state. + */ +#define PAL_HIGH 1U +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#include "pal_lld.h" + +/** + * @brief I/O bus descriptor. + * @details This structure describes a group of contiguous digital I/O lines + * that have to be handled as bus. + * @note I/O operations on a bus do not affect I/O lines on the same port but + * not belonging to the bus. + */ +typedef struct { + /** + * @brief Port identifier. + */ + ioportid_t portid; + /** + * @brief Bus mask aligned to port bit 0. + * @note The bus mask implicitly define the bus width. A logic AND is + * performed on the bus data. + */ + ioportmask_t mask; + /** + * @brief Offset, within the port, of the least significant bit of the bus. + */ + uint_fast8_t offset; +} IOBus; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Port bit helper macro. + * @details This macro calculates the mask of a bit within a port. + * + * @param[in] n bit position within the port + * @return The bit mask. + */ +#if !defined(PAL_PORT_BIT) || defined(__DOXYGEN__) +#define PAL_PORT_BIT(n) ((ioportmask_t)(1U << (n))) +#endif + +/** + * @brief Bits group mask helper. + * @details This macro calculates the mask of a bits group. + * + * @param[in] width group width + * @return The group mask. + */ +#if !defined(PAL_GROUP_MASK) || defined(__DOXYGEN__) +#define PAL_GROUP_MASK(width) ((ioportmask_t)(1U << (width)) - 1U) +#endif + +/** + * @brief Data part of a static I/O bus initializer. + * @details This macro should be used when statically initializing an I/O bus + * that is part of a bigger structure. + * + * @param[in] name name of the IOBus variable + * @param[in] port I/O port descriptor + * @param[in] width bus width in bits + * @param[in] offset bus bit offset within the port + */ +#define _IOBUS_DATA(name, port, width, offset) \ + {port, PAL_GROUP_MASK(width), offset} + +/** + * @brief Static I/O bus initializer. + * + * @param[in] name name of the IOBus variable + * @param[in] port I/O port descriptor + * @param[in] width bus width in bits + * @param[in] offset bus bit offset within the port + */ +#define IOBUS_DECL(name, port, width, offset) \ + IOBus name = _IOBUS_DATA(name, port, width, offset) + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief PAL subsystem initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @param[in] config pointer to an architecture specific configuration + * structure. This structure is defined in the low level driver + * header. + * + * @init + */ +#define palInit(config) pal_lld_init(config) + +/** + * @brief Reads the physical I/O port states. + * @note The default implementation always return zero and computes the + * parameter eventual side effects. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @return The port logic states. + * + * @special + */ +#if !defined(pal_lld_readport) || defined(__DOXYGEN__) +#define palReadPort(port) ((void)(port), 0U) +#else +#define palReadPort(port) pal_lld_readport(port) +#endif + +/** + * @brief Reads the output latch. + * @details The purpose of this function is to read back the latched output + * value. + * @note The default implementation always return zero and computes the + * parameter eventual side effects. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @return The latched logic states. + * + * @special + */ +#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__) +#define palReadLatch(port) ((void)(port), 0U) +#else +#define palReadLatch(port) pal_lld_readlatch(port) +#endif + +/** + * @brief Writes a bits mask on a I/O port. + * @note The default implementation does nothing except computing the + * parameters eventual side effects. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @special + */ +#if !defined(pal_lld_writeport) || defined(__DOXYGEN__) +#define palWritePort(port, bits) ((void)(port), (void)(bits)) +#else +#define palWritePort(port, bits) pal_lld_writeport(port, bits) +#endif + +/** + * @brief Sets a bits mask on a I/O port. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @special + */ +#if !defined(pal_lld_setport) || defined(__DOXYGEN__) +#define palSetPort(port, bits) \ + palWritePort(port, palReadLatch(port) | (bits)) +#else +#define palSetPort(port, bits) pal_lld_setport(port, bits) +#endif + +/** + * @brief Clears a bits mask on a I/O port. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @special + */ +#if !defined(pal_lld_clearport) || defined(__DOXYGEN__) +#define palClearPort(port, bits) \ + palWritePort(port, palReadLatch(port) & ~(bits)) +#else +#define palClearPort(port, bits) pal_lld_clearport(port, bits) +#endif + +/** + * @brief Toggles a bits mask on a I/O port. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] bits bits to be XORed on the specified port + * + * @special + */ +#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__) +#define palTogglePort(port, bits) \ + palWritePort(port, palReadLatch(port) ^ (bits)) +#else +#define palTogglePort(port, bits) pal_lld_toggleport(port, bits) +#endif + +/** + * @brief Reads a group of bits. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] mask group mask, a logic AND is performed on the input + * data + * @param[in] offset group bit offset within the port + * @return The group logic states. + * + * @special + */ +#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__) +#define palReadGroup(port, mask, offset) \ + ((palReadPort(port) >> (offset)) & (mask)) +#else +#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset) +#endif + +/** + * @brief Writes a group of bits. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] mask group mask, a logic AND is performed on the + * output data + * @param[in] offset group bit offset within the port + * @param[in] bits bits to be written. Values exceeding the group + * width are masked. + * + * @special + */ +#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__) +#define palWriteGroup(port, mask, offset, bits) \ + palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \ + (((bits) & (mask)) << (offset))) +#else +#define palWriteGroup(port, mask, offset, bits) \ + pal_lld_writegroup(port, mask, offset, bits) +#endif + + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note Programming an unknown or unsupported mode is silently ignored. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @special + */ +#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__) +#define palSetGroupMode(port, mask, offset, mode) +#else +#define palSetGroupMode(port, mask, offset, mode) \ + pal_lld_setgroupmode(port, mask, offset, mode) +#endif + +/** + * @brief Reads an input pad logic state. + * @note The default implementation not necessarily optimal. Low level + * drivers may optimize the function by using specific hardware + * or coding. + * @note The default implementation internally uses the @p palReadPort(). + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return The logic state. + * @retval PAL_LOW low logic state. + * @retval PAL_HIGH high logic state. + * + * @special + */ +#if !defined(pal_lld_readpad) || defined(__DOXYGEN__) +#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U) +#else +#define palReadPad(port, pad) pal_lld_readpad(port, pad) +#endif + +/** + * @brief Writes a logic state on an output pad. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palReadLatch() + * and @p palWritePort(). + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logic value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @special + */ +#if !defined(pal_lld_writepad) || defined(__DOXYGEN__) +#define palWritePad(port, pad, bit) \ + palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \ + (((bit) & 1U) << pad)) +#else +#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit) +#endif + +/** + * @brief Sets a pad logic state to @p PAL_HIGH. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palSetPort(). + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @special + */ +#if !defined(pal_lld_setpad) || defined(__DOXYGEN__) +#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad)) +#else +#define palSetPad(port, pad) pal_lld_setpad(port, pad) +#endif + +/** + * @brief Clears a pad logic state to @p PAL_LOW. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palClearPort(). + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @special + */ +#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__) +#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad)) +#else +#define palClearPad(port, pad) pal_lld_clearpad(port, pad) +#endif + +/** + * @brief Toggles a pad logic state. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palTogglePort(). + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @special + */ +#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__) +#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad)) +#else +#define palTogglePad(port, pad) pal_lld_togglepad(port, pad) +#endif + +/** + * @brief Pad mode setup. + * @details This function programs a pad with the specified mode. + * @note The default implementation not necessarily optimal. Low level + * drivers may optimize the function by using specific hardware + * or coding. + * @note Programming an unknown or unsupported mode is silently ignored. + * @note The function can be called from any context. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad mode + * + * @special + */ +#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__) +#define palSetPadMode(port, pad, mode) \ + palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode) +#else +#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode) +#endif + +/** + * @brief Reads an input line logic state. + * @note The function can be called from any context. + * + * @param[in] line line identifier + * @return The logic state. + * @retval PAL_LOW low logic state. + * @retval PAL_HIGH high logic state. + * + * @special + */ +#if !defined(pal_lld_readline) || defined(__DOXYGEN__) +#define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) +#else +#define palReadLine(line) pal_lld_readline(line) +#endif + +/** + * @brief Writes a logic state on an output line. + * @note The function can be called from any context. + * + * @param[in] line line identifier + * @param[in] bit logic value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @special + */ +#if !defined(pal_lld_writeline) || defined(__DOXYGEN__) +#define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit) +#else +#define palWriteLine(line, bit) pal_lld_writeline(line, bit) +#endif + +/** + * @brief Sets a line logic state to @p PAL_HIGH. + * @note The function can be called from any context. + * + * @param[in] line line identifier + * + * @special + */ +#if !defined(pal_lld_setline) || defined(__DOXYGEN__) +#define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) +#else +#define palSetLine(line) pal_lld_setline(line) +#endif + +/** + * @brief Clears a line logic state to @p PAL_LOW. + * @note The function can be called from any context. + * + * @param[in] line line identifier + * + * @special + */ +#if !defined(pal_lld_clearline) || defined(__DOXYGEN__) +#define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) +#else +#define palClearLine(line) pal_lld_clearline(line) +#endif + +/** + * @brief Toggles a line logic state. + * @note The function can be called from any context. + * + * @param[in] line line identifier + * + * @special + */ +#if !defined(pal_lld_toggleline) || defined(__DOXYGEN__) +#define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line)) +#else +#define palToggleLine(line) pal_lld_toggleline(line) +#endif + +/** + * @brief Line mode setup. + * @note The function can be called from any context. + * + * @param[in] line line identifier + * @param[in] mode pad mode + * + * @special + */ +#if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__) +#define palSetLineMode(line, mode) \ + palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode) +#else +#define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode) +#endif +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + ioportmask_t palReadBus(IOBus *bus); + void palWriteBus(IOBus *bus, ioportmask_t bits); + void palSetBusMode(IOBus *bus, iomode_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_H_ */ + +#endif /* HAL_USE_PAL == TRUE */ + +/** @} */ diff --git a/os/hal/include/hal_pwm.h b/os/hal/include/hal_pwm.h new file mode 100644 index 000000000..5704b40bc --- /dev/null +++ b/os/hal/include/hal_pwm.h @@ -0,0 +1,308 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file pwm.h + * @brief PWM Driver macros and structures. + * + * @addtogroup PWM + * @{ + */ + +#ifndef _PWM_H_ +#define _PWM_H_ + +#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name PWM output mode macros + * @{ + */ +/** + * @brief Standard output modes mask. + */ +#define PWM_OUTPUT_MASK 0x0FU + +/** + * @brief Output not driven, callback only. + */ +#define PWM_OUTPUT_DISABLED 0x00U + +/** + * @brief Positive PWM logic, active is logic level one. + */ +#define PWM_OUTPUT_ACTIVE_HIGH 0x01U + +/** + * @brief Inverse PWM logic, active is logic level zero. + */ +#define PWM_OUTPUT_ACTIVE_LOW 0x02U +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + PWM_UNINIT = 0, /**< Not initialized. */ + PWM_STOP = 1, /**< Stopped. */ + PWM_READY = 2 /**< Ready. */ +} pwmstate_t; + +/** + * @brief Type of a structure representing a PWM driver. + */ +typedef struct PWMDriver PWMDriver; + +/** + * @brief Type of a PWM notification callback. + * + * @param[in] pwmp pointer to a @p PWMDriver object + */ +typedef void (*pwmcallback_t)(PWMDriver *pwmp); + +#include "pwm_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name PWM duty cycle conversion + * @{ + */ +/** + * @brief Converts from fraction to pulse width. + * @note Be careful with rounding errors, this is integer math not magic. + * You can specify tenths of thousandth but make sure you have the + * proper hardware resolution by carefully choosing the clock source + * and prescaler settings, see @p PWM_COMPUTE_PSC. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] denominator denominator of the fraction + * @param[in] numerator numerator of the fraction + * @return The pulse width to be passed to @p pwmEnableChannel(). + * + * @api + */ +#define PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator) \ + ((pwmcnt_t)((((pwmcnt_t)(pwmp)->period) * \ + (pwmcnt_t)(numerator)) / (pwmcnt_t)(denominator))) + +/** + * @brief Converts from degrees to pulse width. + * @note Be careful with rounding errors, this is integer math not magic. + * You can specify hundredths of degrees but make sure you have the + * proper hardware resolution by carefully choosing the clock source + * and prescaler settings, see @p PWM_COMPUTE_PSC. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] degrees degrees as an integer between 0 and 36000 + * @return The pulse width to be passed to @p pwmEnableChannel(). + * + * @api + */ +#define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \ + PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees) + +/** + * @brief Converts from percentage to pulse width. + * @note Be careful with rounding errors, this is integer math not magic. + * You can specify tenths of thousandth but make sure you have the + * proper hardware resolution by carefully choosing the clock source + * and prescaler settings, see @p PWM_COMPUTE_PSC. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] percentage percentage as an integer between 0 and 10000 + * @return The pulse width to be passed to @p pwmEnableChannel(). + * + * @api + */ +#define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \ + PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage) +/** @} */ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] value new cycle time in ticks + * + * @iclass + */ +#define pwmChangePeriodI(pwmp, value) { \ + (pwmp)->period = (value); \ + pwm_lld_change_period(pwmp, value); \ +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @iclass + */ +#define pwmEnableChannelI(pwmp, channel, width) do { \ + (pwmp)->enabled |= ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \ + pwm_lld_enable_channel(pwmp, channel, width); \ +} while (false) + +/** + * @brief Disables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @iclass + */ +#define pwmDisableChannelI(pwmp, channel) do { \ + (pwmp)->enabled &= ~((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \ + pwm_lld_disable_channel(pwmp, channel); \ +} while (false) + +/** + * @brief Returns a PWM channel status. + * @pre The PWM unit must have been activated using @p pwmStart(). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @iclass + */ +#define pwmIsChannelEnabledI(pwmp, channel) \ + (((pwmp)->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel))) != 0U) + +/** + * @brief Enables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @iclass + */ +#define pwmEnablePeriodicNotificationI(pwmp) \ + pwm_lld_enable_periodic_notification(pwmp) + +/** + * @brief Disables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @iclass + */ +#define pwmDisablePeriodicNotificationI(pwmp) \ + pwm_lld_disable_periodic_notification(pwmp) + +/** + * @brief Enables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @iclass + */ +#define pwmEnableChannelNotificationI(pwmp, channel) \ + pwm_lld_enable_channel_notification(pwmp, channel) + +/** + * @brief Disables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @iclass + */ +#define pwmDisableChannelNotificationI(pwmp, channel) \ + pwm_lld_disable_channel_notification(pwmp, channel) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void pwmInit(void); + void pwmObjectInit(PWMDriver *pwmp); + void pwmStart(PWMDriver *pwmp, const PWMConfig *config); + void pwmStop(PWMDriver *pwmp); + void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period); + void pwmEnableChannel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); + void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel); + void pwmEnablePeriodicNotification(PWMDriver *pwmp); + void pwmDisablePeriodicNotification(PWMDriver *pwmp); + void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel); + void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM == TRUE */ + +#endif /* _PWM_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_rtc.h b/os/hal/include/hal_rtc.h new file mode 100644 index 000000000..e4c32ba64 --- /dev/null +++ b/os/hal/include/hal_rtc.h @@ -0,0 +1,144 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file rtc.h + * @brief RTC Driver macros and structures. + * + * @addtogroup RTC + * @{ + */ + +#ifndef _RTC_H_ +#define _RTC_H_ + +#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) + +/*lint -save -e829 [21.10] The header is required.*/ +#include +/*lint -restore*/ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Base year of the calendar. + */ +#define RTC_BASE_YEAR 1980U + +/** + * @name Date/Time bit masks for FAT format + * @{ + */ +#define RTC_FAT_TIME_SECONDS_MASK 0x0000001FU +#define RTC_FAT_TIME_MINUTES_MASK 0x000007E0U +#define RTC_FAT_TIME_HOURS_MASK 0x0000F800U +#define RTC_FAT_DATE_DAYS_MASK 0x001F0000U +#define RTC_FAT_DATE_MONTHS_MASK 0x01E00000U +#define RTC_FAT_DATE_YEARS_MASK 0xFE000000U +/** @} */ + +/** + * @name Day of week encoding + * @{ + */ +#define RTC_DAY_CATURDAY 0U +#define RTC_DAY_MONDAY 1U +#define RTC_DAY_TUESDAY 2U +#define RTC_DAY_WEDNESDAY 3U +#define RTC_DAY_THURSDAY 4U +#define RTC_DAY_FRIDAY 5U +#define RTC_DAY_SATURDAY 6U +#define RTC_DAY_SUNDAY 7U +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an RTC driver. + */ +typedef struct RTCDriver RTCDriver; + +/** + * @brief Type of a structure representing an RTC date/time stamp. + */ +typedef struct { + /*lint -save -e46 [6.1] In this case uint32_t is fine.*/ + uint32_t year: 8; /**< @brief Years since 1980. */ + uint32_t month: 4; /**< @brief Months 1..12. */ + uint32_t dstflag: 1; /**< @brief DST correction flag. */ + uint32_t dayofweek: 3; /**< @brief Day of week 1..7. */ + uint32_t day: 5; /**< @brief Day of the month 1..31. */ + uint32_t millisecond: 27; /**< @brief Milliseconds since midnight.*/ + /*lint -restore*/ +} RTCDateTime; + +#include "rtc_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void rtcInit(void); + void rtcObjectInit(RTCDriver *rtcp); + void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec); + void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec); +#if RTC_ALARMS > 0 + void rtcSetAlarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec); + void rtcGetAlarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec); +#endif +#if RTC_SUPPORTS_CALLBACKS == TRUE + void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback); +#endif + void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec, + struct tm *timp, + uint32_t *tv_msec); + void rtcConvertStructTmToDateTime(const struct tm *timp, + uint32_t tv_msec, + RTCDateTime *timespec); + uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_RTC == TRUE */ +#endif /* _RTC_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_sdc.h b/os/hal/include/hal_sdc.h new file mode 100644 index 000000000..954688658 --- /dev/null +++ b/os/hal/include/hal_sdc.h @@ -0,0 +1,195 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file sdc.h + * @brief SDC Driver macros and structures. + * + * @addtogroup SDC + * @{ + */ + +#ifndef _SDC_H_ +#define _SDC_H_ + +#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name SD card types + * @{ + */ +#define SDC_MODE_CARDTYPE_MASK 0xFU +#define SDC_MODE_CARDTYPE_SDV11 0U +#define SDC_MODE_CARDTYPE_SDV20 1U +#define SDC_MODE_CARDTYPE_MMC 2U +#define SDC_MODE_HIGH_CAPACITY 0x10U +/** @} */ + +/** + * @name SDC bus error conditions + * @{ + */ +#define SDC_NO_ERROR 0U +#define SDC_CMD_CRC_ERROR 1U +#define SDC_DATA_CRC_ERROR 2U +#define SDC_DATA_TIMEOUT 4U +#define SDC_COMMAND_TIMEOUT 8U +#define SDC_TX_UNDERRUN 16U +#define SDC_RX_OVERRUN 32U +#define SDC_STARTBIT_ERROR 64U +#define SDC_OVERFLOW_ERROR 128U +#define SDC_UNHANDLED_ERROR 0xFFFFFFFFU +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name SDC configuration options + * @{ + */ +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of SDIO bus mode. + */ +typedef enum { + SDC_MODE_1BIT = 0, + SDC_MODE_4BIT, + SDC_MODE_8BIT +} sdcbusmode_t; + +/** + * @brief Max supported clock. + */ +typedef enum { + SDC_CLK_25MHz = 0, + SDC_CLK_50MHz +} sdcbusclk_t; + +#include "sdc_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the card insertion status. + * @note This macro wraps a low level function named + * @p sdc_lld_is_card_inserted(), this function must be + * provided by the application because it is not part of the + * SDC driver. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @return The card state. + * @retval FALSE card not inserted. + * @retval TRUE card inserted. + * + * @api + */ +#define sdcIsCardInserted(sdcp) (sdc_lld_is_card_inserted(sdcp)) + +/** + * @brief Returns the write protect status. + * @note This macro wraps a low level function named + * @p sdc_lld_is_write_protected(), this function must be + * provided by the application because it is not part of the + * SDC driver. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @return The card state. + * @retval FALSE not write protected. + * @retval TRUE write protected. + * + * @api + */ +#define sdcIsWriteProtected(sdcp) (sdc_lld_is_write_protected(sdcp)) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void sdcInit(void); + void sdcObjectInit(SDCDriver *sdcp); + void sdcStart(SDCDriver *sdcp, const SDCConfig *config); + void sdcStop(SDCDriver *sdcp); + bool sdcConnect(SDCDriver *sdcp); + bool sdcDisconnect(SDCDriver *sdcp); + bool sdcRead(SDCDriver *sdcp, uint32_t startblk, + uint8_t *buf, uint32_t n); + bool sdcWrite(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t n); + sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp); + bool sdcSync(SDCDriver *sdcp); + bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip); + bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk); + bool _sdc_wait_for_transfer_state(SDCDriver *sdcp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SDC == TRUE */ + +#endif /* _SDC_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_serial.h b/os/hal/include/hal_serial.h new file mode 100644 index 000000000..814d54569 --- /dev/null +++ b/os/hal/include/hal_serial.h @@ -0,0 +1,286 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file serial.h + * @brief Serial Driver macros and structures. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef _SERIAL_H_ +#define _SERIAL_H_ + +#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Serial status flags + * @{ + */ +#define SD_PARITY_ERROR (eventflags_t)32 /**< @brief Parity. */ +#define SD_FRAMING_ERROR (eventflags_t)64 /**< @brief Framing. */ +#define SD_OVERRUN_ERROR (eventflags_t)128 /**< @brief Overflow. */ +#define SD_NOISE_ERROR (eventflags_t)256 /**< @brief Line noise. */ +#define SD_BREAK_DETECTED (eventflags_t)512 /**< @brief LIN Break. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Serial configuration options + * @{ + */ +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SD_UNINIT = 0, /**< Not initialized. */ + SD_STOP = 1, /**< Stopped. */ + SD_READY = 2 /**< Ready. */ +} sdstate_t; + +/** + * @brief Structure representing a serial driver. + */ +typedef struct SerialDriver SerialDriver; + +#include "serial_lld.h" + +/** + * @brief @p SerialDriver specific methods. + */ +#define _serial_driver_methods \ + _base_asynchronous_channel_methods + +/** + * @extends BaseAsynchronousChannelVMT + * + * @brief @p SerialDriver virtual methods table. + */ +struct SerialDriverVMT { + _serial_driver_methods +}; + +/** + * @extends BaseAsynchronousChannel + * + * @brief Full duplex serial driver class. + * @details This class extends @p BaseAsynchronousChannel by adding physical + * I/O queues. + */ +struct SerialDriver { + /** @brief Virtual Methods Table.*/ + const struct SerialDriverVMT *vmt; + _serial_driver_data +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Direct write to a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * writes directly on the output queue. This is faster but cannot + * be used to write to different channels implementations. + * + * @see chnPutTimeout() + * + * @api + */ +#define sdPut(sdp, b) oqPut(&(sdp)->oqueue, b) + +/** + * @brief Direct write to a @p SerialDriver with timeout specification. + * @note This function bypasses the indirect access to the channel and + * writes directly on the output queue. This is faster but cannot + * be used to write to different channels implementations. + * + * @see chnPutTimeout() + * + * @api + */ +#define sdPutTimeout(sdp, b, t) oqPutTimeout(&(sdp)->oqueue, b, t) + +/** + * @brief Direct read from a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * + * @see chnGetTimeout() + * + * @api + */ +#define sdGet(sdp) iqGet(&(sdp)->iqueue) + +/** + * @brief Direct read from a @p SerialDriver with timeout specification. + * @note This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * + * @see chnGetTimeout() + * + * @api + */ +#define sdGetTimeout(sdp, t) iqGetTimeout(&(sdp)->iqueue, t) + +/** + * @brief Direct blocking write to a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * writes directly to the output queue. This is faster but cannot + * be used to write from different channels implementations. + * + * @see chnWrite() + * + * @api + */ +#define sdWrite(sdp, b, n) \ + oqWriteTimeout(&(sdp)->oqueue, b, n, TIME_INFINITE) + +/** + * @brief Direct blocking write to a @p SerialDriver with timeout + * specification. + * @note This function bypasses the indirect access to the channel and + * writes directly to the output queue. This is faster but cannot + * be used to write to different channels implementations. + * + * @see chnWriteTimeout() + * + * @api + */ +#define sdWriteTimeout(sdp, b, n, t) \ + oqWriteTimeout(&(sdp)->oqueue, b, n, t) + +/** + * @brief Direct non-blocking write to a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * writes directly to the output queue. This is faster but cannot + * be used to write to different channels implementations. + * + * @see chnWriteTimeout() + * + * @api + */ +#define sdAsynchronousWrite(sdp, b, n) \ + oqWriteTimeout(&(sdp)->oqueue, b, n, TIME_IMMEDIATE) + +/** + * @brief Direct blocking read from a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * + * @see chnRead() + * + * @api + */ +#define sdRead(sdp, b, n) \ + iqReadTimeout(&(sdp)->iqueue, b, n, TIME_INFINITE) + +/** + * @brief Direct blocking read from a @p SerialDriver with timeout + * specification. + * @note This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * + * @see chnReadTimeout() + * + * @api + */ +#define sdReadTimeout(sdp, b, n, t) \ + iqReadTimeout(&(sdp)->iqueue, b, n, t) + +/** + * @brief Direct non-blocking read from a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * + * @see chnReadTimeout() + * + * @api + */ +#define sdAsynchronousRead(sdp, b, n) \ + iqReadTimeout(&(sdp)->iqueue, b, n, TIME_IMMEDIATE) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void sdInit(void); + void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify); + void sdStart(SerialDriver *sdp, const SerialConfig *config); + void sdStop(SerialDriver *sdp); + void sdIncomingDataI(SerialDriver *sdp, uint8_t b); + msg_t sdRequestDataI(SerialDriver *sdp); + bool sdPutWouldBlock(SerialDriver *sdp); + bool sdGetWouldBlock(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL == TRUE */ + +#endif /* _SERIAL_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_serial_usb.h b/os/hal/include/hal_serial_usb.h new file mode 100644 index 000000000..d4a1a1b57 --- /dev/null +++ b/os/hal/include/hal_serial_usb.h @@ -0,0 +1,195 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file serial_usb.h + * @brief Serial over USB Driver macros and structures. + * + * @addtogroup SERIAL_USB + * @{ + */ + +#ifndef _SERIAL_USB_H_ +#define _SERIAL_USB_H_ + +#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__) + +#include "usb_cdc.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name SERIAL_USB configuration options + * @{ + */ +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if HAL_USE_USB == FALSE +#error "Serial over USB Driver requires HAL_USE_USB" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SDU_UNINIT = 0, /**< Not initialized. */ + SDU_STOP = 1, /**< Stopped. */ + SDU_READY = 2 /**< Ready. */ +} sdustate_t; + +/** + * @brief Structure representing a serial over USB driver. + */ +typedef struct SerialUSBDriver SerialUSBDriver; + +/** + * @brief Serial over USB Driver configuration structure. + * @details An instance of this structure must be passed to @p sduStart() + * in order to configure and start the driver operations. + */ +typedef struct { + /** + * @brief USB driver to use. + */ + USBDriver *usbp; + /** + * @brief Bulk IN endpoint used for outgoing data transfer. + */ + usbep_t bulk_in; + /** + * @brief Bulk OUT endpoint used for incoming data transfer. + */ + usbep_t bulk_out; + /** + * @brief Interrupt IN endpoint used for notifications. + * @note If set to zero then the INT endpoint is assumed to be not + * present, USB descriptors must be changed accordingly. + */ + usbep_t int_in; +} SerialUSBConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_usb_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdustate_t state; \ + /* Input buffers queue.*/ \ + input_buffers_queue_t ibqueue; \ + /* Output queue.*/ \ + output_buffers_queue_t obqueue; \ + /* Input buffer.*/ \ + uint8_t ib[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \ + SERIAL_USB_BUFFERS_SIZE)]; \ + /* Output buffer.*/ \ + uint8_t ob[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \ + SERIAL_USB_BUFFERS_SIZE)]; \ + /* End of the mandatory fields.*/ \ + /* Current configuration data.*/ \ + const SerialUSBConfig *config; + +/** + * @brief @p SerialUSBDriver specific methods. + */ +#define _serial_usb_driver_methods \ + _base_asynchronous_channel_methods + +/** + * @extends BaseAsynchronousChannelVMT + * + * @brief @p SerialDriver virtual methods table. + */ +struct SerialUSBDriverVMT { + _serial_usb_driver_methods +}; + +/** + * @extends BaseAsynchronousChannel + * + * @brief Full duplex serial driver class. + * @details This class extends @p BaseAsynchronousChannel by adding physical + * I/O queues. + */ +struct SerialUSBDriver { + /** @brief Virtual Methods Table.*/ + const struct SerialUSBDriverVMT *vmt; + _serial_usb_driver_data +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void sduInit(void); + void sduObjectInit(SerialUSBDriver *sdup); + void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config); + void sduStop(SerialUSBDriver *sdup); + void sduDisconnectI(SerialUSBDriver *sdup); + void sduConfigureHookI(SerialUSBDriver *sdup); + bool sduRequestsHook(USBDriver *usbp); + void sduSOFHookI(SerialUSBDriver *sdup); + void sduDataTransmitted(USBDriver *usbp, usbep_t ep); + void sduDataReceived(USBDriver *usbp, usbep_t ep); + void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL_USB == TRUE */ + +#endif /* _SERIAL_USB_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_spi.h b/os/hal/include/hal_spi.h new file mode 100644 index 000000000..45dd0880b --- /dev/null +++ b/os/hal/include/hal_spi.h @@ -0,0 +1,291 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file spi.h + * @brief SPI Driver macros and structures. + * + * @addtogroup SPI + * @{ + */ + +#ifndef _SPI_H_ +#define _SPI_H_ + +#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name SPI configuration options + * @{ + */ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SPI_UNINIT = 0, /**< Not initialized. */ + SPI_STOP = 1, /**< Stopped. */ + SPI_READY = 2, /**< Ready. */ + SPI_ACTIVE = 3, /**< Exchanging data. */ + SPI_COMPLETE = 4 /**< Asynchronous operation complete. */ +} spistate_t; + +#include "spi_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @iclass + */ +#define spiSelectI(spip) { \ + spi_lld_select(spip); \ +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @iclass + */ +#define spiUnselectI(spip) { \ + spi_lld_unselect(spip); \ +} + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @iclass + */ +#define spiStartIgnoreI(spip, n) { \ + (spip)->state = SPI_ACTIVE; \ + spi_lld_ignore(spip, n); \ +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @iclass + */ +#define spiStartExchangeI(spip, n, txbuf, rxbuf) { \ + (spip)->state = SPI_ACTIVE; \ + spi_lld_exchange(spip, n, txbuf, rxbuf); \ +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @iclass + */ +#define spiStartSendI(spip, n, txbuf) { \ + (spip)->state = SPI_ACTIVE; \ + spi_lld_send(spip, n, txbuf); \ +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @iclass + */ +#define spiStartReceiveI(spip, n, rxbuf) { \ + (spip)->state = SPI_ACTIVE; \ + spi_lld_receive(spip, n, rxbuf); \ +} + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * @note This API is implemented as a macro in order to minimize latency. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +#define spiPolledExchange(spip, frame) spi_lld_polled_exchange(spip, frame) +/** @} */ + +/** + * @name Low level driver helper macros + * @{ + */ +#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Wakes up the waiting thread. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +#define _spi_wakeup_isr(spip) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(spip)->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} +#else /* !SPI_USE_WAIT */ +#define _spi_wakeup_isr(spip) +#endif /* !SPI_USE_WAIT */ + +/** + * @brief Common ISR code. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +#define _spi_isr_code(spip) { \ + if ((spip)->config->end_cb) { \ + (spip)->state = SPI_COMPLETE; \ + (spip)->config->end_cb(spip); \ + if ((spip)->state == SPI_COMPLETE) \ + (spip)->state = SPI_READY; \ + } \ + else \ + (spip)->state = SPI_READY; \ + _spi_wakeup_isr(spip); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void spiInit(void); + void spiObjectInit(SPIDriver *spip); + void spiStart(SPIDriver *spip, const SPIConfig *config); + void spiStop(SPIDriver *spip); + void spiSelect(SPIDriver *spip); + void spiUnselect(SPIDriver *spip); + void spiStartIgnore(SPIDriver *spip, size_t n); + void spiStartExchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf); + void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf); +#if SPI_USE_WAIT == TRUE + void spiIgnore(SPIDriver *spip, size_t n); + void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); + void spiSend(SPIDriver *spip, size_t n, const void *txbuf); + void spiReceive(SPIDriver *spip, size_t n, void *rxbuf); +#endif +#if SPI_USE_MUTUAL_EXCLUSION == TRUE + void spiAcquireBus(SPIDriver *spip); + void spiReleaseBus(SPIDriver *spip); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI == TRUE */ + +#endif /* _SPI_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_st.h b/os/hal/include/hal_st.h new file mode 100644 index 000000000..3bd50e854 --- /dev/null +++ b/os/hal/include/hal_st.h @@ -0,0 +1,97 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file st.h + * @brief ST Driver macros and structures. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup ST + * @{ + */ + +#ifndef _ST_H_ +#define _ST_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#include "st_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the time counter value. + * @note This functionality is only available in free running mode, the + * behaviour in periodic mode is undefined. + * + * @return The counter value. + * + * @api + */ +#define stGetCounter() st_lld_get_counter() + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @api + */ +#define stIsAlarmActive() st_lld_is_alarm_active() +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void stInit(void); + void stStartAlarm(systime_t abstime); + void stStopAlarm(void); + void stSetAlarm(systime_t abstime); + systime_t stGetAlarm(void); +#ifdef __cplusplus +} +#endif + +#endif /* _ST_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_uart.h b/os/hal/include/hal_uart.h new file mode 100644 index 000000000..a0a8eecdf --- /dev/null +++ b/os/hal/include/hal_uart.h @@ -0,0 +1,342 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file uart.h + * @brief UART Driver macros and structures. + * + * @addtogroup UART + * @{ + */ + +#ifndef _UART_H_ +#define _UART_H_ + +#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name UART status flags + * @{ + */ +#define UART_NO_ERROR 0 /**< @brief No pending conditions. */ +#define UART_PARITY_ERROR 4 /**< @brief Parity error happened. */ +#define UART_FRAMING_ERROR 8 /**< @brief Framing error happened. */ +#define UART_OVERRUN_ERROR 16 /**< @brief Overflow happened. */ +#define UART_NOISE_ERROR 32 /**< @brief Noise on the line. */ +#define UART_BREAK_DETECTED 64 /**< @brief Break detected. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name UART configuration options + * @{ + */ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + UART_UNINIT = 0, /**< Not initialized. */ + UART_STOP = 1, /**< Stopped. */ + UART_READY = 2 /**< Ready. */ +} uartstate_t; + +/** + * @brief Transmitter state machine states. + */ +typedef enum { + UART_TX_IDLE = 0, /**< Not transmitting. */ + UART_TX_ACTIVE = 1, /**< Transmitting. */ + UART_TX_COMPLETE = 2 /**< Buffer complete. */ +} uarttxstate_t; + +/** + * @brief Receiver state machine states. + */ +typedef enum { + UART_RX_IDLE = 0, /**< Not receiving. */ + UART_RX_ACTIVE = 1, /**< Receiving. */ + UART_RX_COMPLETE = 2 /**< Buffer complete. */ +} uartrxstate_t; + +#include "uart_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Low level driver helper macros + * @{ + */ +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Wakes up the waiting thread in case of early TX complete. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_wakeup_tx1_isr(uartp) { \ + if ((uartp)->early == true) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \ + osalSysUnlockFromISR(); \ + } \ +} +#else /* !UART_USE_WAIT */ +#define _uart_wakeup_tx1_isr(uartp) +#endif /* !UART_USE_WAIT */ + +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Wakes up the waiting thread in case of late TX complete. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_wakeup_tx2_isr(uartp) { \ + if ((uartp)->early == false) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \ + osalSysUnlockFromISR(); \ + } \ +} +#else /* !UART_USE_WAIT */ +#define _uart_wakeup_tx2_isr(uartp) +#endif /* !UART_USE_WAIT */ + +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Wakes up the waiting thread in case of RX complete. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_wakeup_rx_complete_isr(uartp) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(uartp)->threadrx, MSG_OK); \ + osalSysUnlockFromISR(); \ +} +#else /* !UART_USE_WAIT */ +#define _uart_wakeup_rx_complete_isr(uartp) +#endif /* !UART_USE_WAIT */ + +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Wakes up the waiting thread in case of RX error. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_wakeup_rx_error_isr(uartp) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(uartp)->threadrx, MSG_RESET); \ + osalSysUnlockFromISR(); \ +} +#else /* !UART_USE_WAIT */ +#define _uart_wakeup_rx_error_isr(uartp) +#endif /* !UART_USE_WAIT */ + +/** + * @brief Common ISR code for early TX. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_tx1_isr_code(uartp) { \ + (uartp)->txstate = UART_TX_COMPLETE; \ + if ((uartp)->config->txend1_cb != NULL) { \ + (uartp)->config->txend1_cb(uartp); \ + } \ + if ((uartp)->txstate == UART_TX_COMPLETE) { \ + (uartp)->txstate = UART_TX_IDLE; \ + } \ + _uart_wakeup_tx1_isr(uartp); \ +} + +/** + * @brief Common ISR code for late TX. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_tx2_isr_code(uartp) { \ + if ((uartp)->config->txend2_cb != NULL) { \ + (uartp)->config->txend2_cb(uartp); \ + } \ + _uart_wakeup_tx2_isr(uartp); \ +} + +/** + * @brief Common ISR code for RX complete. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_rx_complete_isr_code(uartp) { \ + (uartp)->rxstate = UART_RX_COMPLETE; \ + if ((uartp)->config->rxend_cb != NULL) { \ + (uartp)->config->rxend_cb(uartp); \ + } \ + if ((uartp)->rxstate == UART_RX_COMPLETE) { \ + (uartp)->rxstate = UART_RX_IDLE; \ + uart_enter_rx_idle_loop(uartp); \ + } \ + _uart_wakeup_rx_complete_isr(uartp); \ +} + +/** + * @brief Common ISR code for RX error. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] errors mask of errors to be reported + * + * @notapi + */ +#define _uart_rx_error_isr_code(uartp, errors) { \ + if ((uartp)->config->rxerr_cb != NULL) { \ + (uartp)->config->rxerr_cb(uartp, errors); \ + } \ + _uart_wakeup_rx_error_isr(uartp); \ +} + + +/** + * @brief Common ISR code for RX on idle. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @notapi + */ +#define _uart_rx_idle_code(uartp) { \ + if ((uartp)->config->rxchar_cb != NULL) \ + (uartp)->config->rxchar_cb(uartp, (uartp)->rxbuf); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void uartInit(void); + void uartObjectInit(UARTDriver *uartp); + void uartStart(UARTDriver *uartp, const UARTConfig *config); + void uartStop(UARTDriver *uartp); + void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf); + void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf); + size_t uartStopSend(UARTDriver *uartp); + size_t uartStopSendI(UARTDriver *uartp); + void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf); + void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf); + size_t uartStopReceive(UARTDriver *uartp); + size_t uartStopReceiveI(UARTDriver *uartp); +#if UART_USE_WAIT == TRUE + msg_t uartSendTimeout(UARTDriver *uartp, size_t *np, + const void *txbuf, systime_t timeout); + msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np, + const void *txbuf, systime_t timeout); + msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np, + void *rxbuf, systime_t timeout); +#endif +#if UART_USE_MUTUAL_EXCLUSION == TRUE + void uartAcquireBus(UARTDriver *uartp); + void uartReleaseBus(UARTDriver *uartp); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_UART == TRUE */ + +#endif /* _UART_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_usb.h b/os/hal/include/hal_usb.h new file mode 100644 index 000000000..15d72cc43 --- /dev/null +++ b/os/hal/include/hal_usb.h @@ -0,0 +1,633 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file usb.h + * @brief USB Driver macros and structures. + * + * @addtogroup USB + * @{ + */ + +#ifndef _USB_H_ +#define _USB_H_ + +#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define USB_ENDPOINT_OUT(ep) (ep) +#define USB_ENDPOINT_IN(ep) ((ep) | 0x80U) + +#define USB_RTYPE_DIR_MASK 0x80U +#define USB_RTYPE_DIR_HOST2DEV 0x00U +#define USB_RTYPE_DIR_DEV2HOST 0x80U +#define USB_RTYPE_TYPE_MASK 0x60U +#define USB_RTYPE_TYPE_STD 0x00U +#define USB_RTYPE_TYPE_CLASS 0x20U +#define USB_RTYPE_TYPE_VENDOR 0x40U +#define USB_RTYPE_TYPE_RESERVED 0x60U +#define USB_RTYPE_RECIPIENT_MASK 0x1FU +#define USB_RTYPE_RECIPIENT_DEVICE 0x00U +#define USB_RTYPE_RECIPIENT_INTERFACE 0x01U +#define USB_RTYPE_RECIPIENT_ENDPOINT 0x02U +#define USB_RTYPE_RECIPIENT_OTHER 0x03U + +#define USB_REQ_GET_STATUS 0U +#define USB_REQ_CLEAR_FEATURE 1U +#define USB_REQ_SET_FEATURE 3U +#define USB_REQ_SET_ADDRESS 5U +#define USB_REQ_GET_DESCRIPTOR 6U +#define USB_REQ_SET_DESCRIPTOR 7U +#define USB_REQ_GET_CONFIGURATION 8U +#define USB_REQ_SET_CONFIGURATION 9U +#define USB_REQ_GET_INTERFACE 10U +#define USB_REQ_SET_INTERFACE 11U +#define USB_REQ_SYNCH_FRAME 12U + +#define USB_DESCRIPTOR_DEVICE 1U +#define USB_DESCRIPTOR_CONFIGURATION 2U +#define USB_DESCRIPTOR_STRING 3U +#define USB_DESCRIPTOR_INTERFACE 4U +#define USB_DESCRIPTOR_ENDPOINT 5U +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 6U +#define USB_DESCRIPTOR_OTHER_SPEED_CFG 7U +#define USB_DESCRIPTOR_INTERFACE_POWER 8U +#define USB_DESCRIPTOR_INTERFACE_ASSOCIATION 11U + +#define USB_FEATURE_ENDPOINT_HALT 0U +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1U +#define USB_FEATURE_TEST_MODE 2U + +#define USB_EARLY_SET_ADDRESS 0 +#define USB_LATE_SET_ADDRESS 1 + +#define USB_EP0_STATUS_STAGE_SW 0 +#define USB_EP0_STATUS_STAGE_HW 1 + +#define USB_SET_ADDRESS_ACK_SW 0 +#define USB_SET_ADDRESS_ACK_HW 1 + +/** + * @name Helper macros for USB descriptors + * @{ + */ +/** + * @brief Helper macro for index values into descriptor strings. + */ +#define USB_DESC_INDEX(i) ((uint8_t)(i)) + +/** + * @brief Helper macro for byte values into descriptor strings. + */ +#define USB_DESC_BYTE(b) ((uint8_t)(b)) + +/** + * @brief Helper macro for word values into descriptor strings. + */ +#define USB_DESC_WORD(w) \ + (uint8_t)((w) & 255U), \ + (uint8_t)(((w) >> 8) & 255U) + +/** + * @brief Helper macro for BCD values into descriptor strings. + */ +#define USB_DESC_BCD(bcd) \ + (uint8_t)((bcd) & 255U), \ + (uint8_t)(((bcd) >> 8) & 255) + +/* + * @define Device Descriptor size. + */ +#define USB_DESC_DEVICE_SIZE 18U + +/** + * @brief Device Descriptor helper macro. + */ +#define USB_DESC_DEVICE(bcdUSB, bDeviceClass, bDeviceSubClass, \ + bDeviceProtocol, bMaxPacketSize, idVendor, \ + idProduct, bcdDevice, iManufacturer, \ + iProduct, iSerialNumber, bNumConfigurations) \ + USB_DESC_BYTE(USB_DESC_DEVICE_SIZE), \ + USB_DESC_BYTE(USB_DESCRIPTOR_DEVICE), \ + USB_DESC_BCD(bcdUSB), \ + USB_DESC_BYTE(bDeviceClass), \ + USB_DESC_BYTE(bDeviceSubClass), \ + USB_DESC_BYTE(bDeviceProtocol), \ + USB_DESC_BYTE(bMaxPacketSize), \ + USB_DESC_WORD(idVendor), \ + USB_DESC_WORD(idProduct), \ + USB_DESC_BCD(bcdDevice), \ + USB_DESC_INDEX(iManufacturer), \ + USB_DESC_INDEX(iProduct), \ + USB_DESC_INDEX(iSerialNumber), \ + USB_DESC_BYTE(bNumConfigurations) + +/** + * @brief Configuration Descriptor size. + */ +#define USB_DESC_CONFIGURATION_SIZE 9U + +/** + * @brief Configuration Descriptor helper macro. + */ +#define USB_DESC_CONFIGURATION(wTotalLength, bNumInterfaces, \ + bConfigurationValue, iConfiguration, \ + bmAttributes, bMaxPower) \ + USB_DESC_BYTE(USB_DESC_CONFIGURATION_SIZE), \ + USB_DESC_BYTE(USB_DESCRIPTOR_CONFIGURATION), \ + USB_DESC_WORD(wTotalLength), \ + USB_DESC_BYTE(bNumInterfaces), \ + USB_DESC_BYTE(bConfigurationValue), \ + USB_DESC_INDEX(iConfiguration), \ + USB_DESC_BYTE(bmAttributes), \ + USB_DESC_BYTE(bMaxPower) + +/** + * @brief Interface Descriptor size. + */ +#define USB_DESC_INTERFACE_SIZE 9U + +/** + * @brief Interface Descriptor helper macro. + */ +#define USB_DESC_INTERFACE(bInterfaceNumber, bAlternateSetting, \ + bNumEndpoints, bInterfaceClass, \ + bInterfaceSubClass, bInterfaceProtocol, \ + iInterface) \ + USB_DESC_BYTE(USB_DESC_INTERFACE_SIZE), \ + USB_DESC_BYTE(USB_DESCRIPTOR_INTERFACE), \ + USB_DESC_BYTE(bInterfaceNumber), \ + USB_DESC_BYTE(bAlternateSetting), \ + USB_DESC_BYTE(bNumEndpoints), \ + USB_DESC_BYTE(bInterfaceClass), \ + USB_DESC_BYTE(bInterfaceSubClass), \ + USB_DESC_BYTE(bInterfaceProtocol), \ + USB_DESC_INDEX(iInterface) + +/** + * @brief Interface Association Descriptor size. + */ +#define USB_DESC_INTERFACE_ASSOCIATION_SIZE 8U + +/** + * @brief Interface Association Descriptor helper macro. + */ +#define USB_DESC_INTERFACE_ASSOCIATION(bFirstInterface, \ + bInterfaceCount, bFunctionClass, \ + bFunctionSubClass, bFunctionProcotol, \ + iInterface) \ + USB_DESC_BYTE(USB_DESC_INTERFACE_ASSOCIATION_SIZE), \ + USB_DESC_BYTE(USB_DESCRIPTOR_INTERFACE_ASSOCIATION), \ + USB_DESC_BYTE(bFirstInterface), \ + USB_DESC_BYTE(bInterfaceCount), \ + USB_DESC_BYTE(bFunctionClass), \ + USB_DESC_BYTE(bFunctionSubClass), \ + USB_DESC_BYTE(bFunctionProcotol), \ + USB_DESC_INDEX(iInterface) + +/** + * @brief Endpoint Descriptor size. + */ +#define USB_DESC_ENDPOINT_SIZE 7U + +/** + * @brief Endpoint Descriptor helper macro. + */ +#define USB_DESC_ENDPOINT(bEndpointAddress, bmAttributes, wMaxPacketSize, \ + bInterval) \ + USB_DESC_BYTE(USB_DESC_ENDPOINT_SIZE), \ + USB_DESC_BYTE(USB_DESCRIPTOR_ENDPOINT), \ + USB_DESC_BYTE(bEndpointAddress), \ + USB_DESC_BYTE(bmAttributes), \ + USB_DESC_WORD(wMaxPacketSize), \ + USB_DESC_BYTE(bInterval) +/** @} */ + +/** + * @name Endpoint types and settings + * @{ + */ +#define USB_EP_MODE_TYPE 0x0003U /**< Endpoint type mask. */ +#define USB_EP_MODE_TYPE_CTRL 0x0000U /**< Control endpoint. */ +#define USB_EP_MODE_TYPE_ISOC 0x0001U /**< Isochronous endpoint. */ +#define USB_EP_MODE_TYPE_BULK 0x0002U /**< Bulk endpoint. */ +#define USB_EP_MODE_TYPE_INTR 0x0003U /**< Interrupt endpoint. */ +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an USB driver. + */ +typedef struct USBDriver USBDriver; + +/** + * @brief Type of an endpoint identifier. + */ +typedef uint8_t usbep_t; + +/** + * @brief Type of a driver state machine possible states. + */ +typedef enum { + USB_UNINIT = 0, /**< Not initialized. */ + USB_STOP = 1, /**< Stopped. */ + USB_READY = 2, /**< Ready, after bus reset. */ + USB_SELECTED = 3, /**< Address assigned. */ + USB_ACTIVE = 4, /**< Active, configuration selected.*/ + USB_SUSPENDED = 5 /**< Suspended, low power mode. */ +} usbstate_t; + +/** + * @brief Type of an endpoint status. + */ +typedef enum { + EP_STATUS_DISABLED = 0, /**< Endpoint not active. */ + EP_STATUS_STALLED = 1, /**< Endpoint opened but stalled. */ + EP_STATUS_ACTIVE = 2 /**< Active endpoint. */ +} usbepstatus_t; + +/** + * @brief Type of an endpoint zero state machine states. + */ +typedef enum { + USB_EP0_WAITING_SETUP, /**< Waiting for SETUP data. */ + USB_EP0_TX, /**< Transmitting. */ + USB_EP0_WAITING_TX0, /**< Waiting transmit 0. */ + USB_EP0_WAITING_STS, /**< Waiting status. */ + USB_EP0_RX, /**< Receiving. */ + USB_EP0_SENDING_STS, /**< Sending status. */ + USB_EP0_ERROR /**< Error, EP0 stalled. */ +} usbep0state_t; + +/** + * @brief Type of an enumeration of the possible USB events. + */ +typedef enum { + USB_EVENT_RESET = 0, /**< Driver has been reset by host. */ + USB_EVENT_ADDRESS = 1, /**< Address assigned. */ + USB_EVENT_CONFIGURED = 2, /**< Configuration selected. */ + USB_EVENT_SUSPEND = 3, /**< Entering suspend mode. */ + USB_EVENT_WAKEUP = 4, /**< Leaving suspend mode. */ + USB_EVENT_STALLED = 5 /**< Endpoint 0 error, stalled. */ +} usbevent_t; + +/** + * @brief Type of an USB descriptor. + */ +typedef struct { + /** + * @brief Descriptor size in unicode characters. + */ + size_t ud_size; + /** + * @brief Pointer to the descriptor. + */ + const uint8_t *ud_string; +} USBDescriptor; + +/** + * @brief Type of an USB generic notification callback. + * + * @param[in] usbp pointer to the @p USBDriver object triggering the + * callback + */ +typedef void (*usbcallback_t)(USBDriver *usbp); + +/** + * @brief Type of an USB endpoint callback. + * + * @param[in] usbp pointer to the @p USBDriver object triggering the + * callback + * @param[in] ep endpoint number + */ +typedef void (*usbepcallback_t)(USBDriver *usbp, usbep_t ep); + +/** + * @brief Type of an USB event notification callback. + * + * @param[in] usbp pointer to the @p USBDriver object triggering the + * callback + * @param[in] event event type + */ +typedef void (*usbeventcb_t)(USBDriver *usbp, usbevent_t event); + +/** + * @brief Type of a requests handler callback. + * @details The request is encoded in the @p usb_setup buffer. + * + * @param[in] usbp pointer to the @p USBDriver object triggering the + * callback + * @return The request handling exit code. + * @retval false Request not recognized by the handler. + * @retval true Request handled. + */ +typedef bool (*usbreqhandler_t)(USBDriver *usbp); + +/** + * @brief Type of an USB descriptor-retrieving callback. + */ +typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang); + +#include "usb_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the driver state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The driver state. + * + * @iclass + */ +#define usbGetDriverStateI(usbp) ((usbp)->state) + +/** + * @brief Connects the USB device. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @api + */ +#define usbConnectBus(usbp) usb_lld_connect_bus(usbp) + +/** + * @brief Disconnect the USB device. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @api + */ +#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp) + +/** + * @brief Returns the current frame number. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The current frame number. + * + * @xclass + */ +#define usbGetFrameNumberX(usbp) usb_lld_get_frame_number(usbp) + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The operation status. + * @retval false Endpoint ready. + * @retval true Endpoint transmitting. + * + * @iclass + */ +#define usbGetTransmitStatusI(usbp, ep) \ + (((usbp)->transmitting & (uint16_t)((unsigned)1U << (unsigned)(ep))) != 0U) + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The operation status. + * @retval false Endpoint ready. + * @retval true Endpoint receiving. + * + * @iclass + */ +#define usbGetReceiveStatusI(usbp, ep) \ + (((usbp)->receiving & (uint16_t)((unsigned)1U << (unsigned)(ep))) != 0U) + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @xclass + */ +#define usbGetReceiveTransactionSizeX(usbp, ep) \ + usb_lld_get_transaction_size(usbp, ep) + +/** + * @brief Request transfer setup. + * @details This macro is used by the request handling callbacks in order to + * prepare a transaction over the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] buf pointer to a buffer for the transaction data + * @param[in] n number of bytes to be transferred + * @param[in] endcb callback to be invoked after the transfer or @p NULL + * + * @special + */ +#define usbSetupTransfer(usbp, buf, n, endcb) { \ + (usbp)->ep0next = (buf); \ + (usbp)->ep0n = (n); \ + (usbp)->ep0endcb = (endcb); \ +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @note This function can be invoked both in thread and IRQ context. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @special + */ +#define usbReadSetup(usbp, ep, buf) usb_lld_read_setup(usbp, ep, buf) +/** @} */ + +/** + * @name Low level driver helper macros + * @{ + */ +/** + * @brief Common ISR code, usb event callback. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] evt USB event code + * + * @notapi + */ +#define _usb_isr_invoke_event_cb(usbp, evt) { \ + if (((usbp)->config->event_cb) != NULL) { \ + (usbp)->config->event_cb(usbp, evt); \ + } \ +} + +/** + * @brief Common ISR code, SOF callback. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +#define _usb_isr_invoke_sof_cb(usbp) { \ + if (((usbp)->config->sof_cb) != NULL) { \ + (usbp)->config->sof_cb(usbp); \ + } \ +} + +/** + * @brief Common ISR code, setup packet callback. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +#define _usb_isr_invoke_setup_cb(usbp, ep) { \ + (usbp)->epc[ep]->setup_cb(usbp, ep); \ +} + +/** + * @brief Common ISR code, IN endpoint callback. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) +#define _usb_isr_invoke_in_cb(usbp, ep) { \ + (usbp)->transmitting &= ~(1 << (ep)); \ + if ((usbp)->epc[ep]->in_cb != NULL) { \ + (usbp)->epc[ep]->in_cb(usbp, ep); \ + } \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(usbp)->epc[ep]->in_state->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} +#else +#define _usb_isr_invoke_in_cb(usbp, ep) { \ + (usbp)->transmitting &= ~(1 << (ep)); \ + if ((usbp)->epc[ep]->in_cb != NULL) { \ + (usbp)->epc[ep]->in_cb(usbp, ep); \ + } \ +} +#endif + +/** + * @brief Common ISR code, OUT endpoint event. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) +#define _usb_isr_invoke_out_cb(usbp, ep) { \ + (usbp)->receiving &= ~(1 << (ep)); \ + if ((usbp)->epc[ep]->out_cb != NULL) { \ + (usbp)->epc[ep]->out_cb(usbp, ep); \ + } \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \ + usbGetReceiveTransactionSizeX(usbp, ep)); \ + osalSysUnlockFromISR(); \ +} +#else +#define _usb_isr_invoke_out_cb(usbp, ep) { \ + (usbp)->receiving &= ~(1 << (ep)); \ + if ((usbp)->epc[ep]->out_cb != NULL) { \ + (usbp)->epc[ep]->out_cb(usbp, ep); \ + } \ +} +#endif +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void usbInit(void); + void usbObjectInit(USBDriver *usbp); + void usbStart(USBDriver *usbp, const USBConfig *config); + void usbStop(USBDriver *usbp); + void usbInitEndpointI(USBDriver *usbp, usbep_t ep, + const USBEndpointConfig *epcp); + void usbDisableEndpointsI(USBDriver *usbp); + void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usbStartReceiveI(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n); + void usbStartTransmitI(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n); +#if USB_USE_WAIT == TRUE + msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n); + msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n); +#endif + bool usbStallReceiveI(USBDriver *usbp, usbep_t ep); + bool usbStallTransmitI(USBDriver *usbp, usbep_t ep); + void _usb_reset(USBDriver *usbp); + void _usb_suspend(USBDriver *usbp); + void _usb_wakeup(USBDriver *usbp); + void _usb_ep0setup(USBDriver *usbp, usbep_t ep); + void _usb_ep0in(USBDriver *usbp, usbep_t ep); + void _usb_ep0out(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB == TRUE */ + +#endif /* _USB_H_ */ + +/** @} */ diff --git a/os/hal/include/hal_wdg.h b/os/hal/include/hal_wdg.h new file mode 100644 index 000000000..d10b4a73f --- /dev/null +++ b/os/hal/include/hal_wdg.h @@ -0,0 +1,89 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file wdg.h + * @brief WDG Driver macros and structures. + * + * @addtogroup WDG + * @{ + */ + +#ifndef _WDG_H_ +#define _WDG_H_ + +#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + WDG_UNINIT = 0, /**< Not initialized. */ + WDG_STOP = 1, /**< Stopped. */ + WDG_READY = 2 /**< Ready. */ +} wdgstate_t; + +#include "wdg_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Resets WDG's counter. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * + * @iclass + */ +#define wdgResetI(wdgp) wdg_lld_reset(wdgp) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void wdgInit(void); + void wdgStart(WDGDriver *wdgp, const WDGConfig * config); + void wdgStop(WDGDriver *wdgp); + void wdgReset(WDGDriver *wdgp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_WDG == TRUE */ + +#endif /* _WDG_H_ */ + +/** @} */ diff --git a/os/hal/include/i2c.h b/os/hal/include/i2c.h deleted file mode 100644 index fb8cabad7..000000000 --- a/os/hal/include/i2c.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file i2c.h - * @brief I2C Driver macros and structures. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_H_ -#define _I2C_H_ - -#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/* TODO: To be reviewed, too STM32-centric.*/ -/** - * @name I2C bus error conditions - * @{ - */ -#define I2C_NO_ERROR 0x00 /**< @brief No error. */ -#define I2C_BUS_ERROR 0x01 /**< @brief Bus Error. */ -#define I2C_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */ -#define I2C_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */ -#define I2C_OVERRUN 0x08 /**< @brief Overrun/Underrun. */ -#define I2C_PEC_ERROR 0x10 /**< @brief PEC Error in - reception. */ -#define I2C_TIMEOUT 0x20 /**< @brief Hardware timeout. */ -#define I2C_SMB_ALERT 0x40 /**< @brief SMBus Alert. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION TRUE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - I2C_UNINIT = 0, /**< Not initialized. */ - I2C_STOP = 1, /**< Stopped. */ - I2C_READY = 2, /**< Ready. */ - I2C_ACTIVE_TX = 3, /**< Transmitting. */ - I2C_ACTIVE_RX = 4, /**< Receiving. */ - I2C_LOCKED = 5 /**> Bus or driver locked. */ -} i2cstate_t; - -#include "i2c_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Wakes up the waiting thread notifying no errors. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_wakeup_isr(i2cp) do { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(i2cp)->thread, MSG_OK); \ - osalSysUnlockFromISR(); \ -} while(0) - -/** - * @brief Wakes up the waiting thread notifying errors. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_wakeup_error_isr(i2cp) do { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(i2cp)->thread, MSG_RESET); \ - osalSysUnlockFromISR(); \ -} while(0) - -/** - * @brief Wrap i2cMasterTransmitTimeout function with TIME_INFINITE timeout. - * @api - */ -#define i2cMasterTransmit(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes) \ - (i2cMasterTransmitTimeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, \ - TIME_INFINITE)) - -/** - * @brief Wrap i2cMasterReceiveTimeout function with TIME_INFINITE timeout. - * @api - */ -#define i2cMasterReceive(i2cp, addr, rxbuf, rxbytes) \ - (i2cMasterReceiveTimeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void i2cInit(void); - void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, const I2CConfig *config); - void i2cStop(I2CDriver *i2cp); - i2cflags_t i2cGetErrors(I2CDriver *i2cp); - msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, - i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, - i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); -#if I2C_USE_MUTUAL_EXCLUSION == TRUE - void i2cAcquireBus(I2CDriver *i2cp); - void i2cReleaseBus(I2CDriver *i2cp); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C == TRUE */ - -#endif /* _I2C_H_ */ - -/** @} */ diff --git a/os/hal/include/i2s.h b/os/hal/include/i2s.h deleted file mode 100644 index a759b8455..000000000 --- a/os/hal/include/i2s.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file i2s.h - * @brief I2S Driver macros and structures. - * - * @addtogroup I2S - * @{ - */ - -#ifndef _I2S_H_ -#define _I2S_H_ - -#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name I2S modes - * @{ - */ -#define I2S_MODE_SLAVE 0 -#define I2S_MODE_MASTER 1 -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - I2S_UNINIT = 0, /**< Not initialized. */ - I2S_STOP = 1, /**< Stopped. */ - I2S_READY = 2, /**< Ready. */ - I2S_ACTIVE = 3, /**< Active. */ - I2S_COMPLETE = 4 /**< Transmission complete. */ -} i2sstate_t; - -#include "i2s_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Starts a I2S data exchange. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @iclass - */ -#define i2sStartExchangeI(i2sp) { \ - i2s_lld_start_exchange(i2sp); \ - (i2sp)->state = I2S_ACTIVE; \ -} - -/** - * @brief Stops the ongoing data exchange. - * @details The ongoing data exchange, if any, is stopped, if the driver - * was not active the function does nothing. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @iclass - */ -#define i2sStopExchangeI(i2sp) { \ - i2s_lld_stop_exchange(i2sp); \ - (i2sp)->state = I2S_READY; \ -} - -/** - * @brief Common ISR code, half buffer event. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] i2sp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2s_isr_half_code(i2sp) { \ - if ((i2sp)->config->end_cb != NULL) { \ - (i2sp)->config->end_cb(i2sp, 0, (i2sp)->config->size / 2); \ - } \ -} - -/** - * @brief Common ISR code. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] i2sp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2s_isr_full_code(i2sp) { \ - if ((i2sp)->config->end_cb) { \ - (i2sp)->state = I2S_COMPLETE; \ - (i2sp)->config->end_cb(i2sp, \ - (i2sp)->config->size / 2, \ - (i2sp)->config->size / 2); \ - if ((i2sp)->state == I2S_COMPLETE) \ - (i2sp)->state = I2S_READY; \ - } \ - else \ - (i2sp)->state = I2S_READY; \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void i2sInit(void); - void i2sObjectInit(I2SDriver *i2sp); - void i2sStart(I2SDriver *i2sp, const I2SConfig *config); - void i2sStop(I2SDriver *i2sp); - void i2sStartExchange(I2SDriver *i2sp); - void i2sStopExchange(I2SDriver *i2sp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2S == TRUE */ - -#endif /* _I2S_H_ */ - -/** @} */ diff --git a/os/hal/include/icu.h b/os/hal/include/icu.h deleted file mode 100644 index 262b646fd..000000000 --- a/os/hal/include/icu.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file icu.h - * @brief ICU Driver macros and structures. - * - * @addtogroup ICU - * @{ - */ - -#ifndef _ICU_H_ -#define _ICU_H_ - -#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - ICU_UNINIT = 0, /**< Not initialized. */ - ICU_STOP = 1, /**< Stopped. */ - ICU_READY = 2, /**< Ready. */ - ICU_WAITING = 3, /**< Waiting for first front. */ - ICU_ACTIVE = 4 /**< First front detected. */ -} icustate_t; - -/** - * @brief Type of a structure representing an ICU driver. - */ -typedef struct ICUDriver ICUDriver; - -/** - * @brief ICU notification callback type. - * - * @param[in] icup pointer to a @p ICUDriver object - */ -typedef void (*icucallback_t)(ICUDriver *icup); - -#include "icu_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Starts the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @iclass - */ -#define icuStartCaptureI(icup) do { \ - icu_lld_start_capture(icup); \ - (icup)->state = ICU_WAITING; \ -} while (false) - -/** - * @brief Stops the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @iclass - */ -#define icuStopCaptureI(icup) do { \ - icu_lld_stop_capture(icup); \ - (icup)->state = ICU_READY; \ -} while (false) - -/** - * @brief Enables notifications. - * @pre The ICU unit must have been activated using @p icuStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @iclass - */ -#define icuEnableNotificationsI(icup) icu_lld_enable_notifications(icup) - -/** - * @brief Disables notifications. - * @pre The ICU unit must have been activated using @p icuStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @iclass - */ -#define icuDisableNotificationsI(icup) icu_lld_disable_notifications(icup) - -/** - * @brief Check on notifications status. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The notifications status. - * @retval false if notifications are not enabled. - * @retval true if notifications are enabled. - * - * @notapi - */ -#define icuAreNotificationsEnabledX(icup) \ - icu_lld_are_notifications_enabled(icup) - -/** - * @brief Returns the width of the latest pulse. - * @details The pulse width is defined as number of ticks between the start - * edge and the stop edge. - * @note This function is meant to be invoked from the width capture - * callback. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @xclass - */ -#define icuGetWidthX(icup) icu_lld_get_width(icup) - -/** - * @brief Returns the width of the latest cycle. - * @details The cycle width is defined as number of ticks between a start - * edge and the next start edge. - * @note This function is meant to be invoked from the width capture - * callback. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The number of ticks. - * - * @xclass - */ -#define icuGetPeriodX(icup) icu_lld_get_period(icup) -/** @} */ - -/** - * @name Low level driver helper macros - * @{ - */ -/** - * @brief Common ISR code, ICU width event. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -#define _icu_isr_invoke_width_cb(icup) do { \ - if (((icup)->state == ICU_ACTIVE) && \ - ((icup)->config->width_cb != NULL)) \ - (icup)->config->width_cb(icup); \ -} while (0) - -/** - * @brief Common ISR code, ICU period event. - * @note A period event brings the driver into the @p ICU_ACTIVE state. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -#define _icu_isr_invoke_period_cb(icup) do { \ - if (((icup)->state == ICU_ACTIVE) && \ - ((icup)->config->period_cb != NULL)) \ - (icup)->config->period_cb(icup); \ - (icup)->state = ICU_ACTIVE; \ -} while (0) - -/** - * @brief Common ISR code, ICU timer overflow event. - * @note An overflow always brings the driver back to the @p ICU_WAITING - * state. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @notapi - */ -#define _icu_isr_invoke_overflow_cb(icup) do { \ - (icup)->config->overflow_cb(icup); \ - (icup)->state = ICU_WAITING; \ -} while (0) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void icuInit(void); - void icuObjectInit(ICUDriver *icup); - void icuStart(ICUDriver *icup, const ICUConfig *config); - void icuStop(ICUDriver *icup); - void icuStartCapture(ICUDriver *icup); - bool icuWaitCapture(ICUDriver *icup); - void icuStopCapture(ICUDriver *icup); - void icuEnableNotifications(ICUDriver *icup); - void icuDisableNotifications(ICUDriver *icup); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_ICU == TRUE */ - -#endif /* _ICU_H_ */ - -/** @} */ diff --git a/os/hal/include/mac.h b/os/hal/include/mac.h deleted file mode 100644 index 44bfcafab..000000000 --- a/os/hal/include/mac.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file mac.h - * @brief MAC Driver macros and structures. - * @addtogroup MAC - * @{ - */ - -#ifndef _MAC_H_ -#define _MAC_H_ - -#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name MAC configuration options - * @{ - */ -/** - * @brief Enables an event sources for incoming packets. - */ -#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) -#define MAC_USE_ZERO_COPY FALSE -#endif - -/** - * @brief Enables an event sources for incoming packets. - */ -#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) -#define MAC_USE_EVENTS TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - MAC_UNINIT = 0, /**< Not initialized. */ - MAC_STOP = 1, /**< Stopped. */ - MAC_ACTIVE = 2 /**< Active. */ -} macstate_t; - -/** - * @brief Type of a structure representing a MAC driver. - */ -typedef struct MACDriver MACDriver; - -#include "mac_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Returns the received frames event source. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The pointer to the @p EventSource structure. - * - * @api - */ -#if (MAC_USE_EVENTS == TRUE) || defined(__DOXYGEN__) -#define macGetReceiveEventSource(macp) (&(macp)->rdevent) -#endif - -/** - * @brief Writes to a transmit descriptor's stream. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] buf pointer to the buffer containing the data to be written - * @param[in] size number of bytes to be written - * @return The number of bytes written into the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if the maximum frame - * size is reached. - * - * @api - */ -#define macWriteTransmitDescriptor(tdp, buf, size) \ - mac_lld_write_transmit_descriptor(tdp, buf, size) - -/** - * @brief Reads from a receive descriptor's stream. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] buf pointer to the buffer that will receive the read data - * @param[in] size number of bytes to be read - * @return The number of bytes read from the descriptor's stream, - * this value can be less than the amount specified in the - * parameter @p size if there are no more bytes to read. - * - * @api - */ -#define macReadReceiveDescriptor(rdp, buf, size) \ - mac_lld_read_receive_descriptor(rdp, buf, size) - -#if (MAC_USE_ZERO_COPY == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns a pointer to the next transmit buffer in the descriptor - * chain. - * @note The API guarantees that enough buffers can be requested to fill - * a whole frame. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] size size of the requested buffer. Specify the frame size - * on the first call then scale the value down subtracting - * the amount of data already copied into the previous - * buffers. - * @param[out] sizep pointer to variable receiving the real buffer size. - * The returned value can be less than the amount - * requested, this means that more buffers must be - * requested in order to fill the frame data entirely. - * @return Pointer to the returned buffer. - * - * @api - */ -#define macGetNextTransmitBuffer(tdp, size, sizep) \ - mac_lld_get_next_transmit_buffer(tdp, size, sizep) - -/** - * @brief Returns a pointer to the next receive buffer in the descriptor - * chain. - * @note The API guarantees that the descriptor chain contains a whole - * frame. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[out] sizep pointer to variable receiving the buffer size, it is - * zero when the last buffer has already been returned. - * @return Pointer to the returned buffer. - * @retval NULL if the buffer chain has been entirely scanned. - * - * @api - */ -#define macGetNextReceiveBuffer(rdp, sizep) \ - mac_lld_get_next_receive_buffer(rdp, sizep) -#endif /* MAC_USE_ZERO_COPY */ -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void macInit(void); - void macObjectInit(MACDriver *macp); - void macStart(MACDriver *macp, const MACConfig *config); - void macStop(MACDriver *macp); - void macSetAddress(MACDriver *macp, const uint8_t *p); - msg_t macWaitTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp, - systime_t timeout); - void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp); - msg_t macWaitReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp, - systime_t timeout); - void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp); - bool macPollLinkStatus(MACDriver *macp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_MAC == TRUE */ - -#endif /* _MAC_H_ */ - -/** @} */ diff --git a/os/hal/include/mmc_spi.h b/os/hal/include/mmc_spi.h deleted file mode 100644 index 7c9a60cae..000000000 --- a/os/hal/include/mmc_spi.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file mmc_spi.h - * @brief MMC over SPI driver header. - * - * @addtogroup MMC_SPI - * @{ - */ - -#ifndef _MMC_SPI_H_ -#define _MMC_SPI_H_ - -#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define MMC_CMD0_RETRY 10U -#define MMC_CMD1_RETRY 100U -#define MMC_ACMD41_RETRY 100U -#define MMC_WAIT_DATA 10000U - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name MMC_SPI configuration options - * @{ - */ -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - * This option is recommended also if the SPI driver does not - * use a DMA channel and heavily loads the CPU. - */ -#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) -#define MMC_NICE_WAITING TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if (HAL_USE_SPI == FALSE) || (SPI_USE_WAIT == FALSE) -#error "MMC_SPI driver requires HAL_USE_SPI and SPI_USE_WAIT" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief MMC/SD over SPI driver configuration structure. - */ -typedef struct { - /** - * @brief SPI driver associated to this MMC driver. - */ - SPIDriver *spip; - /** - * @brief SPI low speed configuration used during initialization. - */ - const SPIConfig *lscfg; - /** - * @brief SPI high speed configuration used during transfers. - */ - const SPIConfig *hscfg; -} MMCConfig; - -/** - * @brief @p MMCDriver specific methods. - */ -#define _mmc_driver_methods \ - _mmcsd_block_device_methods - -/** - * @extends MMCSDBlockDeviceVMT - * - * @brief @p MMCDriver virtual methods table. - */ -struct MMCDriverVMT { - _mmc_driver_methods -}; - -/** - * @extends MMCSDBlockDevice - * - * @brief Structure representing a MMC/SD over SPI driver. - */ -typedef struct { - /** - * @brief Virtual Methods Table. - */ - const struct MMCDriverVMT *vmt; - _mmcsd_block_device_data - /** - * @brief Current configuration data. - */ - const MMCConfig *config; - /*** - * @brief Addresses use blocks instead of bytes. - */ - bool block_addresses; -} MMCDriver; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Returns the card insertion status. - * @note This macro wraps a low level function named - * @p sdc_lld_is_card_inserted(), this function must be - * provided by the application because it is not part of the - * SDC driver. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @return The card state. - * @retval FALSE card not inserted. - * @retval TRUE card inserted. - * - * @api - */ -#define mmcIsCardInserted(mmcp) mmc_lld_is_card_inserted(mmcp) - -/** - * @brief Returns the write protect status. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @return The card state. - * @retval FALSE card not inserted. - * @retval TRUE card inserted. - * - * @api - */ -#define mmcIsWriteProtected(mmcp) mmc_lld_is_write_protected(mmcp) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void mmcInit(void); - void mmcObjectInit(MMCDriver *mmcp); - void mmcStart(MMCDriver *mmcp, const MMCConfig *config); - void mmcStop(MMCDriver *mmcp); - bool mmcConnect(MMCDriver *mmcp); - bool mmcDisconnect(MMCDriver *mmcp); - bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk); - bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer); - bool mmcStopSequentialRead(MMCDriver *mmcp); - bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk); - bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer); - bool mmcStopSequentialWrite(MMCDriver *mmcp); - bool mmcSync(MMCDriver *mmcp); - bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip); - bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk); - bool mmc_lld_is_card_inserted(MMCDriver *mmcp); - bool mmc_lld_is_write_protected(MMCDriver *mmcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_MMC_SPI == TRUE */ - -#endif /* _MMC_SPI_H_ */ - -/** @} */ diff --git a/os/hal/include/pal.h b/os/hal/include/pal.h deleted file mode 100644 index df22f3e94..000000000 --- a/os/hal/include/pal.h +++ /dev/null @@ -1,642 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file pal.h - * @brief I/O Ports Abstraction Layer macros, types and structures. - * - * @addtogroup PAL - * @{ - */ - -#ifndef _PAL_H_ -#define _PAL_H_ - -#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Pads mode constants - * @{ - */ -/** - * @brief After reset state. - * @details The state itself is not specified and is architecture dependent, - * it is guaranteed to be equal to the after-reset state. It is - * usually an input state. - */ -#define PAL_MODE_RESET 0U - -/** - * @brief Safe state for unconnected pads. - * @details The state itself is not specified and is architecture dependent, - * it may be mapped on @p PAL_MODE_INPUT_PULLUP, - * @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL for - * example. - */ -#define PAL_MODE_UNCONNECTED 1U - -/** - * @brief Regular input high-Z pad. - */ -#define PAL_MODE_INPUT 2U - -/** - * @brief Input pad with weak pull up resistor. - */ -#define PAL_MODE_INPUT_PULLUP 3U - -/** - * @brief Input pad with weak pull down resistor. - */ -#define PAL_MODE_INPUT_PULLDOWN 4U - -/** - * @brief Analog input mode. - */ -#define PAL_MODE_INPUT_ANALOG 5U - -/** - * @brief Push-pull output pad. - */ -#define PAL_MODE_OUTPUT_PUSHPULL 6U - -/** - * @brief Open-drain output pad. - */ -#define PAL_MODE_OUTPUT_OPENDRAIN 7U -/** @} */ - -/** - * @name Logic level constants - * @{ - */ -/** - * @brief Logical low state. - */ -#define PAL_LOW 0U - -/** - * @brief Logical high state. - */ -#define PAL_HIGH 1U -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -#include "pal_lld.h" - -/** - * @brief I/O bus descriptor. - * @details This structure describes a group of contiguous digital I/O lines - * that have to be handled as bus. - * @note I/O operations on a bus do not affect I/O lines on the same port but - * not belonging to the bus. - */ -typedef struct { - /** - * @brief Port identifier. - */ - ioportid_t portid; - /** - * @brief Bus mask aligned to port bit 0. - * @note The bus mask implicitly define the bus width. A logic AND is - * performed on the bus data. - */ - ioportmask_t mask; - /** - * @brief Offset, within the port, of the least significant bit of the bus. - */ - uint_fast8_t offset; -} IOBus; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Port bit helper macro. - * @details This macro calculates the mask of a bit within a port. - * - * @param[in] n bit position within the port - * @return The bit mask. - */ -#if !defined(PAL_PORT_BIT) || defined(__DOXYGEN__) -#define PAL_PORT_BIT(n) ((ioportmask_t)(1U << (n))) -#endif - -/** - * @brief Bits group mask helper. - * @details This macro calculates the mask of a bits group. - * - * @param[in] width group width - * @return The group mask. - */ -#if !defined(PAL_GROUP_MASK) || defined(__DOXYGEN__) -#define PAL_GROUP_MASK(width) ((ioportmask_t)(1U << (width)) - 1U) -#endif - -/** - * @brief Data part of a static I/O bus initializer. - * @details This macro should be used when statically initializing an I/O bus - * that is part of a bigger structure. - * - * @param[in] name name of the IOBus variable - * @param[in] port I/O port descriptor - * @param[in] width bus width in bits - * @param[in] offset bus bit offset within the port - */ -#define _IOBUS_DATA(name, port, width, offset) \ - {port, PAL_GROUP_MASK(width), offset} - -/** - * @brief Static I/O bus initializer. - * - * @param[in] name name of the IOBus variable - * @param[in] port I/O port descriptor - * @param[in] width bus width in bits - * @param[in] offset bus bit offset within the port - */ -#define IOBUS_DECL(name, port, width, offset) \ - IOBus name = _IOBUS_DATA(name, port, width, offset) - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief PAL subsystem initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @param[in] config pointer to an architecture specific configuration - * structure. This structure is defined in the low level driver - * header. - * - * @init - */ -#define palInit(config) pal_lld_init(config) - -/** - * @brief Reads the physical I/O port states. - * @note The default implementation always return zero and computes the - * parameter eventual side effects. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @return The port logic states. - * - * @special - */ -#if !defined(pal_lld_readport) || defined(__DOXYGEN__) -#define palReadPort(port) ((void)(port), 0U) -#else -#define palReadPort(port) pal_lld_readport(port) -#endif - -/** - * @brief Reads the output latch. - * @details The purpose of this function is to read back the latched output - * value. - * @note The default implementation always return zero and computes the - * parameter eventual side effects. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @return The latched logic states. - * - * @special - */ -#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__) -#define palReadLatch(port) ((void)(port), 0U) -#else -#define palReadLatch(port) pal_lld_readlatch(port) -#endif - -/** - * @brief Writes a bits mask on a I/O port. - * @note The default implementation does nothing except computing the - * parameters eventual side effects. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] bits bits to be written on the specified port - * - * @special - */ -#if !defined(pal_lld_writeport) || defined(__DOXYGEN__) -#define palWritePort(port, bits) ((void)(port), (void)(bits)) -#else -#define palWritePort(port, bits) pal_lld_writeport(port, bits) -#endif - -/** - * @brief Sets a bits mask on a I/O port. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] bits bits to be ORed on the specified port - * - * @special - */ -#if !defined(pal_lld_setport) || defined(__DOXYGEN__) -#define palSetPort(port, bits) \ - palWritePort(port, palReadLatch(port) | (bits)) -#else -#define palSetPort(port, bits) pal_lld_setport(port, bits) -#endif - -/** - * @brief Clears a bits mask on a I/O port. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] bits bits to be cleared on the specified port - * - * @special - */ -#if !defined(pal_lld_clearport) || defined(__DOXYGEN__) -#define palClearPort(port, bits) \ - palWritePort(port, palReadLatch(port) & ~(bits)) -#else -#define palClearPort(port, bits) pal_lld_clearport(port, bits) -#endif - -/** - * @brief Toggles a bits mask on a I/O port. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] bits bits to be XORed on the specified port - * - * @special - */ -#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__) -#define palTogglePort(port, bits) \ - palWritePort(port, palReadLatch(port) ^ (bits)) -#else -#define palTogglePort(port, bits) pal_lld_toggleport(port, bits) -#endif - -/** - * @brief Reads a group of bits. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] mask group mask, a logic AND is performed on the input - * data - * @param[in] offset group bit offset within the port - * @return The group logic states. - * - * @special - */ -#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__) -#define palReadGroup(port, mask, offset) \ - ((palReadPort(port) >> (offset)) & (mask)) -#else -#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset) -#endif - -/** - * @brief Writes a group of bits. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] mask group mask, a logic AND is performed on the - * output data - * @param[in] offset group bit offset within the port - * @param[in] bits bits to be written. Values exceeding the group - * width are masked. - * - * @special - */ -#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__) -#define palWriteGroup(port, mask, offset, bits) \ - palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \ - (((bits) & (mask)) << (offset))) -#else -#define palWriteGroup(port, mask, offset, bits) \ - pal_lld_writegroup(port, mask, offset, bits) -#endif - - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * @note Programming an unknown or unsupported mode is silently ignored. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] mask group mask - * @param[in] offset group bit offset within the port - * @param[in] mode group mode - * - * @special - */ -#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__) -#define palSetGroupMode(port, mask, offset, mode) -#else -#define palSetGroupMode(port, mask, offset, mode) \ - pal_lld_setgroupmode(port, mask, offset, mode) -#endif - -/** - * @brief Reads an input pad logic state. - * @note The default implementation not necessarily optimal. Low level - * drivers may optimize the function by using specific hardware - * or coding. - * @note The default implementation internally uses the @p palReadPort(). - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @return The logic state. - * @retval PAL_LOW low logic state. - * @retval PAL_HIGH high logic state. - * - * @special - */ -#if !defined(pal_lld_readpad) || defined(__DOXYGEN__) -#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U) -#else -#define palReadPad(port, pad) pal_lld_readpad(port, pad) -#endif - -/** - * @brief Writes a logic state on an output pad. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p palReadLatch() - * and @p palWritePort(). - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] bit logic value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @special - */ -#if !defined(pal_lld_writepad) || defined(__DOXYGEN__) -#define palWritePad(port, pad, bit) \ - palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \ - (((bit) & 1U) << pad)) -#else -#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit) -#endif - -/** - * @brief Sets a pad logic state to @p PAL_HIGH. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p palSetPort(). - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @special - */ -#if !defined(pal_lld_setpad) || defined(__DOXYGEN__) -#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad)) -#else -#define palSetPad(port, pad) pal_lld_setpad(port, pad) -#endif - -/** - * @brief Clears a pad logic state to @p PAL_LOW. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p palClearPort(). - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @special - */ -#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__) -#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad)) -#else -#define palClearPad(port, pad) pal_lld_clearpad(port, pad) -#endif - -/** - * @brief Toggles a pad logic state. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p palTogglePort(). - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * - * @special - */ -#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__) -#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad)) -#else -#define palTogglePad(port, pad) pal_lld_togglepad(port, pad) -#endif - -/** - * @brief Pad mode setup. - * @details This function programs a pad with the specified mode. - * @note The default implementation not necessarily optimal. Low level - * drivers may optimize the function by using specific hardware - * or coding. - * @note Programming an unknown or unsupported mode is silently ignored. - * @note The function can be called from any context. - * - * @param[in] port port identifier - * @param[in] pad pad number within the port - * @param[in] mode pad mode - * - * @special - */ -#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__) -#define palSetPadMode(port, pad, mode) \ - palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode) -#else -#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode) -#endif - -/** - * @brief Reads an input line logic state. - * @note The function can be called from any context. - * - * @param[in] line line identifier - * @return The logic state. - * @retval PAL_LOW low logic state. - * @retval PAL_HIGH high logic state. - * - * @special - */ -#if !defined(pal_lld_readline) || defined(__DOXYGEN__) -#define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) -#else -#define palReadLine(line) pal_lld_readline(line) -#endif - -/** - * @brief Writes a logic state on an output line. - * @note The function can be called from any context. - * - * @param[in] line line identifier - * @param[in] bit logic value, the value must be @p PAL_LOW or - * @p PAL_HIGH - * - * @special - */ -#if !defined(pal_lld_writeline) || defined(__DOXYGEN__) -#define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit) -#else -#define palWriteLine(line, bit) pal_lld_writeline(line, bit) -#endif - -/** - * @brief Sets a line logic state to @p PAL_HIGH. - * @note The function can be called from any context. - * - * @param[in] line line identifier - * - * @special - */ -#if !defined(pal_lld_setline) || defined(__DOXYGEN__) -#define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) -#else -#define palSetLine(line) pal_lld_setline(line) -#endif - -/** - * @brief Clears a line logic state to @p PAL_LOW. - * @note The function can be called from any context. - * - * @param[in] line line identifier - * - * @special - */ -#if !defined(pal_lld_clearline) || defined(__DOXYGEN__) -#define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) -#else -#define palClearLine(line) pal_lld_clearline(line) -#endif - -/** - * @brief Toggles a line logic state. - * @note The function can be called from any context. - * - * @param[in] line line identifier - * - * @special - */ -#if !defined(pal_lld_toggleline) || defined(__DOXYGEN__) -#define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line)) -#else -#define palToggleLine(line) pal_lld_toggleline(line) -#endif - -/** - * @brief Line mode setup. - * @note The function can be called from any context. - * - * @param[in] line line identifier - * @param[in] mode pad mode - * - * @special - */ -#if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__) -#define palSetLineMode(line, mode) \ - palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode) -#else -#define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode) -#endif -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - ioportmask_t palReadBus(IOBus *bus); - void palWriteBus(IOBus *bus, ioportmask_t bits); - void palSetBusMode(IOBus *bus, iomode_t mode); -#ifdef __cplusplus -} -#endif - -#endif /* _PAL_H_ */ - -#endif /* HAL_USE_PAL == TRUE */ - -/** @} */ diff --git a/os/hal/include/pwm.h b/os/hal/include/pwm.h deleted file mode 100644 index 5704b40bc..000000000 --- a/os/hal/include/pwm.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file pwm.h - * @brief PWM Driver macros and structures. - * - * @addtogroup PWM - * @{ - */ - -#ifndef _PWM_H_ -#define _PWM_H_ - -#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name PWM output mode macros - * @{ - */ -/** - * @brief Standard output modes mask. - */ -#define PWM_OUTPUT_MASK 0x0FU - -/** - * @brief Output not driven, callback only. - */ -#define PWM_OUTPUT_DISABLED 0x00U - -/** - * @brief Positive PWM logic, active is logic level one. - */ -#define PWM_OUTPUT_ACTIVE_HIGH 0x01U - -/** - * @brief Inverse PWM logic, active is logic level zero. - */ -#define PWM_OUTPUT_ACTIVE_LOW 0x02U -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - PWM_UNINIT = 0, /**< Not initialized. */ - PWM_STOP = 1, /**< Stopped. */ - PWM_READY = 2 /**< Ready. */ -} pwmstate_t; - -/** - * @brief Type of a structure representing a PWM driver. - */ -typedef struct PWMDriver PWMDriver; - -/** - * @brief Type of a PWM notification callback. - * - * @param[in] pwmp pointer to a @p PWMDriver object - */ -typedef void (*pwmcallback_t)(PWMDriver *pwmp); - -#include "pwm_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name PWM duty cycle conversion - * @{ - */ -/** - * @brief Converts from fraction to pulse width. - * @note Be careful with rounding errors, this is integer math not magic. - * You can specify tenths of thousandth but make sure you have the - * proper hardware resolution by carefully choosing the clock source - * and prescaler settings, see @p PWM_COMPUTE_PSC. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] denominator denominator of the fraction - * @param[in] numerator numerator of the fraction - * @return The pulse width to be passed to @p pwmEnableChannel(). - * - * @api - */ -#define PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator) \ - ((pwmcnt_t)((((pwmcnt_t)(pwmp)->period) * \ - (pwmcnt_t)(numerator)) / (pwmcnt_t)(denominator))) - -/** - * @brief Converts from degrees to pulse width. - * @note Be careful with rounding errors, this is integer math not magic. - * You can specify hundredths of degrees but make sure you have the - * proper hardware resolution by carefully choosing the clock source - * and prescaler settings, see @p PWM_COMPUTE_PSC. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] degrees degrees as an integer between 0 and 36000 - * @return The pulse width to be passed to @p pwmEnableChannel(). - * - * @api - */ -#define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \ - PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees) - -/** - * @brief Converts from percentage to pulse width. - * @note Be careful with rounding errors, this is integer math not magic. - * You can specify tenths of thousandth but make sure you have the - * proper hardware resolution by carefully choosing the clock source - * and prescaler settings, see @p PWM_COMPUTE_PSC. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] percentage percentage as an integer between 0 and 10000 - * @return The pulse width to be passed to @p pwmEnableChannel(). - * - * @api - */ -#define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \ - PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage) -/** @} */ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Changes the period the PWM peripheral. - * @details This function changes the period of a PWM unit that has already - * been activated using @p pwmStart(). - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The PWM unit period is changed to the new value. - * @note If a period is specified that is shorter than the pulse width - * programmed in one of the channels then the behavior is not - * guaranteed. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] value new cycle time in ticks - * - * @iclass - */ -#define pwmChangePeriodI(pwmp, value) { \ - (pwmp)->period = (value); \ - pwm_lld_change_period(pwmp, value); \ -} - -/** - * @brief Enables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is active using the specified configuration. - * @note Depending on the hardware implementation this function has - * effect starting on the next cycle (recommended implementation) - * or immediately (fallback implementation). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * @param[in] width PWM pulse width as clock pulses number - * - * @iclass - */ -#define pwmEnableChannelI(pwmp, channel, width) do { \ - (pwmp)->enabled |= ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \ - pwm_lld_enable_channel(pwmp, channel, width); \ -} while (false) - -/** - * @brief Disables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is disabled and its output line returned to the - * idle state. - * @note Depending on the hardware implementation this function has - * effect starting on the next cycle (recommended implementation) - * or immediately (fallback implementation). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @iclass - */ -#define pwmDisableChannelI(pwmp, channel) do { \ - (pwmp)->enabled &= ~((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \ - pwm_lld_disable_channel(pwmp, channel); \ -} while (false) - -/** - * @brief Returns a PWM channel status. - * @pre The PWM unit must have been activated using @p pwmStart(). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @iclass - */ -#define pwmIsChannelEnabledI(pwmp, channel) \ - (((pwmp)->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel))) != 0U) - -/** - * @brief Enables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @iclass - */ -#define pwmEnablePeriodicNotificationI(pwmp) \ - pwm_lld_enable_periodic_notification(pwmp) - -/** - * @brief Disables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @iclass - */ -#define pwmDisablePeriodicNotificationI(pwmp) \ - pwm_lld_disable_periodic_notification(pwmp) - -/** - * @brief Enables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @iclass - */ -#define pwmEnableChannelNotificationI(pwmp, channel) \ - pwm_lld_enable_channel_notification(pwmp, channel) - -/** - * @brief Disables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @iclass - */ -#define pwmDisableChannelNotificationI(pwmp, channel) \ - pwm_lld_disable_channel_notification(pwmp, channel) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void pwmInit(void); - void pwmObjectInit(PWMDriver *pwmp); - void pwmStart(PWMDriver *pwmp, const PWMConfig *config); - void pwmStop(PWMDriver *pwmp); - void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period); - void pwmEnableChannel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width); - void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel); - void pwmEnablePeriodicNotification(PWMDriver *pwmp); - void pwmDisablePeriodicNotification(PWMDriver *pwmp); - void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel); - void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_PWM == TRUE */ - -#endif /* _PWM_H_ */ - -/** @} */ diff --git a/os/hal/include/rtc.h b/os/hal/include/rtc.h deleted file mode 100644 index e4c32ba64..000000000 --- a/os/hal/include/rtc.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file rtc.h - * @brief RTC Driver macros and structures. - * - * @addtogroup RTC - * @{ - */ - -#ifndef _RTC_H_ -#define _RTC_H_ - -#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) - -/*lint -save -e829 [21.10] The header is required.*/ -#include -/*lint -restore*/ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Base year of the calendar. - */ -#define RTC_BASE_YEAR 1980U - -/** - * @name Date/Time bit masks for FAT format - * @{ - */ -#define RTC_FAT_TIME_SECONDS_MASK 0x0000001FU -#define RTC_FAT_TIME_MINUTES_MASK 0x000007E0U -#define RTC_FAT_TIME_HOURS_MASK 0x0000F800U -#define RTC_FAT_DATE_DAYS_MASK 0x001F0000U -#define RTC_FAT_DATE_MONTHS_MASK 0x01E00000U -#define RTC_FAT_DATE_YEARS_MASK 0xFE000000U -/** @} */ - -/** - * @name Day of week encoding - * @{ - */ -#define RTC_DAY_CATURDAY 0U -#define RTC_DAY_MONDAY 1U -#define RTC_DAY_TUESDAY 2U -#define RTC_DAY_WEDNESDAY 3U -#define RTC_DAY_THURSDAY 4U -#define RTC_DAY_FRIDAY 5U -#define RTC_DAY_SATURDAY 6U -#define RTC_DAY_SUNDAY 7U -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an RTC driver. - */ -typedef struct RTCDriver RTCDriver; - -/** - * @brief Type of a structure representing an RTC date/time stamp. - */ -typedef struct { - /*lint -save -e46 [6.1] In this case uint32_t is fine.*/ - uint32_t year: 8; /**< @brief Years since 1980. */ - uint32_t month: 4; /**< @brief Months 1..12. */ - uint32_t dstflag: 1; /**< @brief DST correction flag. */ - uint32_t dayofweek: 3; /**< @brief Day of week 1..7. */ - uint32_t day: 5; /**< @brief Day of the month 1..31. */ - uint32_t millisecond: 27; /**< @brief Milliseconds since midnight.*/ - /*lint -restore*/ -} RTCDateTime; - -#include "rtc_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void rtcInit(void); - void rtcObjectInit(RTCDriver *rtcp); - void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec); - void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec); -#if RTC_ALARMS > 0 - void rtcSetAlarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec); - void rtcGetAlarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec); -#endif -#if RTC_SUPPORTS_CALLBACKS == TRUE - void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback); -#endif - void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec, - struct tm *timp, - uint32_t *tv_msec); - void rtcConvertStructTmToDateTime(const struct tm *timp, - uint32_t tv_msec, - RTCDateTime *timespec); - uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_RTC == TRUE */ -#endif /* _RTC_H_ */ - -/** @} */ diff --git a/os/hal/include/sdc.h b/os/hal/include/sdc.h deleted file mode 100644 index 954688658..000000000 --- a/os/hal/include/sdc.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file sdc.h - * @brief SDC Driver macros and structures. - * - * @addtogroup SDC - * @{ - */ - -#ifndef _SDC_H_ -#define _SDC_H_ - -#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name SD card types - * @{ - */ -#define SDC_MODE_CARDTYPE_MASK 0xFU -#define SDC_MODE_CARDTYPE_SDV11 0U -#define SDC_MODE_CARDTYPE_SDV20 1U -#define SDC_MODE_CARDTYPE_MMC 2U -#define SDC_MODE_HIGH_CAPACITY 0x10U -/** @} */ - -/** - * @name SDC bus error conditions - * @{ - */ -#define SDC_NO_ERROR 0U -#define SDC_CMD_CRC_ERROR 1U -#define SDC_DATA_CRC_ERROR 2U -#define SDC_DATA_TIMEOUT 4U -#define SDC_COMMAND_TIMEOUT 8U -#define SDC_TX_UNDERRUN 16U -#define SDC_RX_OVERRUN 32U -#define SDC_STARTBIT_ERROR 64U -#define SDC_OVERFLOW_ERROR 128U -#define SDC_UNHANDLED_ERROR 0xFFFFFFFFU -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name SDC configuration options - * @{ - */ -/** - * @brief Number of initialization attempts before rejecting the card. - * @note Attempts are performed at 10mS intervals. - */ -#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) -#define SDC_INIT_RETRY 100 -#endif - -/** - * @brief Include support for MMC cards. - * @note MMC support is not yet implemented so this option must be kept - * at @p FALSE. - */ -#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) -#define SDC_MMC_SUPPORT FALSE -#endif - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - */ -#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) -#define SDC_NICE_WAITING TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of SDIO bus mode. - */ -typedef enum { - SDC_MODE_1BIT = 0, - SDC_MODE_4BIT, - SDC_MODE_8BIT -} sdcbusmode_t; - -/** - * @brief Max supported clock. - */ -typedef enum { - SDC_CLK_25MHz = 0, - SDC_CLK_50MHz -} sdcbusclk_t; - -#include "sdc_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Returns the card insertion status. - * @note This macro wraps a low level function named - * @p sdc_lld_is_card_inserted(), this function must be - * provided by the application because it is not part of the - * SDC driver. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @return The card state. - * @retval FALSE card not inserted. - * @retval TRUE card inserted. - * - * @api - */ -#define sdcIsCardInserted(sdcp) (sdc_lld_is_card_inserted(sdcp)) - -/** - * @brief Returns the write protect status. - * @note This macro wraps a low level function named - * @p sdc_lld_is_write_protected(), this function must be - * provided by the application because it is not part of the - * SDC driver. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @return The card state. - * @retval FALSE not write protected. - * @retval TRUE write protected. - * - * @api - */ -#define sdcIsWriteProtected(sdcp) (sdc_lld_is_write_protected(sdcp)) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void sdcInit(void); - void sdcObjectInit(SDCDriver *sdcp); - void sdcStart(SDCDriver *sdcp, const SDCConfig *config); - void sdcStop(SDCDriver *sdcp); - bool sdcConnect(SDCDriver *sdcp); - bool sdcDisconnect(SDCDriver *sdcp); - bool sdcRead(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n); - bool sdcWrite(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n); - sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp); - bool sdcSync(SDCDriver *sdcp); - bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip); - bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk); - bool _sdc_wait_for_transfer_state(SDCDriver *sdcp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SDC == TRUE */ - -#endif /* _SDC_H_ */ - -/** @} */ diff --git a/os/hal/include/serial.h b/os/hal/include/serial.h deleted file mode 100644 index 814d54569..000000000 --- a/os/hal/include/serial.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file serial.h - * @brief Serial Driver macros and structures. - * - * @addtogroup SERIAL - * @{ - */ - -#ifndef _SERIAL_H_ -#define _SERIAL_H_ - -#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name Serial status flags - * @{ - */ -#define SD_PARITY_ERROR (eventflags_t)32 /**< @brief Parity. */ -#define SD_FRAMING_ERROR (eventflags_t)64 /**< @brief Framing. */ -#define SD_OVERRUN_ERROR (eventflags_t)128 /**< @brief Overflow. */ -#define SD_NOISE_ERROR (eventflags_t)256 /**< @brief Line noise. */ -#define SD_BREAK_DETECTED (eventflags_t)512 /**< @brief LIN Break. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Serial configuration options - * @{ - */ -/** - * @brief Default bit rate. - * @details Configuration parameter, this is the baud rate selected for the - * default configuration. - */ -#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) -#define SERIAL_DEFAULT_BITRATE 38400 -#endif - -/** - * @brief Serial buffers size. - * @details Configuration parameter, you can change the depth of the queue - * buffers depending on the requirements of your application. - * @note The default is 16 bytes for both the transmission and receive - * buffers. - */ -#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_BUFFERS_SIZE 16 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - SD_UNINIT = 0, /**< Not initialized. */ - SD_STOP = 1, /**< Stopped. */ - SD_READY = 2 /**< Ready. */ -} sdstate_t; - -/** - * @brief Structure representing a serial driver. - */ -typedef struct SerialDriver SerialDriver; - -#include "serial_lld.h" - -/** - * @brief @p SerialDriver specific methods. - */ -#define _serial_driver_methods \ - _base_asynchronous_channel_methods - -/** - * @extends BaseAsynchronousChannelVMT - * - * @brief @p SerialDriver virtual methods table. - */ -struct SerialDriverVMT { - _serial_driver_methods -}; - -/** - * @extends BaseAsynchronousChannel - * - * @brief Full duplex serial driver class. - * @details This class extends @p BaseAsynchronousChannel by adding physical - * I/O queues. - */ -struct SerialDriver { - /** @brief Virtual Methods Table.*/ - const struct SerialDriverVMT *vmt; - _serial_driver_data -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Direct write to a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * writes directly on the output queue. This is faster but cannot - * be used to write to different channels implementations. - * - * @see chnPutTimeout() - * - * @api - */ -#define sdPut(sdp, b) oqPut(&(sdp)->oqueue, b) - -/** - * @brief Direct write to a @p SerialDriver with timeout specification. - * @note This function bypasses the indirect access to the channel and - * writes directly on the output queue. This is faster but cannot - * be used to write to different channels implementations. - * - * @see chnPutTimeout() - * - * @api - */ -#define sdPutTimeout(sdp, b, t) oqPutTimeout(&(sdp)->oqueue, b, t) - -/** - * @brief Direct read from a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * - * @see chnGetTimeout() - * - * @api - */ -#define sdGet(sdp) iqGet(&(sdp)->iqueue) - -/** - * @brief Direct read from a @p SerialDriver with timeout specification. - * @note This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * - * @see chnGetTimeout() - * - * @api - */ -#define sdGetTimeout(sdp, t) iqGetTimeout(&(sdp)->iqueue, t) - -/** - * @brief Direct blocking write to a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * writes directly to the output queue. This is faster but cannot - * be used to write from different channels implementations. - * - * @see chnWrite() - * - * @api - */ -#define sdWrite(sdp, b, n) \ - oqWriteTimeout(&(sdp)->oqueue, b, n, TIME_INFINITE) - -/** - * @brief Direct blocking write to a @p SerialDriver with timeout - * specification. - * @note This function bypasses the indirect access to the channel and - * writes directly to the output queue. This is faster but cannot - * be used to write to different channels implementations. - * - * @see chnWriteTimeout() - * - * @api - */ -#define sdWriteTimeout(sdp, b, n, t) \ - oqWriteTimeout(&(sdp)->oqueue, b, n, t) - -/** - * @brief Direct non-blocking write to a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * writes directly to the output queue. This is faster but cannot - * be used to write to different channels implementations. - * - * @see chnWriteTimeout() - * - * @api - */ -#define sdAsynchronousWrite(sdp, b, n) \ - oqWriteTimeout(&(sdp)->oqueue, b, n, TIME_IMMEDIATE) - -/** - * @brief Direct blocking read from a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * - * @see chnRead() - * - * @api - */ -#define sdRead(sdp, b, n) \ - iqReadTimeout(&(sdp)->iqueue, b, n, TIME_INFINITE) - -/** - * @brief Direct blocking read from a @p SerialDriver with timeout - * specification. - * @note This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * - * @see chnReadTimeout() - * - * @api - */ -#define sdReadTimeout(sdp, b, n, t) \ - iqReadTimeout(&(sdp)->iqueue, b, n, t) - -/** - * @brief Direct non-blocking read from a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * - * @see chnReadTimeout() - * - * @api - */ -#define sdAsynchronousRead(sdp, b, n) \ - iqReadTimeout(&(sdp)->iqueue, b, n, TIME_IMMEDIATE) -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void sdInit(void); - void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify); - void sdStart(SerialDriver *sdp, const SerialConfig *config); - void sdStop(SerialDriver *sdp); - void sdIncomingDataI(SerialDriver *sdp, uint8_t b); - msg_t sdRequestDataI(SerialDriver *sdp); - bool sdPutWouldBlock(SerialDriver *sdp); - bool sdGetWouldBlock(SerialDriver *sdp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SERIAL == TRUE */ - -#endif /* _SERIAL_H_ */ - -/** @} */ diff --git a/os/hal/include/serial_usb.h b/os/hal/include/serial_usb.h deleted file mode 100644 index d4a1a1b57..000000000 --- a/os/hal/include/serial_usb.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file serial_usb.h - * @brief Serial over USB Driver macros and structures. - * - * @addtogroup SERIAL_USB - * @{ - */ - -#ifndef _SERIAL_USB_H_ -#define _SERIAL_USB_H_ - -#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__) - -#include "usb_cdc.h" - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name SERIAL_USB configuration options - * @{ - */ -/** - * @brief Serial over USB buffers size. - * @details Configuration parameter, the buffer size must be a multiple of - * the USB data endpoint maximum packet size. - * @note The default is 256 bytes for both the transmission and receive - * buffers. - */ -#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_SIZE 256 -#endif - -/** - * @brief Serial over USB number of buffers. - * @note The default is 2 buffers. - */ -#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_NUMBER 2 -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if HAL_USE_USB == FALSE -#error "Serial over USB Driver requires HAL_USE_USB" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - SDU_UNINIT = 0, /**< Not initialized. */ - SDU_STOP = 1, /**< Stopped. */ - SDU_READY = 2 /**< Ready. */ -} sdustate_t; - -/** - * @brief Structure representing a serial over USB driver. - */ -typedef struct SerialUSBDriver SerialUSBDriver; - -/** - * @brief Serial over USB Driver configuration structure. - * @details An instance of this structure must be passed to @p sduStart() - * in order to configure and start the driver operations. - */ -typedef struct { - /** - * @brief USB driver to use. - */ - USBDriver *usbp; - /** - * @brief Bulk IN endpoint used for outgoing data transfer. - */ - usbep_t bulk_in; - /** - * @brief Bulk OUT endpoint used for incoming data transfer. - */ - usbep_t bulk_out; - /** - * @brief Interrupt IN endpoint used for notifications. - * @note If set to zero then the INT endpoint is assumed to be not - * present, USB descriptors must be changed accordingly. - */ - usbep_t int_in; -} SerialUSBConfig; - -/** - * @brief @p SerialDriver specific data. - */ -#define _serial_usb_driver_data \ - _base_asynchronous_channel_data \ - /* Driver state.*/ \ - sdustate_t state; \ - /* Input buffers queue.*/ \ - input_buffers_queue_t ibqueue; \ - /* Output queue.*/ \ - output_buffers_queue_t obqueue; \ - /* Input buffer.*/ \ - uint8_t ib[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \ - SERIAL_USB_BUFFERS_SIZE)]; \ - /* Output buffer.*/ \ - uint8_t ob[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \ - SERIAL_USB_BUFFERS_SIZE)]; \ - /* End of the mandatory fields.*/ \ - /* Current configuration data.*/ \ - const SerialUSBConfig *config; - -/** - * @brief @p SerialUSBDriver specific methods. - */ -#define _serial_usb_driver_methods \ - _base_asynchronous_channel_methods - -/** - * @extends BaseAsynchronousChannelVMT - * - * @brief @p SerialDriver virtual methods table. - */ -struct SerialUSBDriverVMT { - _serial_usb_driver_methods -}; - -/** - * @extends BaseAsynchronousChannel - * - * @brief Full duplex serial driver class. - * @details This class extends @p BaseAsynchronousChannel by adding physical - * I/O queues. - */ -struct SerialUSBDriver { - /** @brief Virtual Methods Table.*/ - const struct SerialUSBDriverVMT *vmt; - _serial_usb_driver_data -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void sduInit(void); - void sduObjectInit(SerialUSBDriver *sdup); - void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config); - void sduStop(SerialUSBDriver *sdup); - void sduDisconnectI(SerialUSBDriver *sdup); - void sduConfigureHookI(SerialUSBDriver *sdup); - bool sduRequestsHook(USBDriver *usbp); - void sduSOFHookI(SerialUSBDriver *sdup); - void sduDataTransmitted(USBDriver *usbp, usbep_t ep); - void sduDataReceived(USBDriver *usbp, usbep_t ep); - void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SERIAL_USB == TRUE */ - -#endif /* _SERIAL_USB_H_ */ - -/** @} */ diff --git a/os/hal/include/spi.h b/os/hal/include/spi.h deleted file mode 100644 index 45dd0880b..000000000 --- a/os/hal/include/spi.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file spi.h - * @brief SPI Driver macros and structures. - * - * @addtogroup SPI - * @{ - */ - -#ifndef _SPI_H_ -#define _SPI_H_ - -#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name SPI configuration options - * @{ - */ -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) -#define SPI_USE_WAIT TRUE -#endif - -/** - * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define SPI_USE_MUTUAL_EXCLUSION TRUE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - SPI_UNINIT = 0, /**< Not initialized. */ - SPI_STOP = 1, /**< Stopped. */ - SPI_READY = 2, /**< Ready. */ - SPI_ACTIVE = 3, /**< Exchanging data. */ - SPI_COMPLETE = 4 /**< Asynchronous operation complete. */ -} spistate_t; - -#include "spi_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @iclass - */ -#define spiSelectI(spip) { \ - spi_lld_select(spip); \ -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @iclass - */ -#define spiUnselectI(spip) { \ - spi_lld_unselect(spip); \ -} - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @iclass - */ -#define spiStartIgnoreI(spip, n) { \ - (spip)->state = SPI_ACTIVE; \ - spi_lld_ignore(spip, n); \ -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @iclass - */ -#define spiStartExchangeI(spip, n, txbuf, rxbuf) { \ - (spip)->state = SPI_ACTIVE; \ - spi_lld_exchange(spip, n, txbuf, rxbuf); \ -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @iclass - */ -#define spiStartSendI(spip, n, txbuf) { \ - (spip)->state = SPI_ACTIVE; \ - spi_lld_send(spip, n, txbuf); \ -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @iclass - */ -#define spiStartReceiveI(spip, n, rxbuf) { \ - (spip)->state = SPI_ACTIVE; \ - spi_lld_receive(spip, n, rxbuf); \ -} - -/** - * @brief Exchanges one frame using a polled wait. - * @details This synchronous function exchanges one frame using a polled - * synchronization method. This function is useful when exchanging - * small amount of data on high speed channels, usually in this - * situation is much more efficient just wait for completion using - * polling than suspending the thread waiting for an interrupt. - * @note This API is implemented as a macro in order to minimize latency. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] frame the data frame to send over the SPI bus - * @return The received data frame from the SPI bus. - */ -#define spiPolledExchange(spip, frame) spi_lld_polled_exchange(spip, frame) -/** @} */ - -/** - * @name Low level driver helper macros - * @{ - */ -#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Wakes up the waiting thread. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -#define _spi_wakeup_isr(spip) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(spip)->thread, MSG_OK); \ - osalSysUnlockFromISR(); \ -} -#else /* !SPI_USE_WAIT */ -#define _spi_wakeup_isr(spip) -#endif /* !SPI_USE_WAIT */ - -/** - * @brief Common ISR code. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @notapi - */ -#define _spi_isr_code(spip) { \ - if ((spip)->config->end_cb) { \ - (spip)->state = SPI_COMPLETE; \ - (spip)->config->end_cb(spip); \ - if ((spip)->state == SPI_COMPLETE) \ - (spip)->state = SPI_READY; \ - } \ - else \ - (spip)->state = SPI_READY; \ - _spi_wakeup_isr(spip); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void spiInit(void); - void spiObjectInit(SPIDriver *spip); - void spiStart(SPIDriver *spip, const SPIConfig *config); - void spiStop(SPIDriver *spip); - void spiSelect(SPIDriver *spip); - void spiUnselect(SPIDriver *spip); - void spiStartIgnore(SPIDriver *spip, size_t n); - void spiStartExchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf); - void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf); -#if SPI_USE_WAIT == TRUE - void spiIgnore(SPIDriver *spip, size_t n); - void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); - void spiSend(SPIDriver *spip, size_t n, const void *txbuf); - void spiReceive(SPIDriver *spip, size_t n, void *rxbuf); -#endif -#if SPI_USE_MUTUAL_EXCLUSION == TRUE - void spiAcquireBus(SPIDriver *spip); - void spiReleaseBus(SPIDriver *spip); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_SPI == TRUE */ - -#endif /* _SPI_H_ */ - -/** @} */ diff --git a/os/hal/include/st.h b/os/hal/include/st.h deleted file mode 100644 index 3bd50e854..000000000 --- a/os/hal/include/st.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file st.h - * @brief ST Driver macros and structures. - * @details This header is designed to be include-able without having to - * include other files from the HAL. - * - * @addtogroup ST - * @{ - */ - -#ifndef _ST_H_ -#define _ST_H_ - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -#include "st_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Returns the time counter value. - * @note This functionality is only available in free running mode, the - * behaviour in periodic mode is undefined. - * - * @return The counter value. - * - * @api - */ -#define stGetCounter() st_lld_get_counter() - -/** - * @brief Determines if the alarm is active. - * - * @return The alarm status. - * @retval false if the alarm is not active. - * @retval true is the alarm is active - * - * @api - */ -#define stIsAlarmActive() st_lld_is_alarm_active() -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void stInit(void); - void stStartAlarm(systime_t abstime); - void stStopAlarm(void); - void stSetAlarm(systime_t abstime); - systime_t stGetAlarm(void); -#ifdef __cplusplus -} -#endif - -#endif /* _ST_H_ */ - -/** @} */ diff --git a/os/hal/include/uart.h b/os/hal/include/uart.h deleted file mode 100644 index a0a8eecdf..000000000 --- a/os/hal/include/uart.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file uart.h - * @brief UART Driver macros and structures. - * - * @addtogroup UART - * @{ - */ - -#ifndef _UART_H_ -#define _UART_H_ - -#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name UART status flags - * @{ - */ -#define UART_NO_ERROR 0 /**< @brief No pending conditions. */ -#define UART_PARITY_ERROR 4 /**< @brief Parity error happened. */ -#define UART_FRAMING_ERROR 8 /**< @brief Framing error happened. */ -#define UART_OVERRUN_ERROR 16 /**< @brief Overflow happened. */ -#define UART_NOISE_ERROR 32 /**< @brief Noise on the line. */ -#define UART_BREAK_DETECTED 64 /**< @brief Break detected. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name UART configuration options - * @{ - */ -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) -#define UART_USE_WAIT FALSE -#endif - -/** - * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define UART_USE_MUTUAL_EXCLUSION FALSE -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - UART_UNINIT = 0, /**< Not initialized. */ - UART_STOP = 1, /**< Stopped. */ - UART_READY = 2 /**< Ready. */ -} uartstate_t; - -/** - * @brief Transmitter state machine states. - */ -typedef enum { - UART_TX_IDLE = 0, /**< Not transmitting. */ - UART_TX_ACTIVE = 1, /**< Transmitting. */ - UART_TX_COMPLETE = 2 /**< Buffer complete. */ -} uarttxstate_t; - -/** - * @brief Receiver state machine states. - */ -typedef enum { - UART_RX_IDLE = 0, /**< Not receiving. */ - UART_RX_ACTIVE = 1, /**< Receiving. */ - UART_RX_COMPLETE = 2 /**< Buffer complete. */ -} uartrxstate_t; - -#include "uart_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Low level driver helper macros - * @{ - */ -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Wakes up the waiting thread in case of early TX complete. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_wakeup_tx1_isr(uartp) { \ - if ((uartp)->early == true) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \ - osalSysUnlockFromISR(); \ - } \ -} -#else /* !UART_USE_WAIT */ -#define _uart_wakeup_tx1_isr(uartp) -#endif /* !UART_USE_WAIT */ - -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Wakes up the waiting thread in case of late TX complete. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_wakeup_tx2_isr(uartp) { \ - if ((uartp)->early == false) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \ - osalSysUnlockFromISR(); \ - } \ -} -#else /* !UART_USE_WAIT */ -#define _uart_wakeup_tx2_isr(uartp) -#endif /* !UART_USE_WAIT */ - -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Wakes up the waiting thread in case of RX complete. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_wakeup_rx_complete_isr(uartp) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(uartp)->threadrx, MSG_OK); \ - osalSysUnlockFromISR(); \ -} -#else /* !UART_USE_WAIT */ -#define _uart_wakeup_rx_complete_isr(uartp) -#endif /* !UART_USE_WAIT */ - -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Wakes up the waiting thread in case of RX error. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_wakeup_rx_error_isr(uartp) { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(uartp)->threadrx, MSG_RESET); \ - osalSysUnlockFromISR(); \ -} -#else /* !UART_USE_WAIT */ -#define _uart_wakeup_rx_error_isr(uartp) -#endif /* !UART_USE_WAIT */ - -/** - * @brief Common ISR code for early TX. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_tx1_isr_code(uartp) { \ - (uartp)->txstate = UART_TX_COMPLETE; \ - if ((uartp)->config->txend1_cb != NULL) { \ - (uartp)->config->txend1_cb(uartp); \ - } \ - if ((uartp)->txstate == UART_TX_COMPLETE) { \ - (uartp)->txstate = UART_TX_IDLE; \ - } \ - _uart_wakeup_tx1_isr(uartp); \ -} - -/** - * @brief Common ISR code for late TX. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_tx2_isr_code(uartp) { \ - if ((uartp)->config->txend2_cb != NULL) { \ - (uartp)->config->txend2_cb(uartp); \ - } \ - _uart_wakeup_tx2_isr(uartp); \ -} - -/** - * @brief Common ISR code for RX complete. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_rx_complete_isr_code(uartp) { \ - (uartp)->rxstate = UART_RX_COMPLETE; \ - if ((uartp)->config->rxend_cb != NULL) { \ - (uartp)->config->rxend_cb(uartp); \ - } \ - if ((uartp)->rxstate == UART_RX_COMPLETE) { \ - (uartp)->rxstate = UART_RX_IDLE; \ - uart_enter_rx_idle_loop(uartp); \ - } \ - _uart_wakeup_rx_complete_isr(uartp); \ -} - -/** - * @brief Common ISR code for RX error. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] errors mask of errors to be reported - * - * @notapi - */ -#define _uart_rx_error_isr_code(uartp, errors) { \ - if ((uartp)->config->rxerr_cb != NULL) { \ - (uartp)->config->rxerr_cb(uartp, errors); \ - } \ - _uart_wakeup_rx_error_isr(uartp); \ -} - - -/** - * @brief Common ISR code for RX on idle. - * @details This code handles the portable part of the ISR code: - * - Callback invocation. - * - Waiting thread wakeup, if any. - * - Driver state transitions. - * . - * @note This macro is meant to be used in the low level drivers - * implementation only. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @notapi - */ -#define _uart_rx_idle_code(uartp) { \ - if ((uartp)->config->rxchar_cb != NULL) \ - (uartp)->config->rxchar_cb(uartp, (uartp)->rxbuf); \ -} -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void uartInit(void); - void uartObjectInit(UARTDriver *uartp); - void uartStart(UARTDriver *uartp, const UARTConfig *config); - void uartStop(UARTDriver *uartp); - void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf); - void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf); - size_t uartStopSend(UARTDriver *uartp); - size_t uartStopSendI(UARTDriver *uartp); - void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf); - void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf); - size_t uartStopReceive(UARTDriver *uartp); - size_t uartStopReceiveI(UARTDriver *uartp); -#if UART_USE_WAIT == TRUE - msg_t uartSendTimeout(UARTDriver *uartp, size_t *np, - const void *txbuf, systime_t timeout); - msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np, - const void *txbuf, systime_t timeout); - msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np, - void *rxbuf, systime_t timeout); -#endif -#if UART_USE_MUTUAL_EXCLUSION == TRUE - void uartAcquireBus(UARTDriver *uartp); - void uartReleaseBus(UARTDriver *uartp); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_UART == TRUE */ - -#endif /* _UART_H_ */ - -/** @} */ diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h deleted file mode 100644 index 15d72cc43..000000000 --- a/os/hal/include/usb.h +++ /dev/null @@ -1,633 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file usb.h - * @brief USB Driver macros and structures. - * - * @addtogroup USB - * @{ - */ - -#ifndef _USB_H_ -#define _USB_H_ - -#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define USB_ENDPOINT_OUT(ep) (ep) -#define USB_ENDPOINT_IN(ep) ((ep) | 0x80U) - -#define USB_RTYPE_DIR_MASK 0x80U -#define USB_RTYPE_DIR_HOST2DEV 0x00U -#define USB_RTYPE_DIR_DEV2HOST 0x80U -#define USB_RTYPE_TYPE_MASK 0x60U -#define USB_RTYPE_TYPE_STD 0x00U -#define USB_RTYPE_TYPE_CLASS 0x20U -#define USB_RTYPE_TYPE_VENDOR 0x40U -#define USB_RTYPE_TYPE_RESERVED 0x60U -#define USB_RTYPE_RECIPIENT_MASK 0x1FU -#define USB_RTYPE_RECIPIENT_DEVICE 0x00U -#define USB_RTYPE_RECIPIENT_INTERFACE 0x01U -#define USB_RTYPE_RECIPIENT_ENDPOINT 0x02U -#define USB_RTYPE_RECIPIENT_OTHER 0x03U - -#define USB_REQ_GET_STATUS 0U -#define USB_REQ_CLEAR_FEATURE 1U -#define USB_REQ_SET_FEATURE 3U -#define USB_REQ_SET_ADDRESS 5U -#define USB_REQ_GET_DESCRIPTOR 6U -#define USB_REQ_SET_DESCRIPTOR 7U -#define USB_REQ_GET_CONFIGURATION 8U -#define USB_REQ_SET_CONFIGURATION 9U -#define USB_REQ_GET_INTERFACE 10U -#define USB_REQ_SET_INTERFACE 11U -#define USB_REQ_SYNCH_FRAME 12U - -#define USB_DESCRIPTOR_DEVICE 1U -#define USB_DESCRIPTOR_CONFIGURATION 2U -#define USB_DESCRIPTOR_STRING 3U -#define USB_DESCRIPTOR_INTERFACE 4U -#define USB_DESCRIPTOR_ENDPOINT 5U -#define USB_DESCRIPTOR_DEVICE_QUALIFIER 6U -#define USB_DESCRIPTOR_OTHER_SPEED_CFG 7U -#define USB_DESCRIPTOR_INTERFACE_POWER 8U -#define USB_DESCRIPTOR_INTERFACE_ASSOCIATION 11U - -#define USB_FEATURE_ENDPOINT_HALT 0U -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1U -#define USB_FEATURE_TEST_MODE 2U - -#define USB_EARLY_SET_ADDRESS 0 -#define USB_LATE_SET_ADDRESS 1 - -#define USB_EP0_STATUS_STAGE_SW 0 -#define USB_EP0_STATUS_STAGE_HW 1 - -#define USB_SET_ADDRESS_ACK_SW 0 -#define USB_SET_ADDRESS_ACK_HW 1 - -/** - * @name Helper macros for USB descriptors - * @{ - */ -/** - * @brief Helper macro for index values into descriptor strings. - */ -#define USB_DESC_INDEX(i) ((uint8_t)(i)) - -/** - * @brief Helper macro for byte values into descriptor strings. - */ -#define USB_DESC_BYTE(b) ((uint8_t)(b)) - -/** - * @brief Helper macro for word values into descriptor strings. - */ -#define USB_DESC_WORD(w) \ - (uint8_t)((w) & 255U), \ - (uint8_t)(((w) >> 8) & 255U) - -/** - * @brief Helper macro for BCD values into descriptor strings. - */ -#define USB_DESC_BCD(bcd) \ - (uint8_t)((bcd) & 255U), \ - (uint8_t)(((bcd) >> 8) & 255) - -/* - * @define Device Descriptor size. - */ -#define USB_DESC_DEVICE_SIZE 18U - -/** - * @brief Device Descriptor helper macro. - */ -#define USB_DESC_DEVICE(bcdUSB, bDeviceClass, bDeviceSubClass, \ - bDeviceProtocol, bMaxPacketSize, idVendor, \ - idProduct, bcdDevice, iManufacturer, \ - iProduct, iSerialNumber, bNumConfigurations) \ - USB_DESC_BYTE(USB_DESC_DEVICE_SIZE), \ - USB_DESC_BYTE(USB_DESCRIPTOR_DEVICE), \ - USB_DESC_BCD(bcdUSB), \ - USB_DESC_BYTE(bDeviceClass), \ - USB_DESC_BYTE(bDeviceSubClass), \ - USB_DESC_BYTE(bDeviceProtocol), \ - USB_DESC_BYTE(bMaxPacketSize), \ - USB_DESC_WORD(idVendor), \ - USB_DESC_WORD(idProduct), \ - USB_DESC_BCD(bcdDevice), \ - USB_DESC_INDEX(iManufacturer), \ - USB_DESC_INDEX(iProduct), \ - USB_DESC_INDEX(iSerialNumber), \ - USB_DESC_BYTE(bNumConfigurations) - -/** - * @brief Configuration Descriptor size. - */ -#define USB_DESC_CONFIGURATION_SIZE 9U - -/** - * @brief Configuration Descriptor helper macro. - */ -#define USB_DESC_CONFIGURATION(wTotalLength, bNumInterfaces, \ - bConfigurationValue, iConfiguration, \ - bmAttributes, bMaxPower) \ - USB_DESC_BYTE(USB_DESC_CONFIGURATION_SIZE), \ - USB_DESC_BYTE(USB_DESCRIPTOR_CONFIGURATION), \ - USB_DESC_WORD(wTotalLength), \ - USB_DESC_BYTE(bNumInterfaces), \ - USB_DESC_BYTE(bConfigurationValue), \ - USB_DESC_INDEX(iConfiguration), \ - USB_DESC_BYTE(bmAttributes), \ - USB_DESC_BYTE(bMaxPower) - -/** - * @brief Interface Descriptor size. - */ -#define USB_DESC_INTERFACE_SIZE 9U - -/** - * @brief Interface Descriptor helper macro. - */ -#define USB_DESC_INTERFACE(bInterfaceNumber, bAlternateSetting, \ - bNumEndpoints, bInterfaceClass, \ - bInterfaceSubClass, bInterfaceProtocol, \ - iInterface) \ - USB_DESC_BYTE(USB_DESC_INTERFACE_SIZE), \ - USB_DESC_BYTE(USB_DESCRIPTOR_INTERFACE), \ - USB_DESC_BYTE(bInterfaceNumber), \ - USB_DESC_BYTE(bAlternateSetting), \ - USB_DESC_BYTE(bNumEndpoints), \ - USB_DESC_BYTE(bInterfaceClass), \ - USB_DESC_BYTE(bInterfaceSubClass), \ - USB_DESC_BYTE(bInterfaceProtocol), \ - USB_DESC_INDEX(iInterface) - -/** - * @brief Interface Association Descriptor size. - */ -#define USB_DESC_INTERFACE_ASSOCIATION_SIZE 8U - -/** - * @brief Interface Association Descriptor helper macro. - */ -#define USB_DESC_INTERFACE_ASSOCIATION(bFirstInterface, \ - bInterfaceCount, bFunctionClass, \ - bFunctionSubClass, bFunctionProcotol, \ - iInterface) \ - USB_DESC_BYTE(USB_DESC_INTERFACE_ASSOCIATION_SIZE), \ - USB_DESC_BYTE(USB_DESCRIPTOR_INTERFACE_ASSOCIATION), \ - USB_DESC_BYTE(bFirstInterface), \ - USB_DESC_BYTE(bInterfaceCount), \ - USB_DESC_BYTE(bFunctionClass), \ - USB_DESC_BYTE(bFunctionSubClass), \ - USB_DESC_BYTE(bFunctionProcotol), \ - USB_DESC_INDEX(iInterface) - -/** - * @brief Endpoint Descriptor size. - */ -#define USB_DESC_ENDPOINT_SIZE 7U - -/** - * @brief Endpoint Descriptor helper macro. - */ -#define USB_DESC_ENDPOINT(bEndpointAddress, bmAttributes, wMaxPacketSize, \ - bInterval) \ - USB_DESC_BYTE(USB_DESC_ENDPOINT_SIZE), \ - USB_DESC_BYTE(USB_DESCRIPTOR_ENDPOINT), \ - USB_DESC_BYTE(bEndpointAddress), \ - USB_DESC_BYTE(bmAttributes), \ - USB_DESC_WORD(wMaxPacketSize), \ - USB_DESC_BYTE(bInterval) -/** @} */ - -/** - * @name Endpoint types and settings - * @{ - */ -#define USB_EP_MODE_TYPE 0x0003U /**< Endpoint type mask. */ -#define USB_EP_MODE_TYPE_CTRL 0x0000U /**< Control endpoint. */ -#define USB_EP_MODE_TYPE_ISOC 0x0001U /**< Isochronous endpoint. */ -#define USB_EP_MODE_TYPE_BULK 0x0002U /**< Bulk endpoint. */ -#define USB_EP_MODE_TYPE_INTR 0x0003U /**< Interrupt endpoint. */ -/** @} */ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) -#define USB_USE_WAIT FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a structure representing an USB driver. - */ -typedef struct USBDriver USBDriver; - -/** - * @brief Type of an endpoint identifier. - */ -typedef uint8_t usbep_t; - -/** - * @brief Type of a driver state machine possible states. - */ -typedef enum { - USB_UNINIT = 0, /**< Not initialized. */ - USB_STOP = 1, /**< Stopped. */ - USB_READY = 2, /**< Ready, after bus reset. */ - USB_SELECTED = 3, /**< Address assigned. */ - USB_ACTIVE = 4, /**< Active, configuration selected.*/ - USB_SUSPENDED = 5 /**< Suspended, low power mode. */ -} usbstate_t; - -/** - * @brief Type of an endpoint status. - */ -typedef enum { - EP_STATUS_DISABLED = 0, /**< Endpoint not active. */ - EP_STATUS_STALLED = 1, /**< Endpoint opened but stalled. */ - EP_STATUS_ACTIVE = 2 /**< Active endpoint. */ -} usbepstatus_t; - -/** - * @brief Type of an endpoint zero state machine states. - */ -typedef enum { - USB_EP0_WAITING_SETUP, /**< Waiting for SETUP data. */ - USB_EP0_TX, /**< Transmitting. */ - USB_EP0_WAITING_TX0, /**< Waiting transmit 0. */ - USB_EP0_WAITING_STS, /**< Waiting status. */ - USB_EP0_RX, /**< Receiving. */ - USB_EP0_SENDING_STS, /**< Sending status. */ - USB_EP0_ERROR /**< Error, EP0 stalled. */ -} usbep0state_t; - -/** - * @brief Type of an enumeration of the possible USB events. - */ -typedef enum { - USB_EVENT_RESET = 0, /**< Driver has been reset by host. */ - USB_EVENT_ADDRESS = 1, /**< Address assigned. */ - USB_EVENT_CONFIGURED = 2, /**< Configuration selected. */ - USB_EVENT_SUSPEND = 3, /**< Entering suspend mode. */ - USB_EVENT_WAKEUP = 4, /**< Leaving suspend mode. */ - USB_EVENT_STALLED = 5 /**< Endpoint 0 error, stalled. */ -} usbevent_t; - -/** - * @brief Type of an USB descriptor. - */ -typedef struct { - /** - * @brief Descriptor size in unicode characters. - */ - size_t ud_size; - /** - * @brief Pointer to the descriptor. - */ - const uint8_t *ud_string; -} USBDescriptor; - -/** - * @brief Type of an USB generic notification callback. - * - * @param[in] usbp pointer to the @p USBDriver object triggering the - * callback - */ -typedef void (*usbcallback_t)(USBDriver *usbp); - -/** - * @brief Type of an USB endpoint callback. - * - * @param[in] usbp pointer to the @p USBDriver object triggering the - * callback - * @param[in] ep endpoint number - */ -typedef void (*usbepcallback_t)(USBDriver *usbp, usbep_t ep); - -/** - * @brief Type of an USB event notification callback. - * - * @param[in] usbp pointer to the @p USBDriver object triggering the - * callback - * @param[in] event event type - */ -typedef void (*usbeventcb_t)(USBDriver *usbp, usbevent_t event); - -/** - * @brief Type of a requests handler callback. - * @details The request is encoded in the @p usb_setup buffer. - * - * @param[in] usbp pointer to the @p USBDriver object triggering the - * callback - * @return The request handling exit code. - * @retval false Request not recognized by the handler. - * @retval true Request handled. - */ -typedef bool (*usbreqhandler_t)(USBDriver *usbp); - -/** - * @brief Type of an USB descriptor-retrieving callback. - */ -typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, - uint8_t dtype, - uint8_t dindex, - uint16_t lang); - -#include "usb_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Returns the driver state. - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The driver state. - * - * @iclass - */ -#define usbGetDriverStateI(usbp) ((usbp)->state) - -/** - * @brief Connects the USB device. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @api - */ -#define usbConnectBus(usbp) usb_lld_connect_bus(usbp) - -/** - * @brief Disconnect the USB device. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @api - */ -#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp) - -/** - * @brief Returns the current frame number. - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The current frame number. - * - * @xclass - */ -#define usbGetFrameNumberX(usbp) usb_lld_get_frame_number(usbp) - -/** - * @brief Returns the status of an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The operation status. - * @retval false Endpoint ready. - * @retval true Endpoint transmitting. - * - * @iclass - */ -#define usbGetTransmitStatusI(usbp, ep) \ - (((usbp)->transmitting & (uint16_t)((unsigned)1U << (unsigned)(ep))) != 0U) - -/** - * @brief Returns the status of an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return The operation status. - * @retval false Endpoint ready. - * @retval true Endpoint receiving. - * - * @iclass - */ -#define usbGetReceiveStatusI(usbp, ep) \ - (((usbp)->receiving & (uint16_t)((unsigned)1U << (unsigned)(ep))) != 0U) - -/** - * @brief Returns the exact size of a receive transaction. - * @details The received size can be different from the size specified in - * @p usbStartReceiveI() because the last packet could have a size - * different from the expected one. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @return Received data size. - * - * @xclass - */ -#define usbGetReceiveTransactionSizeX(usbp, ep) \ - usb_lld_get_transaction_size(usbp, ep) - -/** - * @brief Request transfer setup. - * @details This macro is used by the request handling callbacks in order to - * prepare a transaction over the endpoint zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] buf pointer to a buffer for the transaction data - * @param[in] n number of bytes to be transferred - * @param[in] endcb callback to be invoked after the transfer or @p NULL - * - * @special - */ -#define usbSetupTransfer(usbp, buf, n, endcb) { \ - (usbp)->ep0next = (buf); \ - (usbp)->ep0n = (n); \ - (usbp)->ep0endcb = (endcb); \ -} - -/** - * @brief Reads a setup packet from the dedicated packet buffer. - * @details This function must be invoked in the context of the @p setup_cb - * callback in order to read the received setup packet. - * @pre In order to use this function the endpoint must have been - * initialized as a control endpoint. - * @note This function can be invoked both in thread and IRQ context. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * - * @special - */ -#define usbReadSetup(usbp, ep, buf) usb_lld_read_setup(usbp, ep, buf) -/** @} */ - -/** - * @name Low level driver helper macros - * @{ - */ -/** - * @brief Common ISR code, usb event callback. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] evt USB event code - * - * @notapi - */ -#define _usb_isr_invoke_event_cb(usbp, evt) { \ - if (((usbp)->config->event_cb) != NULL) { \ - (usbp)->config->event_cb(usbp, evt); \ - } \ -} - -/** - * @brief Common ISR code, SOF callback. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -#define _usb_isr_invoke_sof_cb(usbp) { \ - if (((usbp)->config->sof_cb) != NULL) { \ - (usbp)->config->sof_cb(usbp); \ - } \ -} - -/** - * @brief Common ISR code, setup packet callback. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -#define _usb_isr_invoke_setup_cb(usbp, ep) { \ - (usbp)->epc[ep]->setup_cb(usbp, ep); \ -} - -/** - * @brief Common ISR code, IN endpoint callback. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) -#define _usb_isr_invoke_in_cb(usbp, ep) { \ - (usbp)->transmitting &= ~(1 << (ep)); \ - if ((usbp)->epc[ep]->in_cb != NULL) { \ - (usbp)->epc[ep]->in_cb(usbp, ep); \ - } \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(usbp)->epc[ep]->in_state->thread, MSG_OK); \ - osalSysUnlockFromISR(); \ -} -#else -#define _usb_isr_invoke_in_cb(usbp, ep) { \ - (usbp)->transmitting &= ~(1 << (ep)); \ - if ((usbp)->epc[ep]->in_cb != NULL) { \ - (usbp)->epc[ep]->in_cb(usbp, ep); \ - } \ -} -#endif - -/** - * @brief Common ISR code, OUT endpoint event. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) -#define _usb_isr_invoke_out_cb(usbp, ep) { \ - (usbp)->receiving &= ~(1 << (ep)); \ - if ((usbp)->epc[ep]->out_cb != NULL) { \ - (usbp)->epc[ep]->out_cb(usbp, ep); \ - } \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \ - usbGetReceiveTransactionSizeX(usbp, ep)); \ - osalSysUnlockFromISR(); \ -} -#else -#define _usb_isr_invoke_out_cb(usbp, ep) { \ - (usbp)->receiving &= ~(1 << (ep)); \ - if ((usbp)->epc[ep]->out_cb != NULL) { \ - (usbp)->epc[ep]->out_cb(usbp, ep); \ - } \ -} -#endif -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void usbInit(void); - void usbObjectInit(USBDriver *usbp); - void usbStart(USBDriver *usbp, const USBConfig *config); - void usbStop(USBDriver *usbp); - void usbInitEndpointI(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp); - void usbDisableEndpointsI(USBDriver *usbp); - void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf); - void usbStartReceiveI(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n); - void usbStartTransmitI(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n); -#if USB_USE_WAIT == TRUE - msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n); - msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n); -#endif - bool usbStallReceiveI(USBDriver *usbp, usbep_t ep); - bool usbStallTransmitI(USBDriver *usbp, usbep_t ep); - void _usb_reset(USBDriver *usbp); - void _usb_suspend(USBDriver *usbp); - void _usb_wakeup(USBDriver *usbp); - void _usb_ep0setup(USBDriver *usbp, usbep_t ep); - void _usb_ep0in(USBDriver *usbp, usbep_t ep); - void _usb_ep0out(USBDriver *usbp, usbep_t ep); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_USB == TRUE */ - -#endif /* _USB_H_ */ - -/** @} */ diff --git a/os/hal/include/wdg.h b/os/hal/include/wdg.h deleted file mode 100644 index d10b4a73f..000000000 --- a/os/hal/include/wdg.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file wdg.h - * @brief WDG Driver macros and structures. - * - * @addtogroup WDG - * @{ - */ - -#ifndef _WDG_H_ -#define _WDG_H_ - -#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - WDG_UNINIT = 0, /**< Not initialized. */ - WDG_STOP = 1, /**< Stopped. */ - WDG_READY = 2 /**< Ready. */ -} wdgstate_t; - -#include "wdg_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Resets WDG's counter. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * - * @iclass - */ -#define wdgResetI(wdgp) wdg_lld_reset(wdgp) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void wdgInit(void); - void wdgStart(WDGDriver *wdgp, const WDGConfig * config); - void wdgStop(WDGDriver *wdgp); - void wdgReset(WDGDriver *wdgp); -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_WDG == TRUE */ - -#endif /* _WDG_H_ */ - -/** @} */ diff --git a/os/hal/src/adc.c b/os/hal/src/adc.c deleted file mode 100644 index 9bfb1b0d0..000000000 --- a/os/hal/src/adc.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file adc.c - * @brief ADC Driver code. - * - * @addtogroup ADC - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief ADC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void adcInit(void) { - - adc_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p ADCDriver structure. - * - * @param[out] adcp pointer to the @p ADCDriver object - * - * @init - */ -void adcObjectInit(ADCDriver *adcp) { - - adcp->state = ADC_STOP; - adcp->config = NULL; - adcp->samples = NULL; - adcp->depth = 0; - adcp->grpp = NULL; -#if ADC_USE_WAIT == TRUE - adcp->thread = NULL; -#endif -#if ADC_USE_MUTUAL_EXCLUSION == TRUE - osalMutexObjectInit(&adcp->mutex); -#endif -#if defined(ADC_DRIVER_EXT_INIT_HOOK) - ADC_DRIVER_EXT_INIT_HOOK(adcp); -#endif -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] config pointer to the @p ADCConfig object. Depending on - * the implementation the value can be @p NULL. - * - * @api - */ -void adcStart(ADCDriver *adcp, const ADCConfig *config) { - - osalDbgCheck(adcp != NULL); - - osalSysLock(); - osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), - "invalid state"); - adcp->config = config; - adc_lld_start(adcp); - adcp->state = ADC_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcStop(ADCDriver *adcp) { - - osalDbgCheck(adcp != NULL); - - osalSysLock(); - osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), - "invalid state"); - adc_lld_stop(adcp); - adcp->state = ADC_STOP; - osalSysUnlock(); -} - -/** - * @brief Starts an ADC conversion. - * @details Starts an asynchronous conversion operation. - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @api - */ -void adcStartConversion(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth) { - - osalSysLock(); - adcStartConversionI(adcp, grpp, samples, depth); - osalSysUnlock(); -} - -/** - * @brief Starts an ADC conversion. - * @details Starts an asynchronous conversion operation. - * @post The callbacks associated to the conversion group will be invoked - * on buffer fill and error events. - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @iclass - */ -void adcStartConversionI(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth) { - - osalDbgCheckClassI(); - osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && - (depth > 0U) && ((depth == 1U) || ((depth & 1U) == 0U))); - osalDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_COMPLETE) || - (adcp->state == ADC_ERROR), - "not ready"); - - adcp->samples = samples; - adcp->depth = depth; - adcp->grpp = grpp; - adcp->state = ADC_ACTIVE; - adc_lld_start_conversion(adcp); -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p ADC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcStopConversion(ADCDriver *adcp) { - - osalDbgCheck(adcp != NULL); - - osalSysLock(); - osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE), - "invalid state"); - if (adcp->state != ADC_READY) { - adc_lld_stop_conversion(adcp); - adcp->grpp = NULL; - adcp->state = ADC_READY; - _adc_reset_s(adcp); - } - osalSysUnlock(); -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p ADC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @iclass - */ -void adcStopConversionI(ADCDriver *adcp) { - - osalDbgCheckClassI(); - osalDbgCheck(adcp != NULL); - osalDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_ACTIVE) || - (adcp->state == ADC_COMPLETE), - "invalid state"); - - if (adcp->state != ADC_READY) { - adc_lld_stop_conversion(adcp); - adcp->grpp = NULL; - adcp->state = ADC_READY; - _adc_reset_i(adcp); - } -} - -#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Performs an ADC conversion. - * @details Performs a synchronous conversion operation. - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * @return The operation result. - * @retval MSG_OK Conversion finished. - * @retval MSG_RESET The conversion has been stopped using - * @p acdStopConversion() or @p acdStopConversionI(), - * the result buffer may contain incorrect data. - * @retval MSG_TIMEOUT The conversion has been stopped because an hardware - * error. - * - * @api - */ -msg_t adcConvert(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth) { - msg_t msg; - - osalSysLock(); - osalDbgAssert(adcp->thread == NULL, "already waiting"); - adcStartConversionI(adcp, grpp, samples, depth); - msg = osalThreadSuspendS(&adcp->thread); - osalSysUnlock(); - return msg; -} -#endif /* ADC_USE_WAIT == TRUE */ - -#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the ADC peripheral. - * @details This function tries to gain ownership to the ADC bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option - * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcAcquireBus(ADCDriver *adcp) { - - osalDbgCheck(adcp != NULL); - - osalMutexLock(&adcp->mutex); -} - -/** - * @brief Releases exclusive access to the ADC peripheral. - * @pre In order to use this function the option - * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcReleaseBus(ADCDriver *adcp) { - - osalDbgCheck(adcp != NULL); - - osalMutexUnlock(&adcp->mutex); -} -#endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */ - -#endif /* HAL_USE_ADC == TRUE */ - -/** @} */ diff --git a/os/hal/src/can.c b/os/hal/src/can.c deleted file mode 100644 index eecfdb7ce..000000000 --- a/os/hal/src/can.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file can.c - * @brief CAN Driver code. - * - * @addtogroup CAN - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief CAN Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void canInit(void) { - - can_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p CANDriver structure. - * - * @param[out] canp pointer to the @p CANDriver object - * - * @init - */ -void canObjectInit(CANDriver *canp) { - - canp->state = CAN_STOP; - canp->config = NULL; - osalThreadQueueObjectInit(&canp->txqueue); - osalThreadQueueObjectInit(&canp->rxqueue); - osalEventObjectInit(&canp->rxfull_event); - osalEventObjectInit(&canp->txempty_event); - osalEventObjectInit(&canp->error_event); -#if CAN_USE_SLEEP_MODE == TRUE - osalEventObjectInit(&canp->sleep_event); - osalEventObjectInit(&canp->wakeup_event); -#endif -} - -/** - * @brief Configures and activates the CAN peripheral. - * @note Activating the CAN bus can be a slow operation. - * @note Unlike other drivers it is not possible to restart the CAN - * driver without first stopping it using canStop(). - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] config pointer to the @p CANConfig object. Depending on - * the implementation the value can be @p NULL. - * - * @api - */ -void canStart(CANDriver *canp, const CANConfig *config) { - - osalDbgCheck(canp != NULL); - - osalSysLock(); - osalDbgAssert(canp->state == CAN_STOP, "invalid state"); - - /* Entering initialization mode. */ - canp->state = CAN_STARTING; - canp->config = config; - - /* Low level initialization, could be a slow process and sleeps could - be performed inside.*/ - can_lld_start(canp); - - /* The driver finally goes into the ready state.*/ - canp->state = CAN_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @api - */ -void canStop(CANDriver *canp) { - - osalDbgCheck(canp != NULL); - - osalSysLock(); - osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), - "invalid state"); - - /* The low level driver is stopped.*/ - can_lld_stop(canp); - canp->state = CAN_STOP; - - /* Threads waiting on CAN APIs are notified that the driver has been - stopped in order to not have stuck threads.*/ - osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); - osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); - osalOsRescheduleS(); - osalSysUnlock(); -} - -/** - * @brief Can frame transmission attempt. - * @details The specified frame is queued for transmission, if the hardware - * queue is full then the function fails. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[in] ctfp pointer to the CAN frame to be transmitted - * @return The operation result. - * @retval false Frame transmitted. - * @retval true Mailbox full. - * - * @iclass - */ -bool canTryTransmitI(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp) { - - osalDbgCheckClassI(); - osalDbgCheck((canp != NULL) && (ctfp != NULL) && - (mailbox <= (canmbx_t)CAN_TX_MAILBOXES)); - osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "invalid state"); - - /* If the RX mailbox is full then the function fails.*/ - if (!can_lld_is_tx_empty(canp, mailbox)) { - return true; - } - - /* Transmitting frame.*/ - can_lld_transmit(canp, mailbox, ctfp); - - return false; -} - -/** - * @brief Can frame receive attempt. - * @details The function tries to fetch a frame from a mailbox. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[out] crfp pointer to the buffer where the CAN frame is copied - * @return The operation result. - * @retval false Frame fetched. - * @retval true Mailbox empty. - * - * @iclass - */ -bool canTryReceiveI(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp) { - - osalDbgCheckClassI(); - osalDbgCheck((canp != NULL) && (crfp != NULL) && - (mailbox <= (canmbx_t)CAN_RX_MAILBOXES)); - osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "invalid state"); - - /* If the RX mailbox is empty then the function fails.*/ - if (!can_lld_is_rx_nonempty(canp, mailbox)) { - return true; - } - - /* Fetching the frame.*/ - can_lld_receive(canp, mailbox, crfp); - - return false; -} - -/** - * @brief Can frame transmission. - * @details The specified frame is queued for transmission, if the hardware - * queue is full then the invoking thread is queued. - * @note Trying to transmit while in sleep mode simply enqueues the thread. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[in] ctfp pointer to the CAN frame to be transmitted - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation result. - * @retval MSG_OK the frame has been queued for transmission. - * @retval MSG_TIMEOUT The operation has timed out. - * @retval MSG_RESET The driver has been stopped while waiting. - * - * @api - */ -msg_t canTransmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp, - systime_t timeout) { - - osalDbgCheck((canp != NULL) && (ctfp != NULL) && - (mailbox <= (canmbx_t)CAN_TX_MAILBOXES)); - - osalSysLock(); - osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "invalid state"); - - /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/ - while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { - /*lint -restore*/ - msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout); - if (msg != MSG_OK) { - osalSysUnlock(); - return msg; - } - } - can_lld_transmit(canp, mailbox, ctfp); - osalSysUnlock(); - return MSG_OK; -} - -/** - * @brief Can frame receive. - * @details The function waits until a frame is received. - * @note Trying to receive while in sleep mode simply enqueues the thread. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[out] crfp pointer to the buffer where the CAN frame is copied - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout (useful in an - * event driven scenario where a thread never blocks - * for I/O). - * - @a TIME_INFINITE no timeout. - * . - * @return The operation result. - * @retval MSG_OK a frame has been received and placed in the buffer. - * @retval MSG_TIMEOUT The operation has timed out. - * @retval MSG_RESET The driver has been stopped while waiting. - * - * @api - */ -msg_t canReceive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp, - systime_t timeout) { - - osalDbgCheck((canp != NULL) && (crfp != NULL) && - (mailbox <= (canmbx_t)CAN_RX_MAILBOXES)); - - osalSysLock(); - osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "invalid state"); - - /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/ - while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { - /*lint -restore*/ - msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout); - if (msg != MSG_OK) { - osalSysUnlock(); - return msg; - } - } - can_lld_receive(canp, mailbox, crfp); - osalSysUnlock(); - return MSG_OK; -} - -#if (CAN_USE_SLEEP_MODE == TRUE) || defined(__DOXYGEN__) -/** - * @brief Enters the sleep mode. - * @details This function puts the CAN driver in sleep mode and broadcasts - * the @p sleep_event event source. - * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must - * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported - * by the low level driver. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @api - */ -void canSleep(CANDriver *canp) { - - osalDbgCheck(canp != NULL); - - osalSysLock(); - osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "invalid state"); - if (canp->state == CAN_READY) { - can_lld_sleep(canp); - canp->state = CAN_SLEEP; - osalEventBroadcastFlagsI(&canp->sleep_event, (eventflags_t)0); - osalOsRescheduleS(); - } - osalSysUnlock(); -} - -/** - * @brief Enforces leaving the sleep mode. - * @note The sleep mode is supposed to be usually exited automatically by - * an hardware event. - * - * @param[in] canp pointer to the @p CANDriver object - */ -void canWakeup(CANDriver *canp) { - - osalDbgCheck(canp != NULL); - - osalSysLock(); - osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "invalid state"); - if (canp->state == CAN_SLEEP) { - can_lld_wakeup(canp); - canp->state = CAN_READY; - osalEventBroadcastFlagsI(&canp->wakeup_event, (eventflags_t)0); - osalOsRescheduleS(); - } - osalSysUnlock(); -} -#endif /* CAN_USE_SLEEP_MODE == TRUE */ - -#endif /* HAL_USE_CAN == TRUE */ - -/** @} */ diff --git a/os/hal/src/dac.c b/os/hal/src/dac.c deleted file mode 100644 index 0feb4308f..000000000 --- a/os/hal/src/dac.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file dac.c - * @brief DAC Driver code. - * - * @addtogroup DAC - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief DAC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void dacInit(void) { - - dac_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p DACDriver structure. - * - * @param[out] dacp pointer to the @p DACDriver object - * - * @init - */ -void dacObjectInit(DACDriver *dacp) { - - dacp->state = DAC_STOP; - dacp->config = NULL; -#if DAC_USE_WAIT - dacp->thread = NULL; -#endif -#if DAC_USE_MUTUAL_EXCLUSION - osalMutexObjectInit(&dacp->mutex); -#endif -#if defined(DAC_DRIVER_EXT_INIT_HOOK) - DAC_DRIVER_EXT_INIT_HOOK(dacp); -#endif -} - -/** - * @brief Configures and activates the DAC peripheral. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] config pointer to the @p DACConfig object, it can be - * @p NULL if the low level driver implementation - * supports a default configuration - * - * @api - */ -void dacStart(DACDriver *dacp, const DACConfig *config) { - - osalDbgCheck(dacp != NULL); - - osalSysLock(); - - osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), - "invalid state"); - - dacp->config = config; - dac_lld_start(dacp); - dacp->state = DAC_READY; - - osalSysUnlock(); -} - -/** - * @brief Deactivates the DAC peripheral. - * @note Deactivating the peripheral also enforces a release of the slave - * select line. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @api - */ -void dacStop(DACDriver *dacp) { - - osalDbgCheck(dacp != NULL); - - osalSysLock(); - - osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), - "invalid state"); - - dac_lld_stop(dacp); - dacp->state = DAC_STOP; - - osalSysUnlock(); -} - -/** - * @brief Outputs a value directly on a DAC channel. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] channel DAC channel number - * @param[in] sample value to be output - * - * @xclass - */ -void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) { - - osalDbgCheck(channel < DAC_MAX_CHANNELS); - osalDbgAssert(dacp->state == DAC_READY, "invalid state"); - - dac_lld_put_channel(dacp, channel, sample); -} - -/** - * @brief Starts a DAC conversion. - * @details Starts an asynchronous conversion operation. - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] grpp pointer to a @p DACConversionGroup object - * @param[in] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @api - */ -void dacStartConversion(DACDriver *dacp, - const DACConversionGroup *grpp, - const dacsample_t *samples, - size_t depth) { - - osalSysLock(); - dacStartConversionI(dacp, grpp, samples, depth); - osalSysUnlock(); -} - -/** - * @brief Starts a DAC conversion. - * @details Starts an asynchronous conversion operation. - * @post The callbacks associated to the conversion group will be invoked - * on buffer fill and error events. - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] grpp pointer to a @p DACConversionGroup object - * @param[in] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @iclass - */ -void dacStartConversionI(DACDriver *dacp, - const DACConversionGroup *grpp, - const dacsample_t *samples, - size_t depth) { - - osalDbgCheckClassI(); - osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) && - ((depth == 1) || ((depth & 1) == 0))); - osalDbgAssert((dacp->state == DAC_READY) || - (dacp->state == DAC_COMPLETE) || - (dacp->state == DAC_ERROR), - "not ready"); - - dacp->samples = samples; - dacp->depth = depth; - dacp->grpp = grpp; - dacp->state = DAC_ACTIVE; - dac_lld_start_conversion(dacp); -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p DAC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @api - */ -void dacStopConversion(DACDriver *dacp) { - - osalDbgCheck(dacp != NULL); - - osalSysLock(); - - osalDbgAssert((dacp->state == DAC_READY) || - (dacp->state == DAC_ACTIVE), - "invalid state"); - - if (dacp->state != DAC_READY) { - dac_lld_stop_conversion(dacp); - dacp->grpp = NULL; - dacp->state = DAC_READY; - _dac_reset_s(dacp); - } - - osalSysUnlock(); -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p DAC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @iclass - */ -void dacStopConversionI(DACDriver *dacp) { - - osalDbgCheckClassI(); - osalDbgCheck(dacp != NULL); - osalDbgAssert((dacp->state == DAC_READY) || - (dacp->state == DAC_ACTIVE) || - (dacp->state == DAC_COMPLETE), - "invalid state"); - - if (dacp->state != DAC_READY) { - dac_lld_stop_conversion(dacp); - dacp->grpp = NULL; - dacp->state = DAC_READY; - _dac_reset_i(dacp); - } -} - -#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Performs a DAC conversion. - * @details Performs a synchronous conversion operation. - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. - * - * @param[in] dacp pointer to the @p DACDriver object - * @param[in] grpp pointer to a @p DACConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * @return The operation result. - * @retval MSG_OK Conversion finished. - * @retval MSG_RESET The conversion has been stopped using - * @p acdStopConversion() or @p acdStopConversionI(), - * the result buffer may contain incorrect data. - * @retval MSG_TIMEOUT The conversion has been stopped because an hardware - * error. - * - * @api - */ -msg_t dacConvert(DACDriver *dacp, - const DACConversionGroup *grpp, - const dacsample_t *samples, - size_t depth) { - msg_t msg; - - osalSysLock(); - - dacStartConversionI(dacp, grpp, samples, depth); - msg = osalThreadSuspendS(&dacp->thread); - - osalSysUnlock(); - return msg; -} -#endif /* DAC_USE_WAIT == TRUE */ - -#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the DAC bus. - * @details This function tries to gain ownership to the DAC bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @api - */ -void dacAcquireBus(DACDriver *dacp) { - - osalDbgCheck(dacp != NULL); - - osalMutexLock(&dacp->mutex); -} - -/** - * @brief Releases exclusive access to the DAC bus. - * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] dacp pointer to the @p DACDriver object - * - * @api - */ -void dacReleaseBus(DACDriver *dacp) { - - osalDbgCheck(dacp != NULL); - - osalMutexUnlock(&dacp->mutex); -} -#endif /* DAC_USE_MUTUAL_EXCLUSION == TRUE */ - -#endif /* HAL_USE_DAC == TRUE */ - -/** @} */ diff --git a/os/hal/src/ext.c b/os/hal/src/ext.c deleted file mode 100644 index fa25e41a4..000000000 --- a/os/hal/src/ext.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file ext.c - * @brief EXT Driver code. - * - * @addtogroup EXT - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief EXT Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void extInit(void) { - - ext_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p EXTDriver structure. - * - * @param[out] extp pointer to the @p EXTDriver object - * - * @init - */ -void extObjectInit(EXTDriver *extp) { - - extp->state = EXT_STOP; - extp->config = NULL; -} - -/** - * @brief Configures and activates the EXT peripheral. - * @post After activation all EXT channels are in the disabled state, - * use @p extChannelEnable() in order to activate them. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] config pointer to the @p EXTConfig object - * - * @api - */ -void extStart(EXTDriver *extp, const EXTConfig *config) { - - osalDbgCheck((extp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE), - "invalid state"); - extp->config = config; - ext_lld_start(extp); - extp->state = EXT_ACTIVE; - osalSysUnlock(); -} - -/** - * @brief Deactivates the EXT peripheral. - * - * @param[in] extp pointer to the @p EXTDriver object - * - * @api - */ -void extStop(EXTDriver *extp) { - - osalDbgCheck(extp != NULL); - - osalSysLock(); - osalDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE), - "invalid state"); - ext_lld_stop(extp); - extp->state = EXT_STOP; - osalSysUnlock(); -} - -/** - * @brief Enables an EXT channel. - * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be enabled - * - * @api - */ -void extChannelEnable(EXTDriver *extp, expchannel_t channel) { - - osalDbgCheck((extp != NULL) && (channel < (expchannel_t)EXT_MAX_CHANNELS)); - - osalSysLock(); - osalDbgAssert((extp->state == EXT_ACTIVE) && - ((extp->config->channels[channel].mode & - EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), - "invalid state"); - extChannelEnableI(extp, channel); - osalSysUnlock(); -} - -/** - * @brief Disables an EXT channel. - * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be disabled - * - * @api - */ -void extChannelDisable(EXTDriver *extp, expchannel_t channel) { - - osalDbgCheck((extp != NULL) && (channel < (expchannel_t)EXT_MAX_CHANNELS)); - - osalSysLock(); - osalDbgAssert((extp->state == EXT_ACTIVE) && - ((extp->config->channels[channel].mode & - EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), - "invalid state"); - extChannelDisableI(extp, channel); - osalSysUnlock(); -} - -/** - * @brief Changes the operation mode of a channel. - * @note This function attempts to write over the current configuration - * structure that must have been not declared constant. This - * violates the @p const qualifier in @p extStart() but it is - * intentional. - * @note This function cannot be used if the configuration structure is - * declared @p const. - * @note The effect of this function on constant configuration structures - * is not defined. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be changed - * @param[in] extcp new configuration for the channel - * - * @iclass - */ -void extSetChannelModeI(EXTDriver *extp, - expchannel_t channel, - const EXTChannelConfig *extcp) { - EXTChannelConfig *oldcp; - - osalDbgCheck((extp != NULL) && - (channel < (expchannel_t)EXT_MAX_CHANNELS) && - (extcp != NULL)); - - osalDbgAssert(extp->state == EXT_ACTIVE, "invalid state"); - - /* Note that here the access is enforced as non-const, known access - violation.*/ - /*lint -save -e9005 [11.8] Known issue, the driver needs rework here.*/ - oldcp = (EXTChannelConfig *)&extp->config->channels[channel]; - /*lint -restore*/ - - /* Overwriting the old channels configuration then the channel is - reconfigured by the low level driver.*/ - *oldcp = *extcp; - ext_lld_channel_enable(extp, channel); -} - -#endif /* HAL_USE_EXT == TRUE */ - -/** @} */ diff --git a/os/hal/src/gpt.c b/os/hal/src/gpt.c deleted file mode 100644 index b83ffa1c1..000000000 --- a/os/hal/src/gpt.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file gpt.c - * @brief GPT Driver code. - * - * @addtogroup GPT - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief GPT Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void gptInit(void) { - - gpt_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p GPTDriver structure. - * - * @param[out] gptp pointer to the @p GPTDriver object - * - * @init - */ -void gptObjectInit(GPTDriver *gptp) { - - gptp->state = GPT_STOP; - gptp->config = NULL; -} - -/** - * @brief Configures and activates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] config pointer to the @p GPTConfig object - * - * @api - */ -void gptStart(GPTDriver *gptp, const GPTConfig *config) { - - osalDbgCheck((gptp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), - "invalid state"); - gptp->config = config; - gpt_lld_start(gptp); - gptp->state = GPT_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @api - */ -void gptStop(GPTDriver *gptp) { - - osalDbgCheck(gptp != NULL); - - osalSysLock(); - osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), - "invalid state"); - gpt_lld_stop(gptp); - gptp->state = GPT_STOP; - osalSysUnlock(); -} - -/** - * @brief Changes the interval of GPT peripheral. - * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must be running in continuous mode. - * @post The GPT unit interval is changed to the new value. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @param[in] interval new cycle time in timer ticks - * - * @api - */ -void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval) { - - osalDbgCheck(gptp != NULL); - - osalSysLock(); - osalDbgAssert(gptp->state == GPT_CONTINUOUS, - "invalid state"); - gptChangeIntervalI(gptp, interval); - osalSysUnlock(); -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @api - */ -void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval) { - - osalSysLock(); - gptStartContinuousI(gptp, interval); - osalSysUnlock(); -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @iclass - */ -void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval) { - - osalDbgCheckClassI(); - osalDbgCheck(gptp != NULL); - osalDbgAssert(gptp->state == GPT_READY, - "invalid state"); - - gptp->state = GPT_CONTINUOUS; - gpt_lld_start_timer(gptp, interval); -} - -/** - * @brief Starts the timer in one shot mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @api - */ -void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval) { - - osalSysLock(); - gptStartOneShotI(gptp, interval); - osalSysUnlock(); -} - -/** - * @brief Starts the timer in one shot mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @api - */ -void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) { - - osalDbgCheckClassI(); - osalDbgCheck(gptp != NULL); - osalDbgCheck(gptp->config->callback != NULL); - osalDbgAssert(gptp->state == GPT_READY, - "invalid state"); - - gptp->state = GPT_ONESHOT; - gpt_lld_start_timer(gptp, interval); -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @api - */ -void gptStopTimer(GPTDriver *gptp) { - - osalSysLock(); - gptStopTimerI(gptp); - osalSysUnlock(); -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @api - */ -void gptStopTimerI(GPTDriver *gptp) { - - osalDbgCheckClassI(); - osalDbgCheck(gptp != NULL); - osalDbgAssert((gptp->state == GPT_READY) || (gptp->state == GPT_CONTINUOUS) || - (gptp->state == GPT_ONESHOT), - "invalid state"); - - gptp->state = GPT_READY; - gpt_lld_stop_timer(gptp); -} - -/** - * @brief Starts the timer in one shot mode and waits for completion. - * @details This function specifically polls the timer waiting for completion - * in order to not have extra delays caused by interrupt servicing, - * this function is only recommended for short delays. - * @note The configured callback is not invoked when using this function. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @api - */ -void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval) { - - osalDbgAssert(gptp->state == GPT_READY, - "invalid state"); - - gptp->state = GPT_ONESHOT; - gpt_lld_polled_delay(gptp, interval); - gptp->state = GPT_READY; -} - -#endif /* HAL_USE_GPT == TRUE */ - -/** @} */ diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c deleted file mode 100644 index 04cd0b2c5..000000000 --- a/os/hal/src/hal.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file hal.c - * @brief HAL subsystem code. - * - * @addtogroup HAL - * @{ - */ - -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief HAL initialization. - * @details This function invokes the low level initialization code then - * initializes all the drivers enabled in the HAL. Finally the - * board-specific initialization is performed by invoking - * @p boardInit() (usually defined in @p board.c). - * - * @init - */ -void halInit(void) { - - /* Initializes the OS Abstraction Layer.*/ - osalInit(); - - /* Platform low level initializations.*/ - hal_lld_init(); - -#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) - palInit(&pal_default_config); -#endif -#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__) - adcInit(); -#endif -#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__) - canInit(); -#endif -#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__) - dacInit(); -#endif -#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__) - extInit(); -#endif -#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__) - gptInit(); -#endif -#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) - i2cInit(); -#endif -#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__) - i2sInit(); -#endif -#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__) - icuInit(); -#endif -#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__) - macInit(); -#endif -#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) - pwmInit(); -#endif -#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) - sdInit(); -#endif -#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__) - sdcInit(); -#endif -#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__) - spiInit(); -#endif -#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) - uartInit(); -#endif -#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) - usbInit(); -#endif -#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) - mmcInit(); -#endif -#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__) - sduInit(); -#endif -#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) - rtcInit(); -#endif -#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) - wdgInit(); -#endif - - /* Community driver overlay initialization.*/ -#if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__) -#if (HAL_USE_COMMUNITY == TRUE) || defined(__DOXYGEN__) - halCommunityInit(); -#endif -#endif - - /* Board specific initialization.*/ - boardInit(); - -/* - * The ST driver is a special case, it is only initialized if the OSAL is - * configured to require it. - */ -#if OSAL_ST_MODE != OSAL_ST_MODE_NONE - stInit(); -#endif -} - -/** @} */ diff --git a/os/hal/src/hal_adc.c b/os/hal/src/hal_adc.c new file mode 100644 index 000000000..9bfb1b0d0 --- /dev/null +++ b/os/hal/src/hal_adc.c @@ -0,0 +1,321 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file adc.c + * @brief ADC Driver code. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief ADC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void adcInit(void) { + + adc_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p ADCDriver structure. + * + * @param[out] adcp pointer to the @p ADCDriver object + * + * @init + */ +void adcObjectInit(ADCDriver *adcp) { + + adcp->state = ADC_STOP; + adcp->config = NULL; + adcp->samples = NULL; + adcp->depth = 0; + adcp->grpp = NULL; +#if ADC_USE_WAIT == TRUE + adcp->thread = NULL; +#endif +#if ADC_USE_MUTUAL_EXCLUSION == TRUE + osalMutexObjectInit(&adcp->mutex); +#endif +#if defined(ADC_DRIVER_EXT_INIT_HOOK) + ADC_DRIVER_EXT_INIT_HOOK(adcp); +#endif +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] config pointer to the @p ADCConfig object. Depending on + * the implementation the value can be @p NULL. + * + * @api + */ +void adcStart(ADCDriver *adcp, const ADCConfig *config) { + + osalDbgCheck(adcp != NULL); + + osalSysLock(); + osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), + "invalid state"); + adcp->config = config; + adc_lld_start(adcp); + adcp->state = ADC_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcStop(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalSysLock(); + osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), + "invalid state"); + adc_lld_stop(adcp); + adcp->state = ADC_STOP; + osalSysUnlock(); +} + +/** + * @brief Starts an ADC conversion. + * @details Starts an asynchronous conversion operation. + * @note The buffer is organized as a matrix of M*N elements where M is the + * channels number configured into the conversion group and N is the + * buffer depth. The samples are sequentially written into the buffer + * with no gaps. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] grpp pointer to a @p ADCConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @api + */ +void adcStartConversion(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth) { + + osalSysLock(); + adcStartConversionI(adcp, grpp, samples, depth); + osalSysUnlock(); +} + +/** + * @brief Starts an ADC conversion. + * @details Starts an asynchronous conversion operation. + * @post The callbacks associated to the conversion group will be invoked + * on buffer fill and error events. + * @note The buffer is organized as a matrix of M*N elements where M is the + * channels number configured into the conversion group and N is the + * buffer depth. The samples are sequentially written into the buffer + * with no gaps. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] grpp pointer to a @p ADCConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @iclass + */ +void adcStartConversionI(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth) { + + osalDbgCheckClassI(); + osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && + (depth > 0U) && ((depth == 1U) || ((depth & 1U) == 0U))); + osalDbgAssert((adcp->state == ADC_READY) || + (adcp->state == ADC_COMPLETE) || + (adcp->state == ADC_ERROR), + "not ready"); + + adcp->samples = samples; + adcp->depth = depth; + adcp->grpp = grpp; + adcp->state = ADC_ACTIVE; + adc_lld_start_conversion(adcp); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p ADC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcStopConversion(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalSysLock(); + osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE), + "invalid state"); + if (adcp->state != ADC_READY) { + adc_lld_stop_conversion(adcp); + adcp->grpp = NULL; + adcp->state = ADC_READY; + _adc_reset_s(adcp); + } + osalSysUnlock(); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p ADC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @iclass + */ +void adcStopConversionI(ADCDriver *adcp) { + + osalDbgCheckClassI(); + osalDbgCheck(adcp != NULL); + osalDbgAssert((adcp->state == ADC_READY) || + (adcp->state == ADC_ACTIVE) || + (adcp->state == ADC_COMPLETE), + "invalid state"); + + if (adcp->state != ADC_READY) { + adc_lld_stop_conversion(adcp); + adcp->grpp = NULL; + adcp->state = ADC_READY; + _adc_reset_i(adcp); + } +} + +#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Performs an ADC conversion. + * @details Performs a synchronous conversion operation. + * @note The buffer is organized as a matrix of M*N elements where M is the + * channels number configured into the conversion group and N is the + * buffer depth. The samples are sequentially written into the buffer + * with no gaps. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] grpp pointer to a @p ADCConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * @return The operation result. + * @retval MSG_OK Conversion finished. + * @retval MSG_RESET The conversion has been stopped using + * @p acdStopConversion() or @p acdStopConversionI(), + * the result buffer may contain incorrect data. + * @retval MSG_TIMEOUT The conversion has been stopped because an hardware + * error. + * + * @api + */ +msg_t adcConvert(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth) { + msg_t msg; + + osalSysLock(); + osalDbgAssert(adcp->thread == NULL, "already waiting"); + adcStartConversionI(adcp, grpp, samples, depth); + msg = osalThreadSuspendS(&adcp->thread); + osalSysUnlock(); + return msg; +} +#endif /* ADC_USE_WAIT == TRUE */ + +#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the ADC peripheral. + * @details This function tries to gain ownership to the ADC bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option + * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcAcquireBus(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalMutexLock(&adcp->mutex); +} + +/** + * @brief Releases exclusive access to the ADC peripheral. + * @pre In order to use this function the option + * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcReleaseBus(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalMutexUnlock(&adcp->mutex); +} +#endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */ + +#endif /* HAL_USE_ADC == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_can.c b/os/hal/src/hal_can.c new file mode 100644 index 000000000..eecfdb7ce --- /dev/null +++ b/os/hal/src/hal_can.c @@ -0,0 +1,361 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file can.c + * @brief CAN Driver code. + * + * @addtogroup CAN + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief CAN Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void canInit(void) { + + can_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p CANDriver structure. + * + * @param[out] canp pointer to the @p CANDriver object + * + * @init + */ +void canObjectInit(CANDriver *canp) { + + canp->state = CAN_STOP; + canp->config = NULL; + osalThreadQueueObjectInit(&canp->txqueue); + osalThreadQueueObjectInit(&canp->rxqueue); + osalEventObjectInit(&canp->rxfull_event); + osalEventObjectInit(&canp->txempty_event); + osalEventObjectInit(&canp->error_event); +#if CAN_USE_SLEEP_MODE == TRUE + osalEventObjectInit(&canp->sleep_event); + osalEventObjectInit(&canp->wakeup_event); +#endif +} + +/** + * @brief Configures and activates the CAN peripheral. + * @note Activating the CAN bus can be a slow operation. + * @note Unlike other drivers it is not possible to restart the CAN + * driver without first stopping it using canStop(). + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] config pointer to the @p CANConfig object. Depending on + * the implementation the value can be @p NULL. + * + * @api + */ +void canStart(CANDriver *canp, const CANConfig *config) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert(canp->state == CAN_STOP, "invalid state"); + + /* Entering initialization mode. */ + canp->state = CAN_STARTING; + canp->config = config; + + /* Low level initialization, could be a slow process and sleeps could + be performed inside.*/ + can_lld_start(canp); + + /* The driver finally goes into the ready state.*/ + canp->state = CAN_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @api + */ +void canStop(CANDriver *canp) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), + "invalid state"); + + /* The low level driver is stopped.*/ + can_lld_stop(canp); + canp->state = CAN_STOP; + + /* Threads waiting on CAN APIs are notified that the driver has been + stopped in order to not have stuck threads.*/ + osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); + osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); + osalOsRescheduleS(); + osalSysUnlock(); +} + +/** + * @brief Can frame transmission attempt. + * @details The specified frame is queued for transmission, if the hardware + * queue is full then the function fails. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[in] ctfp pointer to the CAN frame to be transmitted + * @return The operation result. + * @retval false Frame transmitted. + * @retval true Mailbox full. + * + * @iclass + */ +bool canTryTransmitI(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp) { + + osalDbgCheckClassI(); + osalDbgCheck((canp != NULL) && (ctfp != NULL) && + (mailbox <= (canmbx_t)CAN_TX_MAILBOXES)); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "invalid state"); + + /* If the RX mailbox is full then the function fails.*/ + if (!can_lld_is_tx_empty(canp, mailbox)) { + return true; + } + + /* Transmitting frame.*/ + can_lld_transmit(canp, mailbox, ctfp); + + return false; +} + +/** + * @brief Can frame receive attempt. + * @details The function tries to fetch a frame from a mailbox. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[out] crfp pointer to the buffer where the CAN frame is copied + * @return The operation result. + * @retval false Frame fetched. + * @retval true Mailbox empty. + * + * @iclass + */ +bool canTryReceiveI(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp) { + + osalDbgCheckClassI(); + osalDbgCheck((canp != NULL) && (crfp != NULL) && + (mailbox <= (canmbx_t)CAN_RX_MAILBOXES)); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "invalid state"); + + /* If the RX mailbox is empty then the function fails.*/ + if (!can_lld_is_rx_nonempty(canp, mailbox)) { + return true; + } + + /* Fetching the frame.*/ + can_lld_receive(canp, mailbox, crfp); + + return false; +} + +/** + * @brief Can frame transmission. + * @details The specified frame is queued for transmission, if the hardware + * queue is full then the invoking thread is queued. + * @note Trying to transmit while in sleep mode simply enqueues the thread. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[in] ctfp pointer to the CAN frame to be transmitted + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation result. + * @retval MSG_OK the frame has been queued for transmission. + * @retval MSG_TIMEOUT The operation has timed out. + * @retval MSG_RESET The driver has been stopped while waiting. + * + * @api + */ +msg_t canTransmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp, + systime_t timeout) { + + osalDbgCheck((canp != NULL) && (ctfp != NULL) && + (mailbox <= (canmbx_t)CAN_TX_MAILBOXES)); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "invalid state"); + + /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/ + while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { + /*lint -restore*/ + msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout); + if (msg != MSG_OK) { + osalSysUnlock(); + return msg; + } + } + can_lld_transmit(canp, mailbox, ctfp); + osalSysUnlock(); + return MSG_OK; +} + +/** + * @brief Can frame receive. + * @details The function waits until a frame is received. + * @note Trying to receive while in sleep mode simply enqueues the thread. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[out] crfp pointer to the buffer where the CAN frame is copied + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout (useful in an + * event driven scenario where a thread never blocks + * for I/O). + * - @a TIME_INFINITE no timeout. + * . + * @return The operation result. + * @retval MSG_OK a frame has been received and placed in the buffer. + * @retval MSG_TIMEOUT The operation has timed out. + * @retval MSG_RESET The driver has been stopped while waiting. + * + * @api + */ +msg_t canReceive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp, + systime_t timeout) { + + osalDbgCheck((canp != NULL) && (crfp != NULL) && + (mailbox <= (canmbx_t)CAN_RX_MAILBOXES)); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "invalid state"); + + /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/ + while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { + /*lint -restore*/ + msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout); + if (msg != MSG_OK) { + osalSysUnlock(); + return msg; + } + } + can_lld_receive(canp, mailbox, crfp); + osalSysUnlock(); + return MSG_OK; +} + +#if (CAN_USE_SLEEP_MODE == TRUE) || defined(__DOXYGEN__) +/** + * @brief Enters the sleep mode. + * @details This function puts the CAN driver in sleep mode and broadcasts + * the @p sleep_event event source. + * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must + * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported + * by the low level driver. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @api + */ +void canSleep(CANDriver *canp) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "invalid state"); + if (canp->state == CAN_READY) { + can_lld_sleep(canp); + canp->state = CAN_SLEEP; + osalEventBroadcastFlagsI(&canp->sleep_event, (eventflags_t)0); + osalOsRescheduleS(); + } + osalSysUnlock(); +} + +/** + * @brief Enforces leaving the sleep mode. + * @note The sleep mode is supposed to be usually exited automatically by + * an hardware event. + * + * @param[in] canp pointer to the @p CANDriver object + */ +void canWakeup(CANDriver *canp) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "invalid state"); + if (canp->state == CAN_SLEEP) { + can_lld_wakeup(canp); + canp->state = CAN_READY; + osalEventBroadcastFlagsI(&canp->wakeup_event, (eventflags_t)0); + osalOsRescheduleS(); + } + osalSysUnlock(); +} +#endif /* CAN_USE_SLEEP_MODE == TRUE */ + +#endif /* HAL_USE_CAN == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_dac.c b/os/hal/src/hal_dac.c new file mode 100644 index 000000000..0feb4308f --- /dev/null +++ b/os/hal/src/hal_dac.c @@ -0,0 +1,349 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file dac.c + * @brief DAC Driver code. + * + * @addtogroup DAC + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief DAC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void dacInit(void) { + + dac_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p DACDriver structure. + * + * @param[out] dacp pointer to the @p DACDriver object + * + * @init + */ +void dacObjectInit(DACDriver *dacp) { + + dacp->state = DAC_STOP; + dacp->config = NULL; +#if DAC_USE_WAIT + dacp->thread = NULL; +#endif +#if DAC_USE_MUTUAL_EXCLUSION + osalMutexObjectInit(&dacp->mutex); +#endif +#if defined(DAC_DRIVER_EXT_INIT_HOOK) + DAC_DRIVER_EXT_INIT_HOOK(dacp); +#endif +} + +/** + * @brief Configures and activates the DAC peripheral. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] config pointer to the @p DACConfig object, it can be + * @p NULL if the low level driver implementation + * supports a default configuration + * + * @api + */ +void dacStart(DACDriver *dacp, const DACConfig *config) { + + osalDbgCheck(dacp != NULL); + + osalSysLock(); + + osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), + "invalid state"); + + dacp->config = config; + dac_lld_start(dacp); + dacp->state = DAC_READY; + + osalSysUnlock(); +} + +/** + * @brief Deactivates the DAC peripheral. + * @note Deactivating the peripheral also enforces a release of the slave + * select line. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacStop(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalSysLock(); + + osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), + "invalid state"); + + dac_lld_stop(dacp); + dacp->state = DAC_STOP; + + osalSysUnlock(); +} + +/** + * @brief Outputs a value directly on a DAC channel. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] channel DAC channel number + * @param[in] sample value to be output + * + * @xclass + */ +void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) { + + osalDbgCheck(channel < DAC_MAX_CHANNELS); + osalDbgAssert(dacp->state == DAC_READY, "invalid state"); + + dac_lld_put_channel(dacp, channel, sample); +} + +/** + * @brief Starts a DAC conversion. + * @details Starts an asynchronous conversion operation. + * @note The buffer is organized as a matrix of M*N elements where M is the + * channels number configured into the conversion group and N is the + * buffer depth. The samples are sequentially written into the buffer + * with no gaps. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] grpp pointer to a @p DACConversionGroup object + * @param[in] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @api + */ +void dacStartConversion(DACDriver *dacp, + const DACConversionGroup *grpp, + const dacsample_t *samples, + size_t depth) { + + osalSysLock(); + dacStartConversionI(dacp, grpp, samples, depth); + osalSysUnlock(); +} + +/** + * @brief Starts a DAC conversion. + * @details Starts an asynchronous conversion operation. + * @post The callbacks associated to the conversion group will be invoked + * on buffer fill and error events. + * @note The buffer is organized as a matrix of M*N elements where M is the + * channels number configured into the conversion group and N is the + * buffer depth. The samples are sequentially written into the buffer + * with no gaps. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] grpp pointer to a @p DACConversionGroup object + * @param[in] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @iclass + */ +void dacStartConversionI(DACDriver *dacp, + const DACConversionGroup *grpp, + const dacsample_t *samples, + size_t depth) { + + osalDbgCheckClassI(); + osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) && + ((depth == 1) || ((depth & 1) == 0))); + osalDbgAssert((dacp->state == DAC_READY) || + (dacp->state == DAC_COMPLETE) || + (dacp->state == DAC_ERROR), + "not ready"); + + dacp->samples = samples; + dacp->depth = depth; + dacp->grpp = grpp; + dacp->state = DAC_ACTIVE; + dac_lld_start_conversion(dacp); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p DAC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacStopConversion(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalSysLock(); + + osalDbgAssert((dacp->state == DAC_READY) || + (dacp->state == DAC_ACTIVE), + "invalid state"); + + if (dacp->state != DAC_READY) { + dac_lld_stop_conversion(dacp); + dacp->grpp = NULL; + dacp->state = DAC_READY; + _dac_reset_s(dacp); + } + + osalSysUnlock(); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p DAC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @iclass + */ +void dacStopConversionI(DACDriver *dacp) { + + osalDbgCheckClassI(); + osalDbgCheck(dacp != NULL); + osalDbgAssert((dacp->state == DAC_READY) || + (dacp->state == DAC_ACTIVE) || + (dacp->state == DAC_COMPLETE), + "invalid state"); + + if (dacp->state != DAC_READY) { + dac_lld_stop_conversion(dacp); + dacp->grpp = NULL; + dacp->state = DAC_READY; + _dac_reset_i(dacp); + } +} + +#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Performs a DAC conversion. + * @details Performs a synchronous conversion operation. + * @note The buffer is organized as a matrix of M*N elements where M is the + * channels number configured into the conversion group and N is the + * buffer depth. The samples are sequentially written into the buffer + * with no gaps. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] grpp pointer to a @p DACConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * @return The operation result. + * @retval MSG_OK Conversion finished. + * @retval MSG_RESET The conversion has been stopped using + * @p acdStopConversion() or @p acdStopConversionI(), + * the result buffer may contain incorrect data. + * @retval MSG_TIMEOUT The conversion has been stopped because an hardware + * error. + * + * @api + */ +msg_t dacConvert(DACDriver *dacp, + const DACConversionGroup *grpp, + const dacsample_t *samples, + size_t depth) { + msg_t msg; + + osalSysLock(); + + dacStartConversionI(dacp, grpp, samples, depth); + msg = osalThreadSuspendS(&dacp->thread); + + osalSysUnlock(); + return msg; +} +#endif /* DAC_USE_WAIT == TRUE */ + +#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the DAC bus. + * @details This function tries to gain ownership to the DAC bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacAcquireBus(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalMutexLock(&dacp->mutex); +} + +/** + * @brief Releases exclusive access to the DAC bus. + * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacReleaseBus(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalMutexUnlock(&dacp->mutex); +} +#endif /* DAC_USE_MUTUAL_EXCLUSION == TRUE */ + +#endif /* HAL_USE_DAC == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_ext.c b/os/hal/src/hal_ext.c new file mode 100644 index 000000000..fa25e41a4 --- /dev/null +++ b/os/hal/src/hal_ext.c @@ -0,0 +1,202 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file ext.c + * @brief EXT Driver code. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief EXT Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void extInit(void) { + + ext_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p EXTDriver structure. + * + * @param[out] extp pointer to the @p EXTDriver object + * + * @init + */ +void extObjectInit(EXTDriver *extp) { + + extp->state = EXT_STOP; + extp->config = NULL; +} + +/** + * @brief Configures and activates the EXT peripheral. + * @post After activation all EXT channels are in the disabled state, + * use @p extChannelEnable() in order to activate them. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] config pointer to the @p EXTConfig object + * + * @api + */ +void extStart(EXTDriver *extp, const EXTConfig *config) { + + osalDbgCheck((extp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE), + "invalid state"); + extp->config = config; + ext_lld_start(extp); + extp->state = EXT_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @api + */ +void extStop(EXTDriver *extp) { + + osalDbgCheck(extp != NULL); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE), + "invalid state"); + ext_lld_stop(extp); + extp->state = EXT_STOP; + osalSysUnlock(); +} + +/** + * @brief Enables an EXT channel. + * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be enabled + * + * @api + */ +void extChannelEnable(EXTDriver *extp, expchannel_t channel) { + + osalDbgCheck((extp != NULL) && (channel < (expchannel_t)EXT_MAX_CHANNELS)); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_ACTIVE) && + ((extp->config->channels[channel].mode & + EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), + "invalid state"); + extChannelEnableI(extp, channel); + osalSysUnlock(); +} + +/** + * @brief Disables an EXT channel. + * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be disabled + * + * @api + */ +void extChannelDisable(EXTDriver *extp, expchannel_t channel) { + + osalDbgCheck((extp != NULL) && (channel < (expchannel_t)EXT_MAX_CHANNELS)); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_ACTIVE) && + ((extp->config->channels[channel].mode & + EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), + "invalid state"); + extChannelDisableI(extp, channel); + osalSysUnlock(); +} + +/** + * @brief Changes the operation mode of a channel. + * @note This function attempts to write over the current configuration + * structure that must have been not declared constant. This + * violates the @p const qualifier in @p extStart() but it is + * intentional. + * @note This function cannot be used if the configuration structure is + * declared @p const. + * @note The effect of this function on constant configuration structures + * is not defined. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be changed + * @param[in] extcp new configuration for the channel + * + * @iclass + */ +void extSetChannelModeI(EXTDriver *extp, + expchannel_t channel, + const EXTChannelConfig *extcp) { + EXTChannelConfig *oldcp; + + osalDbgCheck((extp != NULL) && + (channel < (expchannel_t)EXT_MAX_CHANNELS) && + (extcp != NULL)); + + osalDbgAssert(extp->state == EXT_ACTIVE, "invalid state"); + + /* Note that here the access is enforced as non-const, known access + violation.*/ + /*lint -save -e9005 [11.8] Known issue, the driver needs rework here.*/ + oldcp = (EXTChannelConfig *)&extp->config->channels[channel]; + /*lint -restore*/ + + /* Overwriting the old channels configuration then the channel is + reconfigured by the low level driver.*/ + *oldcp = *extcp; + ext_lld_channel_enable(extp, channel); +} + +#endif /* HAL_USE_EXT == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_gpt.c b/os/hal/src/hal_gpt.c new file mode 100644 index 000000000..b83ffa1c1 --- /dev/null +++ b/os/hal/src/hal_gpt.c @@ -0,0 +1,262 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file gpt.c + * @brief GPT Driver code. + * + * @addtogroup GPT + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief GPT Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void gptInit(void) { + + gpt_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p GPTDriver structure. + * + * @param[out] gptp pointer to the @p GPTDriver object + * + * @init + */ +void gptObjectInit(GPTDriver *gptp) { + + gptp->state = GPT_STOP; + gptp->config = NULL; +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] config pointer to the @p GPTConfig object + * + * @api + */ +void gptStart(GPTDriver *gptp, const GPTConfig *config) { + + osalDbgCheck((gptp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), + "invalid state"); + gptp->config = config; + gpt_lld_start(gptp); + gptp->state = GPT_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @api + */ +void gptStop(GPTDriver *gptp) { + + osalDbgCheck(gptp != NULL); + + osalSysLock(); + osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), + "invalid state"); + gpt_lld_stop(gptp); + gptp->state = GPT_STOP; + osalSysUnlock(); +} + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must be running in continuous mode. + * @post The GPT unit interval is changed to the new value. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * + * @api + */ +void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgCheck(gptp != NULL); + + osalSysLock(); + osalDbgAssert(gptp->state == GPT_CONTINUOUS, + "invalid state"); + gptChangeIntervalI(gptp, interval); + osalSysUnlock(); +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @api + */ +void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval) { + + osalSysLock(); + gptStartContinuousI(gptp, interval); + osalSysUnlock(); +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @iclass + */ +void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgCheckClassI(); + osalDbgCheck(gptp != NULL); + osalDbgAssert(gptp->state == GPT_READY, + "invalid state"); + + gptp->state = GPT_CONTINUOUS; + gpt_lld_start_timer(gptp, interval); +} + +/** + * @brief Starts the timer in one shot mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @api + */ +void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval) { + + osalSysLock(); + gptStartOneShotI(gptp, interval); + osalSysUnlock(); +} + +/** + * @brief Starts the timer in one shot mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @api + */ +void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgCheckClassI(); + osalDbgCheck(gptp != NULL); + osalDbgCheck(gptp->config->callback != NULL); + osalDbgAssert(gptp->state == GPT_READY, + "invalid state"); + + gptp->state = GPT_ONESHOT; + gpt_lld_start_timer(gptp, interval); +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @api + */ +void gptStopTimer(GPTDriver *gptp) { + + osalSysLock(); + gptStopTimerI(gptp); + osalSysUnlock(); +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @api + */ +void gptStopTimerI(GPTDriver *gptp) { + + osalDbgCheckClassI(); + osalDbgCheck(gptp != NULL); + osalDbgAssert((gptp->state == GPT_READY) || (gptp->state == GPT_CONTINUOUS) || + (gptp->state == GPT_ONESHOT), + "invalid state"); + + gptp->state = GPT_READY; + gpt_lld_stop_timer(gptp); +} + +/** + * @brief Starts the timer in one shot mode and waits for completion. + * @details This function specifically polls the timer waiting for completion + * in order to not have extra delays caused by interrupt servicing, + * this function is only recommended for short delays. + * @note The configured callback is not invoked when using this function. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @api + */ +void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgAssert(gptp->state == GPT_READY, + "invalid state"); + + gptp->state = GPT_ONESHOT; + gpt_lld_polled_delay(gptp, interval); + gptp->state = GPT_READY; +} + +#endif /* HAL_USE_GPT == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_hal.c b/os/hal/src/hal_hal.c new file mode 100644 index 000000000..04cd0b2c5 --- /dev/null +++ b/os/hal/src/hal_hal.c @@ -0,0 +1,144 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal.c + * @brief HAL subsystem code. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief HAL initialization. + * @details This function invokes the low level initialization code then + * initializes all the drivers enabled in the HAL. Finally the + * board-specific initialization is performed by invoking + * @p boardInit() (usually defined in @p board.c). + * + * @init + */ +void halInit(void) { + + /* Initializes the OS Abstraction Layer.*/ + osalInit(); + + /* Platform low level initializations.*/ + hal_lld_init(); + +#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) + palInit(&pal_default_config); +#endif +#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__) + adcInit(); +#endif +#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__) + canInit(); +#endif +#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__) + dacInit(); +#endif +#if (HAL_USE_EXT == TRUE) || defined(__DOXYGEN__) + extInit(); +#endif +#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__) + gptInit(); +#endif +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + i2cInit(); +#endif +#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__) + i2sInit(); +#endif +#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__) + icuInit(); +#endif +#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__) + macInit(); +#endif +#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) + pwmInit(); +#endif +#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) + sdInit(); +#endif +#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__) + sdcInit(); +#endif +#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__) + spiInit(); +#endif +#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) + uartInit(); +#endif +#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) + usbInit(); +#endif +#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) + mmcInit(); +#endif +#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__) + sduInit(); +#endif +#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) + rtcInit(); +#endif +#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) + wdgInit(); +#endif + + /* Community driver overlay initialization.*/ +#if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__) +#if (HAL_USE_COMMUNITY == TRUE) || defined(__DOXYGEN__) + halCommunityInit(); +#endif +#endif + + /* Board specific initialization.*/ + boardInit(); + +/* + * The ST driver is a special case, it is only initialized if the OSAL is + * configured to require it. + */ +#if OSAL_ST_MODE != OSAL_ST_MODE_NONE + stInit(); +#endif +} + +/** @} */ diff --git a/os/hal/src/hal_i2c.c b/os/hal/src/hal_i2c.c new file mode 100644 index 000000000..0ed77eeaf --- /dev/null +++ b/os/hal/src/hal_i2c.c @@ -0,0 +1,283 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file i2c.c + * @brief I2C Driver code. + * + * @addtogroup I2C + * @{ + */ +#include "hal.h" + +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief I2C Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void i2cInit(void) { + + i2c_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2CDriver structure. + * + * @param[out] i2cp pointer to the @p I2CDriver object + * + * @init + */ +void i2cObjectInit(I2CDriver *i2cp) { + + i2cp->state = I2C_STOP; + i2cp->config = NULL; + +#if I2C_USE_MUTUAL_EXCLUSION == TRUE + osalMutexObjectInit(&i2cp->mutex); +#endif + +#if defined(I2C_DRIVER_EXT_INIT_HOOK) + I2C_DRIVER_EXT_INIT_HOOK(i2cp); +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] config pointer to the @p I2CConfig object + * + * @api + */ +void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { + + osalDbgCheck((i2cp != NULL) && (config != NULL)); + osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || + (i2cp->state == I2C_LOCKED), "invalid state"); + + osalSysLock(); + i2cp->config = config; + i2c_lld_start(i2cp); + i2cp->state = I2C_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cStop(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || + (i2cp->state == I2C_LOCKED), "invalid state"); + + osalSysLock(); + i2c_lld_stop(i2cp); + i2cp->state = I2C_STOP; + osalSysUnlock(); +} + +/** + * @brief Returns the errors mask associated to the previous operation. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @return The errors mask. + * + * @api + */ +i2cflags_t i2cGetErrors(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + return i2c_lld_get_errors(i2cp); +} + +/** + * @brief Sends data via the I2C bus. + * @details Function designed to realize "read-through-write" transfer + * paradigm. If you want transmit data without any further read, + * than set @b rxbytes field to 0. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address (7 bits) without R/W bit + * @param[in] txbuf pointer to transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to receive buffer + * @param[in] rxbytes number of bytes to be received, set it to 0 if + * you want transmit only + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, + i2caddr_t addr, + const uint8_t *txbuf, + size_t txbytes, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout) { + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && (addr != 0U) && + (txbytes > 0U) && (txbuf != NULL) && + ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != NULL))) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_TX; + rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes, + rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) { + i2cp->state = I2C_LOCKED; + } + else { + i2cp->state = I2C_READY; + } + osalSysUnlock(); + return rdymsg; +} + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address (7 bits) without R/W bit + * @param[out] rxbuf pointer to receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, + i2caddr_t addr, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout){ + + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && (addr != 0U) && + (rxbytes > 0U) && (rxbuf != NULL) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_RX; + rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) { + i2cp->state = I2C_LOCKED; + } + else { + i2cp->state = I2C_READY; + } + osalSysUnlock(); + return rdymsg; +} + +#if (I2C_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the I2C bus. + * @details This function tries to gain ownership to the I2C bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cAcquireBus(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + osalMutexLock(&i2cp->mutex); +} + +/** + * @brief Releases exclusive access to the I2C bus. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cReleaseBus(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + osalMutexUnlock(&i2cp->mutex); +} +#endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */ + +#endif /* HAL_USE_I2C == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_i2s.c b/os/hal/src/hal_i2s.c new file mode 100644 index 000000000..57a43a7e3 --- /dev/null +++ b/os/hal/src/hal_i2s.c @@ -0,0 +1,155 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file i2s.c + * @brief I2S Driver code. + * + * @addtogroup I2S + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief I2S Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void i2sInit(void) { + + i2s_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2SDriver structure. + * + * @param[out] i2sp pointer to the @p I2SDriver object + * + * @init + */ +void i2sObjectInit(I2SDriver *i2sp) { + + i2sp->state = I2S_STOP; + i2sp->config = NULL; +} + +/** + * @brief Configures and activates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] config pointer to the @p I2SConfig object + * + * @api + */ +void i2sStart(I2SDriver *i2sp, const I2SConfig *config) { + + osalDbgCheck((i2sp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), + "invalid state"); + i2sp->config = config; + i2s_lld_start(i2sp); + i2sp->state = I2S_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @api + */ +void i2sStop(I2SDriver *i2sp) { + + osalDbgCheck(i2sp != NULL); + + osalSysLock(); + osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), + "invalid state"); + i2s_lld_stop(i2sp); + i2sp->state = I2S_STOP; + osalSysUnlock(); +} + +/** + * @brief Starts a I2S data exchange. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @api + */ +void i2sStartExchange(I2SDriver *i2sp) { + + osalDbgCheck(i2sp != NULL); + + osalSysLock(); + osalDbgAssert(i2sp->state == I2S_READY, "not ready"); + i2sStartExchangeI(i2sp); + osalSysUnlock(); +} + +/** + * @brief Stops the ongoing data exchange. + * @details The ongoing data exchange, if any, is stopped, if the driver + * was not active the function does nothing. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @api + */ +void i2sStopExchange(I2SDriver *i2sp) { + + osalDbgCheck((i2sp != NULL)); + + osalSysLock(); + osalDbgAssert((i2sp->state == I2S_READY) || + (i2sp->state == I2S_ACTIVE) || + (i2sp->state == I2S_COMPLETE), + "invalid state"); + i2sStopExchangeI(i2sp); + osalSysUnlock(); +} + +#endif /* HAL_USE_I2S == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_icu.c b/os/hal/src/hal_icu.c new file mode 100644 index 000000000..ab42dc8ce --- /dev/null +++ b/os/hal/src/hal_icu.c @@ -0,0 +1,225 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file icu.c + * @brief ICU Driver code. + * + * @addtogroup ICU + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief ICU Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void icuInit(void) { + + icu_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p ICUDriver structure. + * + * @param[out] icup pointer to the @p ICUDriver object + * + * @init + */ +void icuObjectInit(ICUDriver *icup) { + + icup->state = ICU_STOP; + icup->config = NULL; +} + +/** + * @brief Configures and activates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * @param[in] config pointer to the @p ICUConfig object + * + * @api + */ +void icuStart(ICUDriver *icup, const ICUConfig *config) { + + osalDbgCheck((icup != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), + "invalid state"); + icup->config = config; + icu_lld_start(icup); + icup->state = ICU_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuStop(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), + "invalid state"); + icu_lld_stop(icup); + icup->state = ICU_STOP; + osalSysUnlock(); +} + +/** + * @brief Starts the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuStartCapture(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert(icup->state == ICU_READY, "invalid state"); + icuStartCaptureI(icup); + osalSysUnlock(); +} + +/** + * @brief Waits for a completed capture. + * @note The operation could be performed in polled mode depending on. + * @note In order to use this function notifications must be disabled. + * @pre The driver must be in @p ICU_WAITING or @p ICU_ACTIVE states. + * @post After the capture is available the driver is in @p ICU_ACTIVE + * state. If a capture fails then the driver is in @p ICU_WAITING + * state. + * + * @param[in] icup pointer to the @p ICUDriver object + * @return The capture status. + * @retval false if the capture is successful. + * @retval true if a timer overflow occurred. + * + * @api + */ +bool icuWaitCapture(ICUDriver *icup) { + bool result; + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE), + "invalid state"); + osalDbgAssert(icuAreNotificationsEnabledX(icup) == false, + "notifications enabled"); + result = icu_lld_wait_capture(icup); + icup->state = result ? ICU_WAITING : ICU_ACTIVE; + osalSysUnlock(); + + return result; +} + +/** + * @brief Stops the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuStopCapture(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_READY) || (icup->state == ICU_WAITING) || + (icup->state == ICU_ACTIVE), + "invalid state"); + icuStopCaptureI(icup); + osalSysUnlock(); +} + +/** + * @brief Enables notifications. + * @pre The ICU unit must have been activated using @p icuStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuEnableNotifications(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE), + "invalid state"); + icuEnableNotificationsI(icup); + osalSysUnlock(); +} + +/** + * @brief Disables notifications. + * @pre The ICU unit must have been activated using @p icuStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuDisableNotifications(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE), + "invalid state"); + icuDisableNotificationsI(icup); + osalSysUnlock(); +} + +#endif /* HAL_USE_ICU == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_mac.c b/os/hal/src/hal_mac.c new file mode 100644 index 000000000..18add7560 --- /dev/null +++ b/os/hal/src/hal_mac.c @@ -0,0 +1,268 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file mac.c + * @brief MAC Driver code. + * + * @addtogroup MAC + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if (MAC_USE_ZERO_COPY == TRUE) && (MAC_SUPPORTS_ZERO_COPY == FALSE) +#error "MAC_USE_ZERO_COPY not supported by this implementation" +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MAC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void macInit(void) { + + mac_lld_init(); +} + +/** + * @brief Initialize the standard part of a @p MACDriver structure. + * + * @param[out] macp pointer to the @p MACDriver object + * + * @init + */ +void macObjectInit(MACDriver *macp) { + + macp->state = MAC_STOP; + macp->config = NULL; + osalThreadQueueObjectInit(&macp->tdqueue); + osalThreadQueueObjectInit(&macp->rdqueue); +#if MAC_USE_EVENTS == TRUE + osalEventObjectInit(&macp->rdevent); +#endif +} + +/** + * @brief Configures and activates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] config pointer to the @p MACConfig object + * + * @api + */ +void macStart(MACDriver *macp, const MACConfig *config) { + + osalDbgCheck((macp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert(macp->state == MAC_STOP, + "invalid state"); + macp->config = config; + mac_lld_start(macp); + macp->state = MAC_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @api + */ +void macStop(MACDriver *macp) { + + osalDbgCheck(macp != NULL); + + osalSysLock(); + osalDbgAssert((macp->state == MAC_STOP) || (macp->state == MAC_ACTIVE), + "invalid state"); + mac_lld_stop(macp); + macp->state = MAC_STOP; + osalSysUnlock(); +} + +/** + * @brief Allocates a transmission descriptor. + * @details One of the available transmission descriptors is locked and + * returned. If a descriptor is not currently available then the + * invoking thread is queued until one is freed. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK the descriptor was obtained. + * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized. + * + * @api + */ +msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t timeout) { + msg_t msg; + systime_t now; + + osalDbgCheck((macp != NULL) && (tdp != NULL)); + osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); + + while (((msg = mac_lld_get_transmit_descriptor(macp, tdp)) != MSG_OK) && + (timeout > (systime_t)0)) { + osalSysLock(); + now = osalOsGetSystemTimeX(); + msg = osalThreadEnqueueTimeoutS(&macp->tdqueue, timeout); + if (msg == MSG_TIMEOUT) { + osalSysUnlock(); + break; + } + if (timeout != TIME_INFINITE) { + timeout -= (osalOsGetSystemTimeX() - now); + } + osalSysUnlock(); + } + return msg; +} + +/** + * @brief Releases a transmit descriptor and starts the transmission of the + * enqueued data as a single frame. + * + * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure + * + * @api + */ +void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { + + osalDbgCheck(tdp != NULL); + + mac_lld_release_transmit_descriptor(tdp); +} + +/** + * @brief Waits for a received frame. + * @details Stops until a frame is received and buffered. If a frame is + * not immediately available then the invoking thread is queued + * until one is received. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK the descriptor was obtained. + * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized. + * + * @api + */ +msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t timeout) { + msg_t msg; + systime_t now; + + osalDbgCheck((macp != NULL) && (rdp != NULL)); + osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); + + while (((msg = mac_lld_get_receive_descriptor(macp, rdp)) != MSG_OK) && + (timeout > (systime_t)0)) { + osalSysLock(); + now = osalOsGetSystemTimeX(); + msg = osalThreadEnqueueTimeoutS(&macp->rdqueue, timeout); + if (msg == MSG_TIMEOUT) { + osalSysUnlock(); + break; + } + if (timeout != TIME_INFINITE) { + timeout -= (osalOsGetSystemTimeX() - now); + } + osalSysUnlock(); + } + return msg; +} + +/** + * @brief Releases a receive descriptor. + * @details The descriptor and its buffer are made available for more incoming + * frames. + * + * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure + * + * @api + */ +void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { + + osalDbgCheck(rdp != NULL); + + mac_lld_release_receive_descriptor(rdp); +} + +/** + * @brief Updates and returns the link status. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The link status. + * @retval true if the link is active. + * @retval false if the link is down. + * + * @api + */ +bool macPollLinkStatus(MACDriver *macp) { + + osalDbgCheck(macp != NULL); + osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); + + return mac_lld_poll_link_status(macp); +} + +#endif /* HAL_USE_MAC == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_mmc_spi.c b/os/hal/src/hal_mmc_spi.c new file mode 100644 index 000000000..acb0d6d2e --- /dev/null +++ b/os/hal/src/hal_mmc_spi.c @@ -0,0 +1,918 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Parts of this file have been contributed by Matthias Blaicher. + */ + +/** + * @file mmc_spi.c + * @brief MMC over SPI driver code. + * + * @addtogroup MMC_SPI + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* Forward declarations required by mmc_vmt.*/ +static bool mmc_read(void *instance, uint32_t startblk, + uint8_t *buffer, uint32_t n); +static bool mmc_write(void *instance, uint32_t startblk, + const uint8_t *buffer, uint32_t n); + +/** + * @brief Virtual methods table. + */ +static const struct MMCDriverVMT mmc_vmt = { + (bool (*)(void *))mmc_lld_is_card_inserted, + (bool (*)(void *))mmc_lld_is_write_protected, + (bool (*)(void *))mmcConnect, + (bool (*)(void *))mmcDisconnect, + mmc_read, + mmc_write, + (bool (*)(void *))mmcSync, + (bool (*)(void *, BlockDeviceInfo *))mmcGetInfo +}; + +/** + * @brief Lookup table for CRC-7 ( based on polynomial x^7 + x^3 + 1). + */ +static const uint8_t crc7_lookup_table[256] = { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, + 0x6c, 0x65, 0x7e, 0x77, 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, + 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 0x32, 0x3b, 0x20, 0x29, + 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, + 0x47, 0x4e, 0x55, 0x5c, 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 0x7d, 0x74, 0x6f, 0x66, + 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, + 0x3a, 0x33, 0x28, 0x21, 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, + 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5a, + 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, + 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, + 0x34, 0x3d, 0x26, 0x2f, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x6a, 0x63, 0x78, 0x71, + 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, + 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, + 0x49, 0x40, 0x5b, 0x52, 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, + 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 0x17, 0x1e, 0x05, 0x0c, + 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, + 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, + 0x62, 0x6b, 0x70, 0x79 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static bool mmc_read(void *instance, uint32_t startblk, + uint8_t *buffer, uint32_t n) { + + if (mmcStartSequentialRead((MMCDriver *)instance, startblk)) { + return HAL_FAILED; + } + + while (n > 0U) { + if (mmcSequentialRead((MMCDriver *)instance, buffer)) { + return HAL_FAILED; + } + buffer += MMCSD_BLOCK_SIZE; + n--; + } + + if (mmcStopSequentialRead((MMCDriver *)instance)) { + return HAL_FAILED; + } + return HAL_SUCCESS; +} + +static bool mmc_write(void *instance, uint32_t startblk, + const uint8_t *buffer, uint32_t n) { + + if (mmcStartSequentialWrite((MMCDriver *)instance, startblk)) { + return HAL_FAILED; + } + + while (n > 0U) { + if (mmcSequentialWrite((MMCDriver *)instance, buffer)) { + return HAL_FAILED; + } + buffer += MMCSD_BLOCK_SIZE; + n--; + } + + if (mmcStopSequentialWrite((MMCDriver *)instance)) { + return HAL_FAILED; + } + return HAL_SUCCESS; +} + +/** + * @brief Calculate the MMC standard CRC-7 based on a lookup table. + * + * @param[in] crc start value for CRC + * @param[in] buffer pointer to data buffer + * @param[in] len length of data + * @return Calculated CRC + */ +static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) { + + while (len > 0U) { + crc = crc7_lookup_table[(crc << 1) ^ (*buffer++)]; + len--; + } + return crc; +} + +/** + * @brief Waits an idle condition. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @notapi + */ +static void wait(MMCDriver *mmcp) { + int i; + uint8_t buf[4]; + + for (i = 0; i < 16; i++) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFFU) { + return; + } + } + /* Looks like it is a long wait.*/ + while (true) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFFU) { + break; + } +#if MMC_NICE_WAITING == TRUE + /* Trying to be nice with the other threads.*/ + osalThreadSleepMilliseconds(1); +#endif + } +} + +/** + * @brief Sends a command header. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] cmd the command id + * @param[in] arg the command argument + * + * @notapi + */ +static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { + uint8_t buf[6]; + + /* Wait for the bus to become idle if a write operation was in progress.*/ + wait(mmcp); + + buf[0] = (uint8_t)0x40U | cmd; + buf[1] = (uint8_t)(arg >> 24U); + buf[2] = (uint8_t)(arg >> 16U); + buf[3] = (uint8_t)(arg >> 8U); + buf[4] = (uint8_t)arg; + /* Calculate CRC for command header, shift to right position, add stop bit.*/ + buf[5] = ((crc7(0, buf, 5U) & 0x7FU) << 1U) | 0x01U; + + spiSend(mmcp->config->spip, 6, buf); +} + +/** + * @brief Receives a single byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The response as an @p uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t recvr1(MMCDriver *mmcp) { + int i; + uint8_t r1[1]; + + for (i = 0; i < 9; i++) { + spiReceive(mmcp->config->spip, 1, r1); + if (r1[0] != 0xFFU) { + return r1[0]; + } + } + return 0xFFU; +} + +/** + * @brief Receives a three byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to four bytes wide buffer + * @return First response byte as an @p uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t recvr3(MMCDriver *mmcp, uint8_t* buffer) { + uint8_t r1; + + r1 = recvr1(mmcp); + spiReceive(mmcp->config->spip, 4, buffer); + + return r1; +} + +/** + * @brief Sends a command an returns a single byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] cmd the command id + * @param[in] arg the command argument + * @return The response as an @p uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { + uint8_t r1; + + spiSelect(mmcp->config->spip); + send_hdr(mmcp, cmd, arg); + r1 = recvr1(mmcp); + spiUnselect(mmcp->config->spip); + return r1; +} + +/** + * @brief Sends a command which returns a five bytes response (R3). + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] cmd the command id + * @param[in] arg the command argument + * @param[out] response pointer to four bytes wide uint8_t buffer + * @return The first byte of the response (R1) as an @p + * uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg, + uint8_t *response) { + uint8_t r1; + + spiSelect(mmcp->config->spip); + send_hdr(mmcp, cmd, arg); + r1 = recvr3(mmcp, response); + spiUnselect(mmcp->config->spip); + return r1; +} + +/** + * @brief Reads the CSD. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] cmd command + * @param[out] cxd pointer to the CSD/CID buffer + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @notapi + */ +static bool read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) { + unsigned i; + uint8_t *bp, buf[16]; + + spiSelect(mmcp->config->spip); + send_hdr(mmcp, cmd, 0); + if (recvr1(mmcp) != 0x00U) { + spiUnselect(mmcp->config->spip); + return HAL_FAILED; + } + + /* Wait for data availability.*/ + for (i = 0U; i < MMC_WAIT_DATA; i++) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFEU) { + uint32_t *wp; + + spiReceive(mmcp->config->spip, 16, buf); + bp = buf; + for (wp = &cxd[3]; wp >= cxd; wp--) { + *wp = ((uint32_t)bp[0] << 24U) | ((uint32_t)bp[1] << 16U) | + ((uint32_t)bp[2] << 8U) | (uint32_t)bp[3]; + bp += 4; + } + + /* CRC ignored then end of transaction. */ + spiIgnore(mmcp->config->spip, 2); + spiUnselect(mmcp->config->spip); + + return HAL_SUCCESS; + } + } + return HAL_FAILED; +} + +/** + * @brief Waits that the card reaches an idle state. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @notapi + */ +static void sync(MMCDriver *mmcp) { + uint8_t buf[1]; + + spiSelect(mmcp->config->spip); + while (true) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFFU) { + break; + } +#if MMC_NICE_WAITING == TRUE + /* Trying to be nice with the other threads.*/ + osalThreadSleepMilliseconds(1); +#endif + } + spiUnselect(mmcp->config->spip); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MMC over SPI driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void mmcInit(void) { + +} + +/** + * @brief Initializes an instance. + * + * @param[out] mmcp pointer to the @p MMCDriver object + * + * @init + */ +void mmcObjectInit(MMCDriver *mmcp) { + + mmcp->vmt = &mmc_vmt; + mmcp->state = BLK_STOP; + mmcp->config = NULL; + mmcp->block_addresses = false; +} + +/** + * @brief Configures and activates the MMC peripheral. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] config pointer to the @p MMCConfig object. + * + * @api + */ +void mmcStart(MMCDriver *mmcp, const MMCConfig *config) { + + osalDbgCheck((mmcp != NULL) && (config != NULL)); + osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), + "invalid state"); + + mmcp->config = config; + mmcp->state = BLK_ACTIVE; +} + +/** + * @brief Disables the MMC peripheral. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @api + */ +void mmcStop(MMCDriver *mmcp) { + + osalDbgCheck(mmcp != NULL); + osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), + "invalid state"); + + spiStop(mmcp->config->spip); + mmcp->state = BLK_STOP; +} + +/** + * @brief Performs the initialization procedure on the inserted card. + * @details This function should be invoked when a card is inserted and + * brings the driver in the @p MMC_READY state where it is possible + * to perform read and write operations. + * @note It is possible to invoke this function from the insertion event + * handler. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded and the driver is now + * in the @p MMC_READY state. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcConnect(MMCDriver *mmcp) { + unsigned i; + uint8_t r3[4]; + + osalDbgCheck(mmcp != NULL); + + osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), + "invalid state"); + + /* Connection procedure in progress.*/ + mmcp->state = BLK_CONNECTING; + mmcp->block_addresses = false; + + /* Slow clock mode and 128 clock pulses.*/ + spiStart(mmcp->config->spip, mmcp->config->lscfg); + spiIgnore(mmcp->config->spip, 16); + + /* SPI mode selection.*/ + i = 0; + while (true) { + if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01U) { + break; + } + if (++i >= MMC_CMD0_RETRY) { + goto failed; + } + osalThreadSleepMilliseconds(10); + } + + /* Try to detect if this is a high capacity card and switch to block + addresses if possible. + This method is based on "How to support SDC Ver2 and high capacity cards" + by ElmChan.*/ + if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND, + MMCSD_CMD8_PATTERN, r3) != 0x05U) { + + /* Switch to SDHC mode.*/ + i = 0; + while (true) { + /*lint -save -e9007 [13.5] Side effect unimportant.*/ + if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) == 0x01U) && + (send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND, 0x400001AAU, r3) == 0x00U)) { + /*lint -restore*/ + break; + } + + if (++i >= MMC_ACMD41_RETRY) { + goto failed; + } + osalThreadSleepMilliseconds(10); + } + + /* Execute dedicated read on OCR register */ + (void) send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3); + + /* Check if CCS is set in response. Card operates in block mode if set.*/ + if ((r3[0] & 0x40U) != 0U) { + mmcp->block_addresses = true; + } + } + + /* Initialization.*/ + i = 0; + while (true) { + uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0); + if (b == 0x00U) { + break; + } + if (b != 0x01U) { + goto failed; + } + if (++i >= MMC_CMD1_RETRY) { + goto failed; + } + osalThreadSleepMilliseconds(10); + } + + /* Initialization complete, full speed.*/ + spiStart(mmcp->config->spip, mmcp->config->hscfg); + + /* Setting block size.*/ + if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN, + MMCSD_BLOCK_SIZE) != 0x00U) { + goto failed; + } + + /* Determine capacity.*/ + if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd)) { + goto failed; + } + + mmcp->capacity = _mmcsd_get_capacity(mmcp->csd); + if (mmcp->capacity == 0U) { + goto failed; + } + + if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid)) { + goto failed; + } + + mmcp->state = BLK_READY; + return HAL_SUCCESS; + + /* Connection failed, state reset to BLK_ACTIVE.*/ +failed: + spiStop(mmcp->config->spip); + mmcp->state = BLK_ACTIVE; + return HAL_FAILED; +} + +/** + * @brief Brings the driver in a state safe for card removal. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The operation status. + * + * @retval HAL_SUCCESS the operation succeeded and the driver is now + * in the @p MMC_INSERTED state. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcDisconnect(MMCDriver *mmcp) { + + osalDbgCheck(mmcp != NULL); + + osalSysLock(); + osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), + "invalid state"); + if (mmcp->state == BLK_ACTIVE) { + osalSysUnlock(); + return HAL_SUCCESS; + } + mmcp->state = BLK_DISCONNECTING; + osalSysUnlock(); + + /* Wait for the pending write operations to complete.*/ + spiStart(mmcp->config->spip, mmcp->config->hscfg); + sync(mmcp); + + spiStop(mmcp->config->spip); + mmcp->state = BLK_ACTIVE; + return HAL_SUCCESS; +} + +/** + * @brief Starts a sequential read. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk first block to read + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { + + osalDbgCheck(mmcp != NULL); + osalDbgAssert(mmcp->state == BLK_READY, "invalid state"); + + /* Read operation in progress.*/ + mmcp->state = BLK_READING; + + /* (Re)starting the SPI in case it has been reprogrammed externally, it can + happen if the SPI bus is shared among multiple peripherals.*/ + spiStart(mmcp->config->spip, mmcp->config->hscfg); + spiSelect(mmcp->config->spip); + + if (mmcp->block_addresses) { + send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk); + } + else { + send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE); + } + + if (recvr1(mmcp) != 0x00U) { + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return HAL_FAILED; + } + return HAL_SUCCESS; +} + +/** + * @brief Reads a block within a sequential read operation. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to the read buffer + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { + unsigned i; + + osalDbgCheck((mmcp != NULL) && (buffer != NULL)); + + if (mmcp->state != BLK_READING) { + return HAL_FAILED; + } + + for (i = 0; i < MMC_WAIT_DATA; i++) { + spiReceive(mmcp->config->spip, 1, buffer); + if (buffer[0] == 0xFEU) { + spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer); + /* CRC ignored. */ + spiIgnore(mmcp->config->spip, 2); + return HAL_SUCCESS; + } + } + /* Timeout.*/ + spiUnselect(mmcp->config->spip); + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return HAL_FAILED; +} + +/** + * @brief Stops a sequential read gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcStopSequentialRead(MMCDriver *mmcp) { + static const uint8_t stopcmd[] = { + (uint8_t)(0x40U | MMCSD_CMD_STOP_TRANSMISSION), 0, 0, 0, 0, 1, 0xFF + }; + + osalDbgCheck(mmcp != NULL); + + if (mmcp->state != BLK_READING) { + return HAL_FAILED; + } + + spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd); +/* result = recvr1(mmcp) != 0x00U;*/ + /* Note, ignored r1 response, it can be not zero, unknown issue.*/ + (void) recvr1(mmcp); + + /* Read operation finished.*/ + spiUnselect(mmcp->config->spip); + mmcp->state = BLK_READY; + return HAL_SUCCESS; +} + +/** + * @brief Starts a sequential write. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk first block to write + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { + + osalDbgCheck(mmcp != NULL); + osalDbgAssert(mmcp->state == BLK_READY, "invalid state"); + + /* Write operation in progress.*/ + mmcp->state = BLK_WRITING; + + spiStart(mmcp->config->spip, mmcp->config->hscfg); + spiSelect(mmcp->config->spip); + if (mmcp->block_addresses) { + send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk); + } + else { + send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk * MMCSD_BLOCK_SIZE); + } + + if (recvr1(mmcp) != 0x00U) { + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return HAL_FAILED; + } + return HAL_SUCCESS; +} + +/** + * @brief Writes a block within a sequential write operation. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to the write buffer + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { + static const uint8_t start[] = {0xFF, 0xFC}; + uint8_t b[1]; + + osalDbgCheck((mmcp != NULL) && (buffer != NULL)); + + if (mmcp->state != BLK_WRITING) { + return HAL_FAILED; + } + + spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ + spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ + spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */ + spiReceive(mmcp->config->spip, 1, b); + if ((b[0] & 0x1FU) == 0x05U) { + wait(mmcp); + return HAL_SUCCESS; + } + + /* Error.*/ + spiUnselect(mmcp->config->spip); + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return HAL_FAILED; +} + +/** + * @brief Stops a sequential write gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcStopSequentialWrite(MMCDriver *mmcp) { + static const uint8_t stop[] = {0xFD, 0xFF}; + + osalDbgCheck(mmcp != NULL); + + if (mmcp->state != BLK_WRITING) { + return HAL_FAILED; + } + + spiSend(mmcp->config->spip, sizeof(stop), stop); + spiUnselect(mmcp->config->spip); + + /* Write operation finished.*/ + mmcp->state = BLK_READY; + return HAL_SUCCESS; +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcSync(MMCDriver *mmcp) { + + osalDbgCheck(mmcp != NULL); + + if (mmcp->state != BLK_READY) { + return HAL_FAILED; + } + + /* Synchronization operation in progress.*/ + mmcp->state = BLK_SYNCING; + + spiStart(mmcp->config->spip, mmcp->config->hscfg); + sync(mmcp); + + /* Synchronization operation finished.*/ + mmcp->state = BLK_READY; + return HAL_SUCCESS; +} + +/** + * @brief Returns the media info. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] bdip pointer to a @p BlockDeviceInfo structure + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) { + + osalDbgCheck((mmcp != NULL) && (bdip != NULL)); + + if (mmcp->state != BLK_READY) { + return HAL_FAILED; + } + + bdip->blk_num = mmcp->capacity; + bdip->blk_size = MMCSD_BLOCK_SIZE; + + return HAL_SUCCESS; +} + +/** + * @brief Erases blocks. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk starting block number + * @param[in] endblk ending block number + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) { + + osalDbgCheck((mmcp != NULL)); + + /* Erase operation in progress.*/ + mmcp->state = BLK_WRITING; + + /* Handling command differences between HC and normal cards.*/ + if (!mmcp->block_addresses) { + startblk *= MMCSD_BLOCK_SIZE; + endblk *= MMCSD_BLOCK_SIZE; + } + + if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk) != 0x00U) { + goto failed; + } + + if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk) != 0x00U) { + goto failed; + } + + if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0) != 0x00U) { + goto failed; + } + + mmcp->state = BLK_READY; + return HAL_SUCCESS; + + /* Command failed, state reset to BLK_ACTIVE.*/ +failed: + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return HAL_FAILED; +} + +#endif /* HAL_USE_MMC_SPI == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_pal.c b/os/hal/src/hal_pal.c new file mode 100644 index 000000000..f75e8d481 --- /dev/null +++ b/os/hal/src/hal_pal.c @@ -0,0 +1,122 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file pal.c + * @brief I/O Ports Abstraction Layer code. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Read from an I/O bus. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The function internally uses the @p palReadGroup() macro. The use + * of this function is preferred when you value code size, readability + * and error checking over speed. + * @note The function can be called from any context. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @return The bus logical states. + * + * @special + */ +ioportmask_t palReadBus(IOBus *bus) { + + osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); + + return palReadGroup(bus->portid, bus->mask, bus->offset); +} + +/** + * @brief Write to an I/O bus. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The function can be called from any context. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @param[in] bits the bits to be written on the I/O bus. Values exceeding + * the bus width are masked so most significant bits are + * lost. + * + * @special + */ +void palWriteBus(IOBus *bus, ioportmask_t bits) { + + osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); + + palWriteGroup(bus->portid, bus->mask, bus->offset, bits); +} + +/** + * @brief Programs a bus with the specified mode. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p osalSysLock() and + * @p osalSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The function can be called from any context. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @param[in] mode the mode + * + * @special + */ +void palSetBusMode(IOBus *bus, iomode_t mode) { + + osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); + + palSetGroupMode(bus->portid, bus->mask, bus->offset, mode); +} + +#endif /* HAL_USE_PAL == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_pwm.c b/os/hal/src/hal_pwm.c new file mode 100644 index 000000000..f74bf534c --- /dev/null +++ b/os/hal/src/hal_pwm.c @@ -0,0 +1,309 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file pwm.c + * @brief PWM Driver code. + * + * @addtogroup PWM + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief PWM Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void pwmInit(void) { + + pwm_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p PWMDriver structure. + * + * @param[out] pwmp pointer to a @p PWMDriver object + * + * @init + */ +void pwmObjectInit(PWMDriver *pwmp) { + + pwmp->state = PWM_STOP; + pwmp->config = NULL; + pwmp->enabled = 0; + pwmp->channels = 0; +#if defined(PWM_DRIVER_EXT_INIT_HOOK) + PWM_DRIVER_EXT_INIT_HOOK(pwmp); +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] config pointer to a @p PWMConfig object + * + * @api + */ +void pwmStart(PWMDriver *pwmp, const PWMConfig *config) { + + osalDbgCheck((pwmp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), + "invalid state"); + pwmp->config = config; + pwmp->period = config->period; + pwm_lld_start(pwmp); + pwmp->enabled = 0; + pwmp->state = PWM_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @api + */ +void pwmStop(PWMDriver *pwmp) { + + osalDbgCheck(pwmp != NULL); + + osalSysLock(); + osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), + "invalid state"); + pwm_lld_stop(pwmp); + pwmp->enabled = 0; + pwmp->state = PWM_STOP; + osalSysUnlock(); +} + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @api + */ +void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) { + + osalDbgCheck(pwmp != NULL); + + osalSysLock(); + osalDbgAssert(pwmp->state == PWM_READY, "invalid state"); + pwmChangePeriodI(pwmp, period); + osalSysUnlock(); +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @api + */ +void pwmEnableChannel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + + osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); + + osalSysLock(); + + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); + + pwmEnableChannelI(pwmp, channel, width); + + osalSysUnlock(); +} + +/** + * @brief Disables a PWM channel and its notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @api + */ +void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) { + + osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); + + osalSysLock(); + + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); + + pwmDisableChannelI(pwmp, channel); + + osalSysUnlock(); +} + +/** + * @brief Enables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @api + */ +void pwmEnablePeriodicNotification(PWMDriver *pwmp) { + + osalDbgCheck(pwmp != NULL); + + osalSysLock(); + + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); + osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback"); + + pwmEnablePeriodicNotificationI(pwmp); + + osalSysUnlock(); +} + +/** + * @brief Disables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @api + */ +void pwmDisablePeriodicNotification(PWMDriver *pwmp) { + + osalDbgCheck(pwmp != NULL); + + osalSysLock(); + + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); + osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback"); + + pwmDisablePeriodicNotificationI(pwmp); + + osalSysUnlock(); +} + +/** + * @brief Enables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @api + */ +void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) { + + osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); + + osalSysLock(); + + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); + osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U, + "channel not enabled"); + osalDbgAssert(pwmp->config->channels[channel].callback != NULL, + "undefined channel callback"); + + pwmEnableChannelNotificationI(pwmp, channel); + + osalSysUnlock(); +} + +/** + * @brief Disables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @api + */ +void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) { + + osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); + + osalSysLock(); + + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); + osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U, + "channel not enabled"); + osalDbgAssert(pwmp->config->channels[channel].callback != NULL, + "undefined channel callback"); + + pwmDisableChannelNotificationI(pwmp, channel); + + osalSysUnlock(); +} + +#endif /* HAL_USE_PWM == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_rtc.c b/os/hal/src/hal_rtc.c new file mode 100644 index 000000000..252bb7ab1 --- /dev/null +++ b/os/hal/src/hal_rtc.c @@ -0,0 +1,321 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file rtc.c + * @brief RTC Driver code. + * + * @addtogroup RTC + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* + * Lookup table with months' length + */ +static const uint8_t month_len[12] = { + 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief RTC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void rtcInit(void) { + + rtc_lld_init(); +} + +/** + * @brief Initializes a generic RTC driver object. + * @details The HW dependent part of the initialization has to be performed + * outside, usually in the hardware initialization code. + * + * @param[out] rtcp pointer to RTC driver structure + * + * @init + */ +void rtcObjectInit(RTCDriver *rtcp) { + +#if RTC_HAS_STORAGE == TRUE + rtcp->vmt = &_rtc_lld_vmt; +#else + (void)rtcp; +#endif +} + +/** + * @brief Set current time. + * @note This function can be called from any context but limitations + * could be imposed by the low level implementation. It is + * guaranteed that the function can be called from thread + * context. + * @note The function can be reentrant or not reentrant depending on + * the low level implementation. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] timespec pointer to a @p RTCDateTime structure + * + * @special + */ +void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec) { + + osalDbgCheck((rtcp != NULL) && (timespec != NULL)); + + rtc_lld_set_time(rtcp, timespec); +} + +/** + * @brief Get current time. + * @note This function can be called from any context but limitations + * could be imposed by the low level implementation. It is + * guaranteed that the function can be called from thread + * context. + * @note The function can be reentrant or not reentrant depending on + * the low level implementation. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @special + */ +void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec) { + + osalDbgCheck((rtcp != NULL) && (timespec != NULL)); + + rtc_lld_get_time(rtcp, timespec); +} + +#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) +/** + * @brief Set alarm time. + * @note This function can be called from any context but limitations + * could be imposed by the low level implementation. It is + * guaranteed that the function can be called from thread + * context. + * @note The function can be reentrant or not reentrant depending on + * the low level implementation. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[in] alarmspec pointer to a @p RTCAlarm structure or @p NULL + * + * @special + */ +void rtcSetAlarm(RTCDriver *rtcp, + rtcalarm_t alarm, + const RTCAlarm *alarmspec) { + + osalDbgCheck((rtcp != NULL) && (alarm < (rtcalarm_t)RTC_ALARMS)); + + rtc_lld_set_alarm(rtcp, alarm, alarmspec); +} + +/** + * @brief Get current alarm. + * @note If an alarm has not been set then the returned alarm specification + * is not meaningful. + * @note This function can be called from any context but limitations + * could be imposed by the low level implementation. It is + * guaranteed that the function can be called from thread + * context. + * @note The function can be reentrant or not reentrant depending on + * the low level implementation. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] alarm alarm identifier + * @param[out] alarmspec pointer to a @p RTCAlarm structure + * + * @special + */ +void rtcGetAlarm(RTCDriver *rtcp, + rtcalarm_t alarm, + RTCAlarm *alarmspec) { + + osalDbgCheck((rtcp != NULL) && + (alarm < (rtcalarm_t)RTC_ALARMS) && + (alarmspec != NULL)); + + rtc_lld_get_alarm(rtcp, alarm, alarmspec); +} +#endif /* RTC_ALARMS > 0 */ + +#if (RTC_SUPPORTS_CALLBACKS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Enables or disables RTC callbacks. + * @details This function enables or disables the callback, use a @p NULL + * pointer in order to disable it. + * @note This function can be called from any context but limitations + * could be imposed by the low level implementation. It is + * guaranteed that the function can be called from thread + * context. + * @note The function can be reentrant or not reentrant depending on + * the low level implementation. + * + * @param[in] rtcp pointer to RTC driver structure + * @param[in] callback callback function pointer or @p NULL + * + * @special + */ +void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) { + + osalDbgCheck(rtcp != NULL); + + rtc_lld_set_callback(rtcp, callback); +} +#endif /* RTC_SUPPORTS_CALLBACKS == TRUE */ + +/** + * @brief Convert @p RTCDateTime to broken-down time structure. + * + * @param[in] timespec pointer to a @p RTCDateTime structure + * @param[out] timp pointer to a broken-down time structure + * @param[out] tv_msec pointer to milliseconds value or @p NULL + * + * @api + */ +void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec, + struct tm *timp, + uint32_t *tv_msec) { + int sec; + + timp->tm_year = (int)timespec->year + (1980 - 1900); + timp->tm_mon = (int)timespec->month - 1; + timp->tm_mday = (int)timespec->day; + timp->tm_isdst = (int)timespec->dstflag; + timp->tm_wday = (int)timespec->dayofweek - 1; + + sec = (int)timespec->millisecond / 1000; + timp->tm_hour = sec / 3600; + sec %= 3600; + timp->tm_min = sec / 60; + timp->tm_sec = sec % 60; + + if (NULL != tv_msec) { + *tv_msec = (uint32_t)timespec->millisecond % 1000U; + } +} + +/** + * @brief Convert broken-down time structure to @p RTCDateTime. + * + * @param[in] timp pointer to a broken-down time structure + * @param[in] tv_msec milliseconds value + * @param[out] timespec pointer to a @p RTCDateTime structure + * + * @api + */ +void rtcConvertStructTmToDateTime(const struct tm *timp, + uint32_t tv_msec, + RTCDateTime *timespec) { + + /*lint -save -e9034 [10.4] Verified assignments to bit fields.*/ + timespec->year = (uint32_t)timp->tm_year - (1980U - 1900U); + timespec->month = (uint32_t)timp->tm_mon + 1U; + timespec->day = (uint32_t)timp->tm_mday; + timespec->dayofweek = (uint32_t)timp->tm_wday + 1U; + if (-1 == timp->tm_isdst) { + timespec->dstflag = 0U; /* set zero if dst is unknown */ + } + else { + timespec->dstflag = (uint32_t)timp->tm_isdst; + } + /*lint -restore*/ + /*lint -save -e9033 [10.8] Verified assignments to bit fields.*/ + timespec->millisecond = tv_msec + (uint32_t)(((timp->tm_hour * 3600) + + (timp->tm_min * 60) + + timp->tm_sec) * 1000); + /*lint -restore*/ +} + +/** + * @brief Get current time in format suitable for usage in FAT file system. + * @note The information about day of week and DST is lost in DOS + * format, the second field loses its least significant bit. + * + * @param[out] timespec pointer to a @p RTCDateTime structure + * @return FAT date/time value. + * + * @api + */ +uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec) { + uint32_t fattime; + uint32_t sec, min, hour, day, month; + + sec = timespec->millisecond / 1000U; + hour = sec / 3600U; + sec %= 3600U; + min = sec / 60U; + sec %= 60U; + day = timespec->day; + month = timespec->month; + + /* handle DST flag */ + if (1U == timespec->dstflag) { + hour += 1U; + if (hour == 24U) { + hour = 0U; + day += 1U; + if (day > month_len[month - 1U]) { + day = 1U; + month += 1U; + } + } + } + + fattime = sec >> 1U; + fattime |= min << 5U; + fattime |= hour << 11U; + fattime |= day << 16U; + fattime |= month << 21U; + fattime |= (uint32_t)timespec->year << 25U; + + return fattime; +} + +#endif /* HAL_USE_RTC == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_sdc.c b/os/hal/src/hal_sdc.c new file mode 100644 index 000000000..bd2c0bef6 --- /dev/null +++ b/os/hal/src/hal_sdc.c @@ -0,0 +1,1005 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file sdc.c + * @brief SDC Driver code. + * + * @addtogroup SDC + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/** + * @brief MMC switch mode. + */ +typedef enum { + MMC_SWITCH_COMMAND_SET = 0, + MMC_SWITCH_SET_BITS = 1, + MMC_SWITCH_CLEAR_BITS = 2, + MMC_SWITCH_WRITE_BYTE = 3 +} mmc_switch_t; + +/** + * @brief SDC switch mode. + */ +typedef enum { + SD_SWITCH_CHECK = 0, + SD_SWITCH_SET = 1 +} sd_switch_t; + +/** + * @brief SDC switch function. + */ +typedef enum { + SD_SWITCH_FUNCTION_SPEED = 0, + SD_SWITCH_FUNCTION_CMD_SYSTEM = 1, + SD_SWITCH_FUNCTION_DRIVER_STRENGTH = 2, + SD_SWITCH_FUNCTION_CURRENT_LIMIT = 3 +} sd_switch_function_t; + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Virtual methods table. + */ +static const struct SDCDriverVMT sdc_vmt = { + (bool (*)(void *))sdc_lld_is_card_inserted, + (bool (*)(void *))sdc_lld_is_write_protected, + (bool (*)(void *))sdcConnect, + (bool (*)(void *))sdcDisconnect, + (bool (*)(void *, uint32_t, uint8_t *, uint32_t))sdcRead, + (bool (*)(void *, uint32_t, const uint8_t *, uint32_t))sdcWrite, + (bool (*)(void *))sdcSync, + (bool (*)(void *, BlockDeviceInfo *))sdcGetInfo +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ +/** + * @brief Detects card mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool mode_detect(SDCDriver *sdcp) { + uint32_t resp[1]; + + /* V2.0 cards detection.*/ + if (!sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_IF_COND, + MMCSD_CMD8_PATTERN, resp)) { + sdcp->cardmode = SDC_MODE_CARDTYPE_SDV20; + /* Voltage verification.*/ + if (((resp[0] >> 8U) & 0xFU) != 1U) { + return HAL_FAILED; + } + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || + MMCSD_R1_ERROR(resp[0])) { + return HAL_FAILED; + } + } + else { + /* MMC or SD V1.1 detection.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || + MMCSD_R1_ERROR(resp[0])) { + sdcp->cardmode = SDC_MODE_CARDTYPE_MMC; + } + else { + sdcp->cardmode = SDC_MODE_CARDTYPE_SDV11; + + /* Reset error flag illegal command.*/ + sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); + } + } + + return HAL_SUCCESS; +} + +/** + * @brief Init procedure for MMC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool mmc_init(SDCDriver *sdcp) { + uint32_t ocr; + unsigned i; + uint32_t resp[1]; + + ocr = 0xC0FF8000U; + i = 0; + while (true) { + if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_INIT, ocr, resp)) { + return HAL_FAILED; + } + if ((resp[0] & 0x80000000U) != 0U) { + if ((resp[0] & 0x40000000U) != 0U) { + sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY; + } + break; + } + if (++i >= (unsigned)SDC_INIT_RETRY) { + return HAL_FAILED; + } + osalThreadSleepMilliseconds(10); + } + + return HAL_SUCCESS; +} + +/** + * @brief Init procedure for SDC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_init(SDCDriver *sdcp) { + unsigned i; + uint32_t ocr; + uint32_t resp[1]; + + if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_SDV20) { + ocr = 0xC0100000U; + } + else { + ocr = 0x80100000U; + } + + i = 0; + while (true) { + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || + MMCSD_R1_ERROR(resp[0])) { + return HAL_FAILED; + } + if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_APP_OP_COND, ocr, resp)) { + return HAL_FAILED; + } + if ((resp[0] & 0x80000000U) != 0U) { + if ((resp[0] & 0x40000000U) != 0U) { + sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY; + } + break; + } + if (++i >= (unsigned)SDC_INIT_RETRY) { + return HAL_FAILED; + } + osalThreadSleepMilliseconds(10); + } + + return HAL_SUCCESS; +} + +/** + * @brief Constructs CMD6 argument for MMC. + * + * @param[in] access EXT_CSD access mode + * @param[in] idx EXT_CSD byte number + * @param[in] value value to be written in target field + * @param[in] cmd_set switch current command set + * + * @return CMD6 argument. + * + * @notapi + */ +static uint32_t mmc_cmd6_construct(mmc_switch_t access, uint32_t idx, + uint32_t value, uint32_t cmd_set) { + + osalDbgAssert(idx <= 191U, "This field is not writable"); + osalDbgAssert(cmd_set < 8U, "This field has only 3 bits"); + + return ((uint32_t)access << 24U) | (idx << 16U) | (value << 8U) | cmd_set; +} + +/** + * @brief Constructs CMD6 argument for SDC. + * + * @param[in] mode switch/test mode + * @param[in] function function number to be switched + * @param[in] value value to be written in target function + * + * @return CMD6 argument. + * + * @notapi + */ +static uint32_t sdc_cmd6_construct(sd_switch_t mode, + sd_switch_function_t function, + uint32_t value) { + uint32_t ret = 0xFFFFFF; + + osalDbgAssert((value < 16U), "This field has only 4 bits"); + + ret &= ~((uint32_t)0xFU << ((uint32_t)function * 4U)); + ret |= value << ((uint32_t)function * 4U); + return ret | ((uint32_t)mode << 31U); +} + +/** + * @brief Extracts information from CMD6 answer. + * + * @param[in] function function number to be switched + * @param[in] buf buffer with answer + * + * @return extracted answer. + * + * @notapi + */ +static uint16_t sdc_cmd6_extract_info(sd_switch_function_t function, + const uint8_t *buf) { + + unsigned start = 12U - ((unsigned)function * 2U); + + return ((uint16_t)buf[start] << 8U) | (uint16_t)buf[start + 1U]; +} + +/** + * @brief Checks status after switching using CMD6. + * + * @param[in] function function number to be switched + * @param[in] buf buffer with answer + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_cmd6_check_status(sd_switch_function_t function, + const uint8_t *buf) { + + uint32_t tmp; + uint32_t status; + + tmp = ((uint32_t)buf[14] << 16U) | + ((uint32_t)buf[15] << 8U) | + (uint32_t)buf[16]; + status = (tmp >> ((uint32_t)function * 4U)) & 0xFU; + if (0xFU != status) { + return HAL_SUCCESS; + } + return HAL_FAILED; +} + +/** + * @brief Reads supported bus clock and switch SDC to appropriate mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] clk pointer to clock enum + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) { + uint32_t cmdarg; + const size_t N = 64; + uint8_t tmp[N]; + + /* Safe default.*/ + *clk = SDC_CLK_25MHz; + + /* Looks like only "high capacity" cards produce meaningful results during + this clock detection procedure.*/ + if (0U == _mmcsd_get_slice(sdcp->csd, MMCSD_CSD_10_CSD_STRUCTURE_SLICE)) { + *clk = SDC_CLK_25MHz; + return HAL_SUCCESS; + } + + /* Read switch functions' register.*/ + if (sdc_lld_read_special(sdcp, tmp, N, MMCSD_CMD_SWITCH, 0)) { + return HAL_FAILED; + } + + /* Check card capabilities parsing acquired data.*/ + if ((sdc_cmd6_extract_info(SD_SWITCH_FUNCTION_SPEED, tmp) & 2U) == 2U) { + /* Construct command to set the bus speed.*/ + cmdarg = sdc_cmd6_construct(SD_SWITCH_SET, SD_SWITCH_FUNCTION_SPEED, 1); + + /* Write constructed command and read operation status in single call.*/ + if (sdc_lld_read_special(sdcp, tmp, N, MMCSD_CMD_SWITCH, cmdarg)) { + return HAL_FAILED; + } + + /* Check card answer for success status bits.*/ + if (HAL_SUCCESS == sdc_cmd6_check_status(SD_SWITCH_FUNCTION_SPEED, tmp)) { + *clk = SDC_CLK_50MHz; + } + else { + *clk = SDC_CLK_25MHz; + } + } + + return HAL_SUCCESS; +} + +/** + * @brief Reads supported bus clock and switch MMC to appropriate mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] clk pointer to clock enum + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool mmc_detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) { + uint32_t cmdarg; + uint32_t resp[1]; + uint8_t *scratchpad = sdcp->config->scratchpad; + + /* Safe default.*/ + *clk = SDC_CLK_25MHz; + + /* Use safe default when there is no space for data.*/ + if (NULL == scratchpad) { + return HAL_SUCCESS; + } + + cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 185, 1, 0); + if (!(sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SWITCH, cmdarg, resp) || + MMCSD_R1_ERROR(resp[0]))) { + *clk = SDC_CLK_50MHz; + } + + return HAL_SUCCESS; +} + +/** + * @brief Reads supported bus clock and switch card to appropriate mode. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] clk pointer to clock enum + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) { + + if (SDC_MODE_CARDTYPE_MMC == (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK)) { + return mmc_detect_bus_clk(sdcp, clk); + } + return sdc_detect_bus_clk(sdcp, clk); +} + +/** + * @brief Sets bus width for SDC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool sdc_set_bus_width(SDCDriver *sdcp) { + uint32_t resp[1]; + + if (SDC_MODE_1BIT == sdcp->config->bus_width) { + /* Nothing to do. Bus is already in 1bit mode.*/ + return HAL_SUCCESS; + } + else if (SDC_MODE_4BIT == sdcp->config->bus_width) { + sdc_lld_set_bus_mode(sdcp, SDC_MODE_4BIT); + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, sdcp->rca, resp) || + MMCSD_R1_ERROR(resp[0])) { + return HAL_FAILED; + } + + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BUS_WIDTH, 2, resp) || + MMCSD_R1_ERROR(resp[0])) { + return HAL_FAILED; + } + } + else { + /* SD card does not support 8bit bus.*/ + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Sets bus width for MMC. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +static bool mmc_set_bus_width(SDCDriver *sdcp) { + uint32_t resp[1]; + uint32_t cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 0, 0); + + switch(sdcp->config->bus_width){ + case SDC_MODE_1BIT: + /* Nothing to do. Bus is already in 1bit mode.*/ + return HAL_SUCCESS; + case SDC_MODE_4BIT: + cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 1, 0); + break; + case SDC_MODE_8BIT: + cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 2, 0); + break; + default: + osalDbgAssert(false, "unexpected case"); + break; + } + + sdc_lld_set_bus_mode(sdcp, sdcp->config->bus_width); + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SWITCH, cmdarg, resp) || + MMCSD_R1_ERROR(resp[0])) { + return HAL_FAILED; + } + + return HAL_SUCCESS; +} + +/** + * @brief Wait for the card to complete pending operations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool _sdc_wait_for_transfer_state(SDCDriver *sdcp) { + uint32_t resp[1]; + + while (true) { + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_STATUS, + sdcp->rca, resp) || + MMCSD_R1_ERROR(resp[0])) { + return HAL_FAILED; + } + + switch (MMCSD_R1_STS(resp[0])) { + case MMCSD_STS_TRAN: + return HAL_SUCCESS; + case MMCSD_STS_DATA: + case MMCSD_STS_RCV: + case MMCSD_STS_PRG: +#if SDC_NICE_WAITING == TRUE + osalThreadSleepMilliseconds(1); +#endif + continue; + default: + /* The card should have been initialized so any other state is not + valid and is reported as an error.*/ + return HAL_FAILED; + } + } +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief SDC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sdcInit(void) { + + sdc_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p SDCDriver structure. + * + * @param[out] sdcp pointer to the @p SDCDriver object + * + * @init + */ +void sdcObjectInit(SDCDriver *sdcp) { + + sdcp->vmt = &sdc_vmt; + sdcp->state = BLK_STOP; + sdcp->errors = SDC_NO_ERROR; + sdcp->config = NULL; + sdcp->capacity = 0; +} + +/** + * @brief Configures and activates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] config pointer to the @p SDCConfig object, can be @p NULL if + * the driver supports a default configuration or + * requires no configuration + * + * @api + */ +void sdcStart(SDCDriver *sdcp, const SDCConfig *config) { + + osalDbgCheck(sdcp != NULL); + + osalSysLock(); + osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), + "invalid state"); + sdcp->config = config; + sdc_lld_start(sdcp); + sdcp->state = BLK_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @api + */ +void sdcStop(SDCDriver *sdcp) { + + osalDbgCheck(sdcp != NULL); + + osalSysLock(); + osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), + "invalid state"); + sdc_lld_stop(sdcp); + sdcp->state = BLK_STOP; + osalSysUnlock(); +} + +/** + * @brief Performs the initialization procedure on the inserted card. + * @details This function should be invoked when a card is inserted and + * brings the driver in the @p BLK_READY state where it is possible + * to perform read and write operations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcConnect(SDCDriver *sdcp) { + uint32_t resp[1]; + sdcbusclk_t clk = SDC_CLK_25MHz; + + osalDbgCheck(sdcp != NULL); + osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), + "invalid state"); + + /* Connection procedure in progress.*/ + sdcp->state = BLK_CONNECTING; + + /* Card clock initialization.*/ + sdc_lld_start_clk(sdcp); + + /* Enforces the initial card state.*/ + sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); + + /* Detect card type.*/ + if (HAL_FAILED == mode_detect(sdcp)) { + goto failed; + } + + /* Perform specific initialization procedure.*/ + if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) { + if (HAL_FAILED == mmc_init(sdcp)) { + goto failed; + } + } + else { + if (HAL_FAILED == sdc_init(sdcp)) { + goto failed; + } + } + + /* Reads CID.*/ + if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_ALL_SEND_CID, 0, sdcp->cid)) { + goto failed; + } + + /* Asks for the RCA.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_RELATIVE_ADDR, + 0, &sdcp->rca)) { + goto failed; + } + + /* Reads CSD.*/ + if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_SEND_CSD, + sdcp->rca, sdcp->csd)) { + goto failed; + } + + /* Selects the card for operations.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEL_DESEL_CARD, + sdcp->rca, resp)) { + goto failed; + } + + /* Switches to high speed.*/ + if (HAL_SUCCESS != detect_bus_clk(sdcp, &clk)) { + goto failed; + } + sdc_lld_set_data_clk(sdcp, clk); + + /* Reads extended CSD if needed and possible.*/ + if (SDC_MODE_CARDTYPE_MMC == (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK)) { + + /* The card is a MMC, checking if it is a large device.*/ + if (_mmcsd_get_slice(sdcp->csd, MMCSD_CSD_MMC_CSD_STRUCTURE_SLICE) > 1U) { + uint8_t *ext_csd = sdcp->config->scratchpad; + + /* Size detection requires the buffer.*/ + if (NULL == ext_csd) { + goto failed; + } + + if(sdc_lld_read_special(sdcp, ext_csd, 512, MMCSD_CMD_SEND_EXT_CSD, 0)) { + goto failed; + } + + /* Capacity from the EXT_CSD.*/ + sdcp->capacity = _mmcsd_get_capacity_ext(ext_csd); + } + else { + /* Capacity from the normal CSD.*/ + sdcp->capacity = _mmcsd_get_capacity(sdcp->csd); + } + } + else { + /* The card is an SDC, capacity from the normal CSD.*/ + sdcp->capacity = _mmcsd_get_capacity(sdcp->csd); + } + + /* Block length fixed at 512 bytes.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BLOCKLEN, + MMCSD_BLOCK_SIZE, resp) || + MMCSD_R1_ERROR(resp[0])) { + goto failed; + } + + /* Switches to wide bus mode.*/ + switch (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) { + case SDC_MODE_CARDTYPE_SDV11: + case SDC_MODE_CARDTYPE_SDV20: + if (HAL_FAILED == sdc_set_bus_width(sdcp)) { + goto failed; + } + break; + case SDC_MODE_CARDTYPE_MMC: + if (HAL_FAILED == mmc_set_bus_width(sdcp)) { + goto failed; + } + break; + default: + /* Unknown type.*/ + goto failed; + } + + /* Initialization complete.*/ + sdcp->state = BLK_READY; + return HAL_SUCCESS; + + /* Connection failed, state reset to BLK_ACTIVE.*/ +failed: + sdc_lld_stop_clk(sdcp); + sdcp->state = BLK_ACTIVE; + return HAL_FAILED; +} + +/** + * @brief Brings the driver in a state safe for card removal. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcDisconnect(SDCDriver *sdcp) { + + osalDbgCheck(sdcp != NULL); + + osalSysLock(); + osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), + "invalid state"); + if (sdcp->state == BLK_ACTIVE) { + osalSysUnlock(); + return HAL_SUCCESS; + } + sdcp->state = BLK_DISCONNECTING; + osalSysUnlock(); + + /* Waits for eventual pending operations completion.*/ + if (_sdc_wait_for_transfer_state(sdcp)) { + sdc_lld_stop_clk(sdcp); + sdcp->state = BLK_ACTIVE; + return HAL_FAILED; + } + + /* Card clock stopped.*/ + sdc_lld_stop_clk(sdcp); + sdcp->state = BLK_ACTIVE; + return HAL_SUCCESS; +} + +/** + * @brief Reads one or more blocks. + * @pre The driver must be in the @p BLK_READY state after a successful + * sdcConnect() invocation. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] n number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcRead(SDCDriver *sdcp, uint32_t startblk, uint8_t *buf, uint32_t n) { + bool status; + + osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0U)); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + if ((startblk + n - 1U) > sdcp->capacity){ + sdcp->errors |= SDC_OVERFLOW_ERROR; + return HAL_FAILED; + } + + /* Read operation in progress.*/ + sdcp->state = BLK_READING; + + status = sdc_lld_read(sdcp, startblk, buf, n); + + /* Read operation finished.*/ + sdcp->state = BLK_READY; + return status; +} + +/** + * @brief Writes one or more blocks. + * @pre The driver must be in the @p BLK_READY state after a successful + * sdcConnect() invocation. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcWrite(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t n) { + bool status; + + osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0U)); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + if ((startblk + n - 1U) > sdcp->capacity){ + sdcp->errors |= SDC_OVERFLOW_ERROR; + return HAL_FAILED; + } + + /* Write operation in progress.*/ + sdcp->state = BLK_WRITING; + + status = sdc_lld_write(sdcp, startblk, buf, n); + + /* Write operation finished.*/ + sdcp->state = BLK_READY; + return status; +} + +/** + * @brief Returns the errors mask associated to the previous operation. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @return The errors mask. + * + * @api + */ +sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp) { + sdcflags_t flags; + + osalDbgCheck(sdcp != NULL); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + osalSysLock(); + flags = sdcp->errors; + sdcp->errors = SDC_NO_ERROR; + osalSysUnlock(); + return flags; +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdcSync(SDCDriver *sdcp) { + bool result; + + osalDbgCheck(sdcp != NULL); + + if (sdcp->state != BLK_READY) { + return HAL_FAILED; + } + + /* Synchronization operation in progress.*/ + sdcp->state = BLK_SYNCING; + + result = sdc_lld_sync(sdcp); + + /* Synchronization operation finished.*/ + sdcp->state = BLK_READY; + return result; +} + +/** + * @brief Returns the media info. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] bdip pointer to a @p BlockDeviceInfo structure + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) { + + osalDbgCheck((sdcp != NULL) && (bdip != NULL)); + + if (sdcp->state != BLK_READY) { + return HAL_FAILED; + } + + bdip->blk_num = sdcp->capacity; + bdip->blk_size = MMCSD_BLOCK_SIZE; + + return HAL_SUCCESS; +} + +/** + * @brief Erases the supplied blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk starting block number + * @param[in] endblk ending block number + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) { + uint32_t resp[1]; + + osalDbgCheck((sdcp != NULL)); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + /* Erase operation in progress.*/ + sdcp->state = BLK_WRITING; + + /* Handling command differences between HC and normal cards.*/ + if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) != 0U) { + startblk *= MMCSD_BLOCK_SIZE; + endblk *= MMCSD_BLOCK_SIZE; + } + + if (_sdc_wait_for_transfer_state(sdcp)) { + goto failed; + } + + if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_START, + startblk, resp) != HAL_SUCCESS) || + MMCSD_R1_ERROR(resp[0])) { + goto failed; + } + + if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_END, + endblk, resp) != HAL_SUCCESS) || + MMCSD_R1_ERROR(resp[0])) { + goto failed; + } + + if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE, + 0, resp) != HAL_SUCCESS) || + MMCSD_R1_ERROR(resp[0])) { + goto failed; + } + + /* Quick sleep to allow it to transition to programming or receiving state */ + /* TODO: ??????????????????????????? */ + + /* Wait for it to return to transfer state to indicate it has finished erasing */ + if (_sdc_wait_for_transfer_state(sdcp)) { + goto failed; + } + + sdcp->state = BLK_READY; + return HAL_SUCCESS; + +failed: + sdcp->state = BLK_READY; + return HAL_FAILED; +} + +#endif /* HAL_USE_SDC == TRUE */ + +/** @} */ + diff --git a/os/hal/src/hal_serial.c b/os/hal/src/hal_serial.c new file mode 100644 index 000000000..a0956ba9a --- /dev/null +++ b/os/hal/src/hal_serial.c @@ -0,0 +1,289 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file serial.c + * @brief Serial Driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/* + * Interface implementation, the following functions just invoke the equivalent + * queue-level function or macro. + */ + +static size_t write(void *ip, const uint8_t *bp, size_t n) { + + return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, + n, TIME_INFINITE); +} + +static size_t read(void *ip, uint8_t *bp, size_t n) { + + return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, + n, TIME_INFINITE); +} + +static msg_t put(void *ip, uint8_t b) { + + return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, TIME_INFINITE); +} + +static msg_t get(void *ip) { + + return iqGetTimeout(&((SerialDriver *)ip)->iqueue, TIME_INFINITE); +} + +static msg_t putt(void *ip, uint8_t b, systime_t timeout) { + + return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout); +} + +static msg_t gett(void *ip, systime_t timeout) { + + return iqGetTimeout(&((SerialDriver *)ip)->iqueue, timeout); +} + +static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) { + + return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, timeout); +} + +static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) { + + return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, timeout); +} + +static const struct SerialDriverVMT vmt = { + write, read, put, get, + putt, gett, writet, readt +}; + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Serial Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sdInit(void) { + + sd_lld_init(); +} + +/** + * @brief Initializes a generic full duplex driver object. + * @details The HW dependent part of the initialization has to be performed + * outside, usually in the hardware initialization code. + * + * @param[out] sdp pointer to a @p SerialDriver structure + * @param[in] inotify pointer to a callback function that is invoked when + * some data is read from the Queue. The value can be + * @p NULL. + * @param[in] onotify pointer to a callback function that is invoked when + * some data is written in the Queue. The value can be + * @p NULL. + * + * @init + */ +void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { + + sdp->vmt = &vmt; + osalEventObjectInit(&sdp->event); + sdp->state = SD_STOP; + iqObjectInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); + oqObjectInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); +} + +/** + * @brief Configures and starts the driver. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @api + */ +void sdStart(SerialDriver *sdp, const SerialConfig *config) { + + osalDbgCheck(sdp != NULL); + + osalSysLock(); + osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), + "invalid state"); + sd_lld_start(sdp, config); + sdp->state = SD_READY; + osalSysUnlock(); +} + +/** + * @brief Stops the driver. + * @details Any thread waiting on the driver's queues will be awakened with + * the message @p MSG_RESET. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @api + */ +void sdStop(SerialDriver *sdp) { + + osalDbgCheck(sdp != NULL); + + osalSysLock(); + osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), + "invalid state"); + sd_lld_stop(sdp); + sdp->state = SD_STOP; + oqResetI(&sdp->oqueue); + iqResetI(&sdp->iqueue); + osalOsRescheduleS(); + osalSysUnlock(); +} + +/** + * @brief Handles incoming data. + * @details This function must be called from the input interrupt service + * routine in order to enqueue incoming data and generate the + * related events. + * @note The incoming data event is only generated when the input queue + * becomes non-empty. + * @note In order to gain some performance it is suggested to not use + * this function directly but copy this code directly into the + * interrupt service routine. + * + * @param[in] sdp pointer to a @p SerialDriver structure + * @param[in] b the byte to be written in the driver's Input Queue + * + * @iclass + */ +void sdIncomingDataI(SerialDriver *sdp, uint8_t b) { + + osalDbgCheckClassI(); + osalDbgCheck(sdp != NULL); + + if (iqIsEmptyI(&sdp->iqueue)) + chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE); + if (iqPutI(&sdp->iqueue, b) < MSG_OK) + chnAddFlagsI(sdp, SD_OVERRUN_ERROR); +} + +/** + * @brief Handles outgoing data. + * @details Must be called from the output interrupt service routine in order + * to get the next byte to be transmitted. + * @note In order to gain some performance it is suggested to not use + * this function directly but copy this code directly into the + * interrupt service routine. + * + * @param[in] sdp pointer to a @p SerialDriver structure + * @return The byte value read from the driver's output queue. + * @retval MSG_TIMEOUT if the queue is empty (the lower driver usually + * disables the interrupt source when this happens). + * + * @iclass + */ +msg_t sdRequestDataI(SerialDriver *sdp) { + msg_t b; + + osalDbgCheckClassI(); + osalDbgCheck(sdp != NULL); + + b = oqGetI(&sdp->oqueue); + if (b < MSG_OK) + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + return b; +} + +/** + * @brief Direct output check on a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * checks directly the output queue. This is faster but cannot + * be used to check different channels implementations. + * + * @param[in] sdp pointer to a @p SerialDriver structure + * @return The queue status. + * @retval false if the next write operation would not block. + * @retval true if the next write operation would block. + * + * @deprecated + * + * @api + */ +bool sdPutWouldBlock(SerialDriver *sdp) { + bool b; + + osalSysLock(); + b = oqIsFullI(&sdp->oqueue); + osalSysUnlock(); + + return b; +} + +/** + * @brief Direct input check on a @p SerialDriver. + * @note This function bypasses the indirect access to the channel and + * checks directly the input queue. This is faster but cannot + * be used to check different channels implementations. + * + * @param[in] sdp pointer to a @p SerialDriver structure + * @return The queue status. + * @retval false if the next write operation would not block. + * @retval true if the next write operation would block. + * + * @deprecated + * + * @api + */ +bool sdGetWouldBlock(SerialDriver *sdp) { + bool b; + + osalSysLock(); + b = iqIsEmptyI(&sdp->iqueue); + osalSysUnlock(); + + return b; +} + +#endif /* HAL_USE_SERIAL == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_serial_usb.c b/os/hal/src/hal_serial_usb.c new file mode 100644 index 000000000..9c21f7b56 --- /dev/null +++ b/os/hal/src/hal_serial_usb.c @@ -0,0 +1,502 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file serial_usb.c + * @brief Serial over USB Driver code. + * + * @addtogroup SERIAL_USB + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* + * Current Line Coding. + */ +static cdc_linecoding_t linecoding = { + {0x00, 0x96, 0x00, 0x00}, /* 38400. */ + LC_STOP_1, LC_PARITY_NONE, 8 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/* + * Interface implementation. + */ + +static size_t write(void *ip, const uint8_t *bp, size_t n) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return 0; + } + + return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp, + n, TIME_INFINITE); +} + +static size_t read(void *ip, uint8_t *bp, size_t n) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return 0; + } + + return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp, + n, TIME_INFINITE); +} + +static msg_t put(void *ip, uint8_t b) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return MSG_RESET; + } + + return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, TIME_INFINITE); +} + +static msg_t get(void *ip) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return MSG_RESET; + } + + return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, TIME_INFINITE); +} + +static msg_t putt(void *ip, uint8_t b, systime_t timeout) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return MSG_RESET; + } + + return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, timeout); +} + +static msg_t gett(void *ip, systime_t timeout) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return MSG_RESET; + } + + return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, timeout); +} + +static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return 0; + } + + return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp, n, timeout); +} + +static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) { + + if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { + return 0; + } + + return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp, n, timeout); +} + +static const struct SerialUSBDriverVMT vmt = { + write, read, put, get, + putt, gett, writet, readt +}; + +/** + * @brief Notification of empty buffer released into the input buffers queue. + * + * @param[in] bqp the buffers queue pointer. + */ +static void ibnotify(io_buffers_queue_t *bqp) { + SerialUSBDriver *sdup = bqGetLinkX(bqp); + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) { + return; + } + + /* Checking if there is already a transaction ongoing on the endpoint.*/ + if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) { + /* Trying to get a free buffer.*/ + uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue); + if (buf != NULL) { + /* Buffer found, starting a new transaction.*/ + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); + } + } +} + +/** + * @brief Notification of filled buffer inserted into the output buffers queue. + * + * @param[in] bqp the buffers queue pointer. + */ +static void obnotify(io_buffers_queue_t *bqp) { + size_t n; + SerialUSBDriver *sdup = bqGetLinkX(bqp); + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) { + return; + } + + /* Checking if there is already a transaction ongoing on the endpoint.*/ + if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) { + /* Trying to get a full buffer.*/ + uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n); + if (buf != NULL) { + /* Buffer found, starting a new transaction.*/ + usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n); + } + } +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Serial Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sduInit(void) { +} + +/** + * @brief Initializes a generic full duplex driver object. + * @details The HW dependent part of the initialization has to be performed + * outside, usually in the hardware initialization code. + * + * @param[out] sdup pointer to a @p SerialUSBDriver structure + * + * @init + */ +void sduObjectInit(SerialUSBDriver *sdup) { + + sdup->vmt = &vmt; + osalEventObjectInit(&sdup->event); + sdup->state = SDU_STOP; + ibqObjectInit(&sdup->ibqueue, sdup->ib, + SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER, + ibnotify, sdup); + obqObjectInit(&sdup->obqueue, sdup->ob, + SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER, + obnotify, sdup); +} + +/** + * @brief Configures and starts the driver. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * @param[in] config the serial over USB driver configuration + * + * @api + */ +void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { + USBDriver *usbp = config->usbp; + + osalDbgCheck(sdup != NULL); + + osalSysLock(); + osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), + "invalid state"); + usbp->in_params[config->bulk_in - 1U] = sdup; + usbp->out_params[config->bulk_out - 1U] = sdup; + if (config->int_in > 0U) { + usbp->in_params[config->int_in - 1U] = sdup; + } + sdup->config = config; + sdup->state = SDU_READY; + osalSysUnlock(); +} + +/** + * @brief Stops the driver. + * @details Any thread waiting on the driver's queues will be awakened with + * the message @p MSG_RESET. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @api + */ +void sduStop(SerialUSBDriver *sdup) { + USBDriver *usbp = sdup->config->usbp; + + osalDbgCheck(sdup != NULL); + + osalSysLock(); + osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), + "invalid state"); + + /* Driver in stopped state.*/ + usbp->in_params[sdup->config->bulk_in - 1U] = NULL; + usbp->out_params[sdup->config->bulk_out - 1U] = NULL; + if (sdup->config->int_in > 0U) { + usbp->in_params[sdup->config->int_in - 1U] = NULL; + } + sdup->state = SDU_STOP; + + /* Enforces a disconnection.*/ + sduDisconnectI(sdup); + osalOsRescheduleS(); + osalSysUnlock(); +} + +/** + * @brief USB device disconnection handler. + * @note If this function is not called from an ISR then an explicit call + * to @p osalOsRescheduleS() in necessary afterward. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @iclass + */ +void sduDisconnectI(SerialUSBDriver *sdup) { + + /* Queues reset in order to signal the driver stop to the application.*/ + chnAddFlagsI(sdup, CHN_DISCONNECTED); + ibqResetI(&sdup->ibqueue); + obqResetI(&sdup->obqueue); +} + +/** + * @brief USB device configured handler. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @iclass + */ +void sduConfigureHookI(SerialUSBDriver *sdup) { + uint8_t *buf; + + ibqResetI(&sdup->ibqueue); + obqResetI(&sdup->obqueue); + chnAddFlagsI(sdup, CHN_CONNECTED); + + /* Starts the first OUT transaction immediately.*/ + buf = ibqGetEmptyBufferI(&sdup->ibqueue); + + osalDbgAssert(buf != NULL, "no free buffer"); + + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); +} + +/** + * @brief Default requests hook. + * @details Applications wanting to use the Serial over USB driver can use + * this function as requests hook in the USB configuration. + * The following requests are emulated: + * - CDC_GET_LINE_CODING. + * - CDC_SET_LINE_CODING. + * - CDC_SET_CONTROL_LINE_STATE. + * . + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The hook status. + * @retval true Message handled internally. + * @retval false Message not handled. + */ +bool sduRequestsHook(USBDriver *usbp) { + + if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { + switch (usbp->setup[1]) { + case CDC_GET_LINE_CODING: + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + return true; + case CDC_SET_LINE_CODING: + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + return true; + case CDC_SET_CONTROL_LINE_STATE: + /* Nothing to do, there are no control lines.*/ + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + default: + return false; + } + } + return false; +} + +/** + * @brief SOF handler. + * @details The SOF interrupt is used for automatic flushing of incomplete + * buffers pending in the output queue. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @iclass + */ +void sduSOFHookI(SerialUSBDriver *sdup) { + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) { + return; + } + + /* If there is already a transaction ongoing then another one cannot be + started.*/ + if (usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) { + return; + } + + /* Checking if there only a buffer partially filled, if so then it is + enforced in the queue and transmitted.*/ + if (obqTryFlushI(&sdup->obqueue)) { + size_t n; + uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n); + + osalDbgAssert(buf != NULL, "queue is empty"); + + usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n); + } +} + +/** + * @brief Default data transmitted callback. + * @details The application must use this function as callback for the IN + * data endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep IN endpoint number + */ +void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { + uint8_t *buf; + size_t n; + SerialUSBDriver *sdup = usbp->in_params[ep - 1U]; + + if (sdup == NULL) { + return; + } + + osalSysLockFromISR(); + + /* Signaling that space is available in the output queue.*/ + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); + + /* Freeing the buffer just transmitted, if it was not a zero size packet.*/ + if (usbp->epc[ep]->in_state->txsize > 0U) { + obqReleaseEmptyBufferI(&sdup->obqueue); + } + + /* Checking if there is a buffer ready for transmission.*/ + buf = obqGetFullBufferI(&sdup->obqueue, &n); + + if (buf != NULL) { + /* The endpoint cannot be busy, we are in the context of the callback, + so it is safe to transmit without a check.*/ + usbStartTransmitI(usbp, ep, buf, n); + } + else if ((usbp->epc[ep]->in_state->txsize > 0U) && + ((usbp->epc[ep]->in_state->txsize & + ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) { + /* Transmit zero sized packet in case the last one has maximum allowed + size. Otherwise the recipient may expect more data coming soon and + not return buffered data to app. See section 5.8.3 Bulk Transfer + Packet Size Constraints of the USB Specification document.*/ + usbStartTransmitI(usbp, ep, usbp->setup, 0); + + } + else { + /* Nothing to transmit.*/ + } + + osalSysUnlockFromISR(); +} + +/** + * @brief Default data received callback. + * @details The application must use this function as callback for the OUT + * data endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep OUT endpoint number + */ +void sduDataReceived(USBDriver *usbp, usbep_t ep) { + uint8_t *buf; + SerialUSBDriver *sdup = usbp->out_params[ep - 1U]; + + if (sdup == NULL) { + return; + } + + osalSysLockFromISR(); + + /* Signaling that data is available in the input queue.*/ + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); + + /* Posting the filled buffer in the queue.*/ + ibqPostFullBufferI(&sdup->ibqueue, + usbGetReceiveTransactionSizeX(sdup->config->usbp, + sdup->config->bulk_out)); + + /* The endpoint cannot be busy, we are in the context of the callback, + so a packet is in the buffer for sure. Trying to get a free buffer + for the next transaction.*/ + buf = ibqGetEmptyBufferI(&sdup->ibqueue); + if (buf != NULL) { + /* Buffer found, starting a new transaction.*/ + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); + } + osalSysUnlockFromISR(); +} + +/** + * @brief Default data received callback. + * @details The application must use this function as callback for the IN + * interrupt endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + */ +void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + (void)ep; +} + +#endif /* HAL_USE_SERIAL_USB == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_spi.c b/os/hal/src/hal_spi.c new file mode 100644 index 000000000..90907e8f4 --- /dev/null +++ b/os/hal/src/hal_spi.c @@ -0,0 +1,416 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file spi.c + * @brief SPI Driver code. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief SPI Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void spiInit(void) { + + spi_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p SPIDriver structure. + * + * @param[out] spip pointer to the @p SPIDriver object + * + * @init + */ +void spiObjectInit(SPIDriver *spip) { + + spip->state = SPI_STOP; + spip->config = NULL; +#if SPI_USE_WAIT == TRUE + spip->thread = NULL; +#endif +#if SPI_USE_MUTUAL_EXCLUSION == TRUE + osalMutexObjectInit(&spip->mutex); +#endif +#if defined(SPI_DRIVER_EXT_INIT_HOOK) + SPI_DRIVER_EXT_INIT_HOOK(spip); +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] config pointer to the @p SPIConfig object + * + * @api + */ +void spiStart(SPIDriver *spip, const SPIConfig *config) { + + osalDbgCheck((spip != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), + "invalid state"); + spip->config = config; + spi_lld_start(spip); + spip->state = SPI_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the SPI peripheral. + * @note Deactivating the peripheral also enforces a release of the slave + * select line. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiStop(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalSysLock(); + osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), + "invalid state"); + spi_lld_stop(spip); + spip->state = SPI_STOP; + osalSysUnlock(); +} + +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiSelect(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + spiSelectI(spip); + osalSysUnlock(); +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiUnselect(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + spiUnselectI(spip); + osalSysUnlock(); +} + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @api + */ +void spiStartIgnore(SPIDriver *spip, size_t n) { + + osalDbgCheck((spip != NULL) && (n > 0U)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + spiStartIgnoreI(spip, n); + osalSysUnlock(); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiStartExchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0U) && + (rxbuf != NULL) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + spiStartExchangeI(spip, n, txbuf, rxbuf); + osalSysUnlock(); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + spiStartSendI(spip, n, txbuf); + osalSysUnlock(); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + spiStartReceiveI(spip, n, rxbuf); + osalSysUnlock(); +} + +#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Ignores data on the SPI bus. + * @details This synchronous function performs the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @api + */ +void spiIgnore(SPIDriver *spip, size_t n) { + + osalDbgCheck((spip != NULL) && (n > 0U)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); + spiStartIgnoreI(spip, n); + (void) osalThreadSuspendS(&spip->thread); + osalSysUnlock(); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This synchronous function performs a simultaneous transmit/receive + * operation. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiExchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0U) && + (rxbuf != NULL) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); + spiStartExchangeI(spip, n, txbuf, rxbuf); + (void) osalThreadSuspendS(&spip->thread); + osalSysUnlock(); +} + +/** + * @brief Sends data over the SPI bus. + * @details This synchronous function performs a transmit operation. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); + spiStartSendI(spip, n, txbuf); + (void) osalThreadSuspendS(&spip->thread); + osalSysUnlock(); +} + +/** + * @brief Receives data from the SPI bus. + * @details This synchronous function performs a receive operation. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); + spiStartReceiveI(spip, n, rxbuf); + (void) osalThreadSuspendS(&spip->thread); + osalSysUnlock(); +} +#endif /* SPI_USE_WAIT == TRUE */ + +#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the SPI bus. + * @details This function tries to gain ownership to the SPI bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiAcquireBus(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalMutexLock(&spip->mutex); +} + +/** + * @brief Releases exclusive access to the SPI bus. + * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiReleaseBus(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalMutexUnlock(&spip->mutex); +} +#endif /* SPI_USE_MUTUAL_EXCLUSION == TRUE */ + +#endif /* HAL_USE_SPI == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_st.c b/os/hal/src/hal_st.c new file mode 100644 index 000000000..cf654f882 --- /dev/null +++ b/os/hal/src/hal_st.c @@ -0,0 +1,130 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file st.c + * @brief ST Driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief ST Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void stInit(void) { + + st_lld_init(); +} + + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] abstime the time to be set for the first alarm + * + * @api + */ +void stStartAlarm(systime_t abstime) { + + osalDbgAssert(stIsAlarmActive() == false, "already active"); + + st_lld_start_alarm(abstime); +} + +/** + * @brief Stops the alarm interrupt. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @api + */ +void stStopAlarm(void) { + + st_lld_stop_alarm(); +} + +/** + * @brief Sets the alarm time. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] abstime the time to be set for the next alarm + * + * @api + */ +void stSetAlarm(systime_t abstime) { + + osalDbgAssert(stIsAlarmActive() != false, "not active"); + + st_lld_set_alarm(abstime); +} + +/** + * @brief Returns the current alarm time. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @return The currently set alarm time. + * + * @api + */ +systime_t stGetAlarm(void) { + + osalDbgAssert(stIsAlarmActive() != false, "not active"); + + return st_lld_get_alarm(); +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ diff --git a/os/hal/src/hal_uart.c b/os/hal/src/hal_uart.c new file mode 100644 index 000000000..7bf0e5d74 --- /dev/null +++ b/os/hal/src/hal_uart.c @@ -0,0 +1,515 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file uart.c + * @brief UART Driver code. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief UART Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void uartInit(void) { + + uart_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p UARTDriver structure. + * + * @param[out] uartp pointer to the @p UARTDriver object + * + * @init + */ +void uartObjectInit(UARTDriver *uartp) { + + uartp->state = UART_STOP; + uartp->txstate = UART_TX_IDLE; + uartp->rxstate = UART_RX_IDLE; + uartp->config = NULL; +#if UART_USE_WAIT == TRUE + uartp->early = false; + uartp->threadrx = NULL; + uartp->threadtx = NULL; +#endif /* UART_USE_WAIT */ +#if UART_USE_MUTUAL_EXCLUSION == TRUE + osalMutexObjectInit(&uartp->mutex); +#endif /* UART_USE_MUTUAL_EXCLUSION */ + + /* Optional, user-defined initializer.*/ +#if defined(UART_DRIVER_EXT_INIT_HOOK) + UART_DRIVER_EXT_INIT_HOOK(uartp); +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] config pointer to the @p UARTConfig object + * + * @api + */ +void uartStart(UARTDriver *uartp, const UARTConfig *config) { + + osalDbgCheck((uartp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), + "invalid state"); + + uartp->config = config; + uart_lld_start(uartp); + uartp->state = UART_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @api + */ +void uartStop(UARTDriver *uartp) { + + osalDbgCheck(uartp != NULL); + + osalSysLock(); + osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), + "invalid state"); + + uart_lld_stop(uartp); + uartp->state = UART_STOP; + uartp->txstate = UART_TX_IDLE; + uartp->rxstate = UART_RX_IDLE; + osalSysUnlock(); +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf) { + + osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); + + uart_lld_start_send(uartp, n, txbuf); + uartp->txstate = UART_TX_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @iclass + */ +void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) { + + osalDbgCheckClassI(); + osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL)); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); + + uart_lld_start_send(uartp, n, txbuf); + uartp->txstate = UART_TX_ACTIVE; +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * @retval 0 There was no transmit operation in progress. + * + * @api + */ +size_t uartStopSend(UARTDriver *uartp) { + size_t n; + + osalDbgCheck(uartp != NULL); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->txstate == UART_TX_ACTIVE) { + n = uart_lld_stop_send(uartp); + uartp->txstate = UART_TX_IDLE; + } + else { + n = 0; + } + osalSysUnlock(); + + return n; +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * @retval 0 There was no transmit operation in progress. + * + * @iclass + */ +size_t uartStopSendI(UARTDriver *uartp) { + + osalDbgCheckClassI(); + osalDbgCheck(uartp != NULL); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->txstate == UART_TX_ACTIVE) { + size_t n = uart_lld_stop_send(uartp); + uartp->txstate = UART_TX_IDLE; + return n; + } + return 0; +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to receive + * @param[in] rxbuf the pointer to the receive buffer + * + * @api + */ +void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) { + + osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); + + uart_lld_start_receive(uartp, n, rxbuf); + uartp->rxstate = UART_RX_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @iclass + */ +void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) { + + osalDbgCheckClassI(); + osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL)); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); + + uart_lld_start_receive(uartp, n, rxbuf); + uartp->rxstate = UART_RX_ACTIVE; +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * @retval 0 There was no receive operation in progress. + * + * @api + */ +size_t uartStopReceive(UARTDriver *uartp) { + size_t n; + + osalDbgCheck(uartp != NULL); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->rxstate == UART_RX_ACTIVE) { + n = uart_lld_stop_receive(uartp); + uartp->rxstate = UART_RX_IDLE; + } + else { + n = 0; + } + osalSysUnlock(); + + return n; +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * @retval 0 There was no receive operation in progress. + * + * @iclass + */ +size_t uartStopReceiveI(UARTDriver *uartp) { + + osalDbgCheckClassI(); + osalDbgCheck(uartp != NULL); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->rxstate == UART_RX_ACTIVE) { + size_t n = uart_lld_stop_receive(uartp); + uartp->rxstate = UART_RX_IDLE; + return n; + } + return 0; +} + +#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Performs a transmission on the UART peripheral. + * @note The function returns when the specified number of frames have been + * sent to the UART or on timeout. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in,out] np number of data frames to transmit, on exit the number + * of frames actually transmitted + * @param[in] txbuf the pointer to the transmit buffer + * @param[in] timeout operation timeout + * @return The operation status. + * @retval MSG_OK if the operation completed successfully. + * @retval MSG_TIMEOUT if the operation timed out. + * + * @api + */ +msg_t uartSendTimeout(UARTDriver *uartp, size_t *np, + const void *txbuf, systime_t timeout) { + msg_t msg; + + osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); + + /* Transmission start.*/ + uartp->early = true; + uart_lld_start_send(uartp, *np, txbuf); + uartp->txstate = UART_TX_ACTIVE; + + /* Waiting for result.*/ + msg = osalThreadSuspendTimeoutS(&uartp->threadtx, timeout); + if (msg != MSG_OK) { + *np = uartStopSendI(uartp); + } + osalSysUnlock(); + + return msg; +} + +/** + * @brief Performs a transmission on the UART peripheral. + * @note The function returns when the specified number of frames have been + * physically transmitted or on timeout. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in,out] np number of data frames to transmit, on exit the number + * of frames actually transmitted + * @param[in] txbuf the pointer to the transmit buffer + * @param[in] timeout operation timeout + * @return The operation status. + * @retval MSG_OK if the operation completed successfully. + * @retval MSG_TIMEOUT if the operation timed out. + * + * @api + */ +msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np, + const void *txbuf, systime_t timeout) { + msg_t msg; + + osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); + + /* Transmission start.*/ + uartp->early = false; + uart_lld_start_send(uartp, *np, txbuf); + uartp->txstate = UART_TX_ACTIVE; + + /* Waiting for result.*/ + msg = osalThreadSuspendTimeoutS(&uartp->threadtx, timeout); + if (msg != MSG_OK) { + *np = uartStopSendI(uartp); + } + osalSysUnlock(); + + return msg; +} + +/** + * @brief Performs a receive operation on the UART peripheral. + * @note The function returns when the specified number of frames have been + * received or on error/timeout. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in,out] np number of data frames to receive, on exit the number + * of frames actually received + * @param[in] rxbuf the pointer to the receive buffer + * @param[in] timeout operation timeout + * + * @return The operation status. + * @retval MSG_OK if the operation completed successfully. + * @retval MSG_TIMEOUT if the operation timed out. + * @retval MSG_RESET in case of a receive error. + * + * @api + */ +msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np, + void *rxbuf, systime_t timeout) { + msg_t msg; + + osalDbgCheck((uartp != NULL) && (*np > 0U) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); + + /* Receive start.*/ + uart_lld_start_receive(uartp, *np, rxbuf); + uartp->rxstate = UART_RX_ACTIVE; + + /* Waiting for result.*/ + msg = osalThreadSuspendTimeoutS(&uartp->threadrx, timeout); + if (msg != MSG_OK) { + *np = uartStopReceiveI(uartp); + } + osalSysUnlock(); + + return msg; +} +#endif + +#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the UART bus. + * @details This function tries to gain ownership to the UART bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @api + */ +void uartAcquireBus(UARTDriver *uartp) { + + osalDbgCheck(uartp != NULL); + + osalMutexLock(&uartp->mutex); +} + +/** + * @brief Releases exclusive access to the UART bus. + * @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @api + */ +void uartReleaseBus(UARTDriver *uartp) { + + osalDbgCheck(uartp != NULL); + + osalMutexUnlock(&uartp->mutex); +} +#endif + +#endif /* HAL_USE_UART == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_usb.c b/os/hal/src/hal_usb.c new file mode 100644 index 000000000..d9fbc091a --- /dev/null +++ b/os/hal/src/hal_usb.c @@ -0,0 +1,950 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file usb.c + * @brief USB Driver code. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint8_t zero_status[] = {0x00, 0x00}; +static const uint8_t active_status[] ={0x00, 0x00}; +static const uint8_t halted_status[] = {0x01, 0x00}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static uint16_t get_hword(uint8_t *p) { + uint16_t hw; + + hw = (uint16_t)*p++; + hw |= (uint16_t)*p << 8U; + return hw; +} + +/** + * @brief SET ADDRESS transaction callback. + * + * @param[in] usbp pointer to the @p USBDriver object + */ +static void set_address(USBDriver *usbp) { + + usbp->address = usbp->setup[2]; + usb_lld_set_address(usbp); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_ADDRESS); + usbp->state = USB_SELECTED; +} + +/** + * @brief Standard requests handler. + * @details This is the standard requests default handler, most standard + * requests are handled here, the user can override the standard + * handling using the @p requests_hook_cb hook in the + * @p USBConfig structure. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The request handling exit code. + * @retval false Request not recognized by the handler or error. + * @retval true Request handled. + */ +static bool default_handler(USBDriver *usbp) { + const USBDescriptor *dp; + + /* Decoding the request.*/ + switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | + USB_RTYPE_TYPE_MASK)) | + ((uint32_t)usbp->setup[1] << 8U))) { + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_STATUS << 8): + /* Just returns the current status word.*/ + usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL); + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8): + /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature + number is handled as an error.*/ + if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { + usbp->status &= ~2U; + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return false; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_FEATURE << 8): + /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature + number is handled as an error.*/ + if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { + usbp->status |= 2U; + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + } + return false; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_ADDRESS << 8): + /* The SET_ADDRESS handling can be performed here or postponed after + the status packed depending on the USB_SET_ADDRESS_MODE low + driver setting.*/ +#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS + if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) && + (usbp->setup[1] == USB_REQ_SET_ADDRESS)) { + set_address(usbp); + } + usbSetupTransfer(usbp, NULL, 0, NULL); +#else + usbSetupTransfer(usbp, NULL, 0, set_address); +#endif + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8): + /* Handling descriptor requests from the host.*/ + dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], + usbp->setup[2], + get_hword(&usbp->setup[4])); + if (dp == NULL) { + return false; + } + /*lint -save -e9005 [11.8] Removing const is fine.*/ + usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); + /*lint -restore*/ + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_CONFIGURATION << 8): + /* Returning the last selected configuration.*/ + usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_CONFIGURATION << 8): + /* Handling configuration selection from the host.*/ + usbp->configuration = usbp->setup[2]; + if (usbp->configuration == 0U) { + usbp->state = USB_SELECTED; + } + else { + usbp->state = USB_ACTIVE; + } + _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_STATUS << 8): + case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SYNCH_FRAME << 8): + /* Just sending two zero bytes, the application can change the behavior + using a hook..*/ + /*lint -save -e9005 [11.8] Removing const is fine.*/ + usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL); + /*lint -restore*/ + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_GET_STATUS << 8): + /* Sending the EP status.*/ + if ((usbp->setup[4] & 0x80U) != 0U) { + switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) { + case EP_STATUS_STALLED: + /*lint -save -e9005 [11.8] Removing const is fine.*/ + usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); + /*lint -restore*/ + return true; + case EP_STATUS_ACTIVE: + /*lint -save -e9005 [11.8] Removing const is fine.*/ + usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); + /*lint -restore*/ + return true; + case EP_STATUS_DISABLED: + default: + return false; + } + } + else { + switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) { + case EP_STATUS_STALLED: + /*lint -save -e9005 [11.8] Removing const is fine.*/ + usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); + /*lint -restore*/ + return true; + case EP_STATUS_ACTIVE: + /*lint -save -e9005 [11.8] Removing const is fine.*/ + usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); + /*lint -restore*/ + return true; + case EP_STATUS_DISABLED: + default: + return false; + } + } + case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8): + /* Only ENDPOINT_HALT is handled as feature.*/ + if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) { + return false; + } + /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/ + if ((usbp->setup[4] & 0x0FU) != 0U) { + if ((usbp->setup[4] & 0x80U) != 0U) { + usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU); + } + else { + usb_lld_clear_out(usbp, usbp->setup[4] & 0x0FU); + } + } + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SET_FEATURE << 8): + /* Only ENDPOINT_HALT is handled as feature.*/ + if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) { + return false; + } + /* Stalling the EP, not valid for EP0, it is ignored in that case.*/ + if ((usbp->setup[4] & 0x0FU) != 0U) { + if ((usbp->setup[4] & 0x80U) != 0U) { + usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU); + } + else { + usb_lld_stall_out(usbp, usbp->setup[4] & 0x0FU); + } + } + usbSetupTransfer(usbp, NULL, 0, NULL); + return true; + case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_DESCRIPTOR << 8): + case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8): + case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_FEATURE << 8): + case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_INTERFACE << 8): + case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_INTERFACE << 8): + /* All the above requests are not handled here, if you need them then + use the hook mechanism and provide handling.*/ + default: + return false; + } +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief USB Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void usbInit(void) { + + usb_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p USBDriver structure. + * + * @param[out] usbp pointer to the @p USBDriver object + * + * @init + */ +void usbObjectInit(USBDriver *usbp) { + unsigned i; + + usbp->state = USB_STOP; + usbp->config = NULL; + for (i = 0; i < (unsigned)USB_MAX_ENDPOINTS; i++) { + usbp->in_params[i] = NULL; + usbp->out_params[i] = NULL; + } + usbp->transmitting = 0; + usbp->receiving = 0; +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] config pointer to the @p USBConfig object + * + * @api + */ +void usbStart(USBDriver *usbp, const USBConfig *config) { + unsigned i; + + osalDbgCheck((usbp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY), + "invalid state"); + usbp->config = config; + for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { + usbp->epc[i] = NULL; + } + usb_lld_start(usbp); + usbp->state = USB_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @api + */ +void usbStop(USBDriver *usbp) { + unsigned i; + + osalDbgCheck(usbp != NULL); + + osalSysLock(); + osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) || + (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) || + (usbp->state == USB_SUSPENDED), + "invalid state"); + usb_lld_stop(usbp); + usbp->state = USB_STOP; + + /* Resetting all ongoing synchronous operations.*/ + for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { +#if USB_USE_WAIT == TRUE + if (usbp->epc[i] != NULL) { + if (usbp->epc[i]->in_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); + } + if (usbp->epc[i]->out_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); + } + } +#endif + usbp->epc[i] = NULL; + } + osalOsRescheduleS(); + osalSysUnlock(); +} + +/** + * @brief Enables an endpoint. + * @details This function enables an endpoint, both IN and/or OUT directions + * depending on the configuration structure. + * @note This function must be invoked in response of a SET_CONFIGURATION + * or SET_INTERFACE message. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] epcp the endpoint configuration + * + * @iclass + */ +void usbInitEndpointI(USBDriver *usbp, usbep_t ep, + const USBEndpointConfig *epcp) { + + osalDbgCheckClassI(); + osalDbgCheck((usbp != NULL) && (epcp != NULL)); + osalDbgAssert(usbp->state == USB_ACTIVE, + "invalid state"); + osalDbgAssert(usbp->epc[ep] == NULL, "already initialized"); + + /* Logically enabling the endpoint in the USBDriver structure.*/ + usbp->epc[ep] = epcp; + + /* Clearing the state structures, custom fields as well.*/ + if (epcp->in_state != NULL) { + memset(epcp->in_state, 0, sizeof(USBInEndpointState)); + } + if (epcp->out_state != NULL) { + memset(epcp->out_state, 0, sizeof(USBOutEndpointState)); + } + + /* Low level endpoint activation.*/ + usb_lld_init_endpoint(usbp, ep); +} + +/** + * @brief Disables all the active endpoints. + * @details This function disables all the active endpoints except the + * endpoint zero. + * @note This function must be invoked in response of a SET_CONFIGURATION + * message with configuration number zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @iclass + */ +void usbDisableEndpointsI(USBDriver *usbp) { + unsigned i; + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + osalDbgAssert(usbp->state == USB_SELECTED, "invalid state"); + + usbp->transmitting &= ~1U; + usbp->receiving &= ~1U; + for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { +#if USB_USE_WAIT == TRUE + /* Signaling the event to threads waiting on endpoints.*/ + if (usbp->epc[i] != NULL) { + osalSysLockFromISR(); + if (usbp->epc[i]->in_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); + } + if (usbp->epc[i]->out_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); + } + osalSysUnlockFromISR(); + } +#endif + usbp->epc[i] = NULL; + } + + /* Low level endpoints deactivation.*/ + usb_lld_disable_endpoints(usbp); +} + +/** + * @brief Starts a receive transaction on an OUT endpoint. + * @note This function is meant to be called from ISR context outside + * critical zones because there is a potentially slow operation + * inside. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the received data + * @param[in] n transaction size. It is recommended a multiple of + * the packet size because the excess is discarded. + * + * @iclass + */ +void usbStartReceiveI(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { + USBOutEndpointState *osp; + + osalDbgCheckClassI(); + osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS)); + osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving"); + + /* Marking the endpoint as active.*/ + usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); + + /* Setting up the transfer.*/ + /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ + osp = usbp->epc[ep]->out_state; + /*lint -restore*/ + osp->rxbuf = buf; + osp->rxsize = n; + osp->rxcnt = 0; +#if USB_USE_WAIT == TRUE + osp->thread = NULL; +#endif + + /* Starting transfer.*/ + usb_lld_start_out(usbp, ep); +} + +/** + * @brief Starts a transmit transaction on an IN endpoint. + * @note This function is meant to be called from ISR context outside + * critical zones because there is a potentially slow operation + * inside. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the data to be transmitted + * @param[in] n transaction size + * + * @iclass + */ +void usbStartTransmitI(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { + USBInEndpointState *isp; + + osalDbgCheckClassI(); + osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS)); + osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting"); + + /* Marking the endpoint as active.*/ + usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); + + /* Setting up the transfer.*/ + /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ + isp = usbp->epc[ep]->in_state; + /*lint -restore*/ + isp->txbuf = buf; + isp->txsize = n; + isp->txcnt = 0; +#if USB_USE_WAIT == TRUE + isp->thread = NULL; +#endif + + /* Starting transfer.*/ + usb_lld_start_in(usbp, ep); +} + +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Performs a receive transaction on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the received data + * @param[in] n transaction size. It is recommended a multiple of + * the packet size because the excess is discarded. + * + * @return The received effective data size, it can be less than + * the amount specified. + * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation + * has been aborted by an USB reset or a transition to + * the @p USB_SUSPENDED state. + * + * @api + */ +msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { + msg_t msg; + + osalSysLock(); + + if (usbGetDriverStateI(usbp) != USB_ACTIVE) { + osalSysUnlock(); + return MSG_RESET; + } + + usbStartReceiveI(usbp, ep, buf, n); + msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread); + osalSysUnlock(); + + return msg; +} + +/** + * @brief Performs a transmit transaction on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the data to be transmitted + * @param[in] n transaction size + * + * @return The operation status. + * @retval MSG_OK operation performed successfully. + * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation + * has been aborted by an USB reset or a transition to + * the @p USB_SUSPENDED state. + * + * @api + */ +msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) { + msg_t msg; + + osalSysLock(); + + if (usbGetDriverStateI(usbp) != USB_ACTIVE) { + osalSysUnlock(); + return MSG_RESET; + } + + usbStartTransmitI(usbp, ep, buf, n); + msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread); + osalSysUnlock(); + + return msg; +} +#endif /* USB_USE_WAIT == TRUE */ + +/** + * @brief Stalls an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @return The operation status. + * @retval false Endpoint stalled. + * @retval true Endpoint busy, not stalled. + * + * @iclass + */ +bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) { + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + + if (usbGetReceiveStatusI(usbp, ep)) { + return true; + } + + usb_lld_stall_out(usbp, ep); + return false; +} + +/** + * @brief Stalls an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @return The operation status. + * @retval false Endpoint stalled. + * @retval true Endpoint busy, not stalled. + * + * @iclass + */ +bool usbStallTransmitI(USBDriver *usbp, usbep_t ep) { + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + + if (usbGetTransmitStatusI(usbp, ep)) { + return true; + } + + usb_lld_stall_in(usbp, ep); + return false; +} + +/** + * @brief USB reset routine. + * @details This function must be invoked when an USB bus reset condition is + * detected. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void _usb_reset(USBDriver *usbp) { + unsigned i; + + /* State transition.*/ + usbp->state = USB_READY; + + /* Resetting internal state.*/ + usbp->status = 0; + usbp->address = 0; + usbp->configuration = 0; + usbp->transmitting = 0; + usbp->receiving = 0; + + /* Invalidates all endpoints into the USBDriver structure.*/ + for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { +#if USB_USE_WAIT == TRUE + /* Signaling the event to threads waiting on endpoints.*/ + if (usbp->epc[i] != NULL) { + osalSysLockFromISR(); + if (usbp->epc[i]->in_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); + } + if (usbp->epc[i]->out_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); + } + osalSysUnlockFromISR(); + } +#endif + usbp->epc[i] = NULL; + } + + /* EP0 state machine initialization.*/ + usbp->ep0state = USB_EP0_WAITING_SETUP; + + /* Low level reset.*/ + usb_lld_reset(usbp); + + /* Notification of reset event.*/ + _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); +} + +/** + * @brief USB suspend routine. + * @details This function must be invoked when an USB bus suspend condition is + * detected. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void _usb_suspend(USBDriver *usbp) { + + /* State transition.*/ + usbp->state = USB_SUSPENDED; + + /* Notification of suspend event.*/ + _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND); + + /* Signaling the event to threads waiting on endpoints.*/ +#if USB_USE_WAIT == TRUE + { + unsigned i; + + for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { + if (usbp->epc[i] != NULL) { + osalSysLockFromISR(); + if (usbp->epc[i]->in_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); + } + if (usbp->epc[i]->out_state != NULL) { + osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); + } + osalSysUnlockFromISR(); + } + } + } +#endif +} + +/** + * @brief USB wake-up routine. + * @details This function must be invoked when an USB bus wake-up condition is + * detected. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void _usb_wakeup(USBDriver *usbp) { + + /* State transition.*/ + usbp->state = USB_ACTIVE; + + /* Notification of suspend event.*/ + _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); +} + +/** + * @brief Default EP0 SETUP callback. + * @details This function is used by the low level driver as default handler + * for EP0 SETUP events. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number, always zero + * + * @notapi + */ +void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { + size_t max; + + usbp->ep0state = USB_EP0_WAITING_SETUP; + usbReadSetup(usbp, ep, usbp->setup); + + /* First verify if the application has an handler installed for this + request.*/ + /*lint -save -e9007 [13.5] No side effects, it is intentional.*/ + if ((usbp->config->requests_hook_cb == NULL) || + !(usbp->config->requests_hook_cb(usbp))) { + /*lint -restore*/ + /* Invoking the default handler, if this fails then stalls the + endpoint zero as error.*/ + /*lint -save -e9007 [13.5] No side effects, it is intentional.*/ + if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) || + !default_handler(usbp)) { + /*lint -restore*/ + /* Error response, the state machine goes into an error state, the low + level layer will have to reset it to USB_EP0_WAITING_SETUP after + receiving a SETUP packet.*/ + usb_lld_stall_in(usbp, 0); + usb_lld_stall_out(usbp, 0); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); + usbp->ep0state = USB_EP0_ERROR; + return; + } + } +#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW) + if (usbp->setup[1] == USB_REQ_SET_ADDRESS) { + /* Zero-length packet sent by hardware */ + return; + } +#endif + /* Transfer preparation. The request handler must have populated + correctly the fields ep0next, ep0n and ep0endcb using the macro + usbSetupTransfer().*/ + max = (size_t)get_hword(&usbp->setup[6]); + /* The transfer size cannot exceed the specified amount.*/ + if (usbp->ep0n > max) { + usbp->ep0n = max; + } + if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) { + /* IN phase.*/ + if (usbp->ep0n != 0U) { + /* Starts the transmit phase.*/ + usbp->ep0state = USB_EP0_TX; + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n); + osalSysUnlockFromISR(); + } + else { + /* No transmission phase, directly receiving the zero sized status + packet.*/ + usbp->ep0state = USB_EP0_WAITING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) + osalSysLockFromISR(); + usbStartReceiveI(usbp, 0, NULL, 0); + osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif + } + } + else { + /* OUT phase.*/ + if (usbp->ep0n != 0U) { + /* Starts the receive phase.*/ + usbp->ep0state = USB_EP0_RX; + osalSysLockFromISR(); + usbStartReceiveI(usbp, 0, usbp->ep0next, usbp->ep0n); + osalSysUnlockFromISR(); + } + else { + /* No receive phase, directly sending the zero sized status + packet.*/ + usbp->ep0state = USB_EP0_SENDING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0, NULL, 0); + osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif + } + } +} + +/** + * @brief Default EP0 IN callback. + * @details This function is used by the low level driver as default handler + * for EP0 IN events. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number, always zero + * + * @notapi + */ +void _usb_ep0in(USBDriver *usbp, usbep_t ep) { + size_t max; + + (void)ep; + switch (usbp->ep0state) { + case USB_EP0_TX: + max = (size_t)get_hword(&usbp->setup[6]); + /* If the transmitted size is less than the requested size and it is a + multiple of the maximum packet size then a zero size packet must be + transmitted.*/ + if ((usbp->ep0n < max) && + ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) { + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0, NULL, 0); + osalSysUnlockFromISR(); + usbp->ep0state = USB_EP0_WAITING_TX0; + return; + } + /* Falls into, it is intentional.*/ + case USB_EP0_WAITING_TX0: + /* Transmit phase over, receiving the zero sized status packet.*/ + usbp->ep0state = USB_EP0_WAITING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) + osalSysLockFromISR(); + usbStartReceiveI(usbp, 0, NULL, 0); + osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif + return; + case USB_EP0_SENDING_STS: + /* Status packet sent, invoking the callback if defined.*/ + if (usbp->ep0endcb != NULL) { + usbp->ep0endcb(usbp); + } + usbp->ep0state = USB_EP0_WAITING_SETUP; + return; + case USB_EP0_WAITING_SETUP: + case USB_EP0_WAITING_STS: + case USB_EP0_RX: + /* All the above are invalid states in the IN phase.*/ + osalDbgAssert(false, "EP0 state machine error"); + /* Falling through is intentional.*/ + case USB_EP0_ERROR: + /* Error response, the state machine goes into an error state, the low + level layer will have to reset it to USB_EP0_WAITING_SETUP after + receiving a SETUP packet.*/ + usb_lld_stall_in(usbp, 0); + usb_lld_stall_out(usbp, 0); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); + usbp->ep0state = USB_EP0_ERROR; + return; + default: + osalDbgAssert(false, "EP0 state machine invalid state"); + } +} + +/** + * @brief Default EP0 OUT callback. + * @details This function is used by the low level driver as default handler + * for EP0 OUT events. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number, always zero + * + * @notapi + */ +void _usb_ep0out(USBDriver *usbp, usbep_t ep) { + + (void)ep; + switch (usbp->ep0state) { + case USB_EP0_RX: + /* Receive phase over, sending the zero sized status packet.*/ + usbp->ep0state = USB_EP0_SENDING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0, NULL, 0); + osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif + return; + case USB_EP0_WAITING_STS: + /* Status packet received, it must be zero sized, invoking the callback + if defined.*/ +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) + if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) { + break; + } +#endif + if (usbp->ep0endcb != NULL) { + usbp->ep0endcb(usbp); + } + usbp->ep0state = USB_EP0_WAITING_SETUP; + return; + case USB_EP0_WAITING_SETUP: + case USB_EP0_TX: + case USB_EP0_WAITING_TX0: + case USB_EP0_SENDING_STS: + /* All the above are invalid states in the IN phase.*/ + osalDbgAssert(false, "EP0 state machine error"); + /* Falling through is intentional.*/ + case USB_EP0_ERROR: + /* Error response, the state machine goes into an error state, the low + level layer will have to reset it to USB_EP0_WAITING_SETUP after + receiving a SETUP packet.*/ + usb_lld_stall_in(usbp, 0); + usb_lld_stall_out(usbp, 0); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); + usbp->ep0state = USB_EP0_ERROR; + return; + default: + osalDbgAssert(false, "EP0 state machine invalid state"); + } +} + +#endif /* HAL_USE_USB == TRUE */ + +/** @} */ diff --git a/os/hal/src/hal_wdg.c b/os/hal/src/hal_wdg.c new file mode 100644 index 000000000..a764864a4 --- /dev/null +++ b/os/hal/src/hal_wdg.c @@ -0,0 +1,120 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file wdg.c + * @brief WDG Driver code. + * + * @addtogroup WDG + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief WDG Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void wdgInit(void) { + + wdg_lld_init(); +} + +/** + * @brief Configures and activates the WDG peripheral. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * @param[in] config pointer to the @p WDGConfig object + * + * @api + */ +void wdgStart(WDGDriver *wdgp, const WDGConfig *config) { + + osalDbgCheck((wdgp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((wdgp->state == WDG_STOP) || (wdgp->state == WDG_READY), + "invalid state"); + wdgp->config = config; + wdg_lld_start(wdgp); + wdgp->state = WDG_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the WDG peripheral. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * + * @api + */ +void wdgStop(WDGDriver *wdgp) { + + osalDbgCheck(wdgp != NULL); + + osalSysLock(); + osalDbgAssert((wdgp->state == WDG_STOP) || (wdgp->state == WDG_READY), + "invalid state"); + wdg_lld_stop(wdgp); + wdgp->state = WDG_STOP; + osalSysUnlock(); +} + +/** + * @brief Resets WDG's counter. + * + * @param[in] wdgp pointer to the @p WDGDriver object + * + * @api + */ +void wdgReset(WDGDriver *wdgp) { + + osalDbgCheck(wdgp != NULL); + + osalSysLock(); + osalDbgAssert(wdgp->state == WDG_READY, "not ready"); + wdgResetI(wdgp); + osalSysUnlock(); +} + +#endif /* HAL_USE_WDG == TRUE */ + +/** @} */ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c deleted file mode 100644 index 0ed77eeaf..000000000 --- a/os/hal/src/i2c.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file i2c.c - * @brief I2C Driver code. - * - * @addtogroup I2C - * @{ - */ -#include "hal.h" - -#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief I2C Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void i2cInit(void) { - - i2c_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2CDriver structure. - * - * @param[out] i2cp pointer to the @p I2CDriver object - * - * @init - */ -void i2cObjectInit(I2CDriver *i2cp) { - - i2cp->state = I2C_STOP; - i2cp->config = NULL; - -#if I2C_USE_MUTUAL_EXCLUSION == TRUE - osalMutexObjectInit(&i2cp->mutex); -#endif - -#if defined(I2C_DRIVER_EXT_INIT_HOOK) - I2C_DRIVER_EXT_INIT_HOOK(i2cp); -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] config pointer to the @p I2CConfig object - * - * @api - */ -void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { - - osalDbgCheck((i2cp != NULL) && (config != NULL)); - osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || - (i2cp->state == I2C_LOCKED), "invalid state"); - - osalSysLock(); - i2cp->config = config; - i2c_lld_start(i2cp); - i2cp->state = I2C_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cStop(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || - (i2cp->state == I2C_LOCKED), "invalid state"); - - osalSysLock(); - i2c_lld_stop(i2cp); - i2cp->state = I2C_STOP; - osalSysUnlock(); -} - -/** - * @brief Returns the errors mask associated to the previous operation. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @return The errors mask. - * - * @api - */ -i2cflags_t i2cGetErrors(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - - return i2c_lld_get_errors(i2cp); -} - -/** - * @brief Sends data via the I2C bus. - * @details Function designed to realize "read-through-write" transfer - * paradigm. If you want transmit data without any further read, - * than set @b rxbytes field to 0. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address (7 bits) without R/W bit - * @param[in] txbuf pointer to transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to receive buffer - * @param[in] rxbytes number of bytes to be received, set it to 0 if - * you want transmit only - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. - * - * @api - */ -msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, - i2caddr_t addr, - const uint8_t *txbuf, - size_t txbytes, - uint8_t *rxbuf, - size_t rxbytes, - systime_t timeout) { - msg_t rdymsg; - - osalDbgCheck((i2cp != NULL) && (addr != 0U) && - (txbytes > 0U) && (txbuf != NULL) && - ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != NULL))) && - (timeout != TIME_IMMEDIATE)); - - osalDbgAssert(i2cp->state == I2C_READY, "not ready"); - - osalSysLock(); - i2cp->errors = I2C_NO_ERROR; - i2cp->state = I2C_ACTIVE_TX; - rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes, - rxbuf, rxbytes, timeout); - if (rdymsg == MSG_TIMEOUT) { - i2cp->state = I2C_LOCKED; - } - else { - i2cp->state = I2C_READY; - } - osalSysUnlock(); - return rdymsg; -} - -/** - * @brief Receives data from the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address (7 bits) without R/W bit - * @param[out] rxbuf pointer to receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. - * - * @api - */ -msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, - i2caddr_t addr, - uint8_t *rxbuf, - size_t rxbytes, - systime_t timeout){ - - msg_t rdymsg; - - osalDbgCheck((i2cp != NULL) && (addr != 0U) && - (rxbytes > 0U) && (rxbuf != NULL) && - (timeout != TIME_IMMEDIATE)); - - osalDbgAssert(i2cp->state == I2C_READY, "not ready"); - - osalSysLock(); - i2cp->errors = I2C_NO_ERROR; - i2cp->state = I2C_ACTIVE_RX; - rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout); - if (rdymsg == MSG_TIMEOUT) { - i2cp->state = I2C_LOCKED; - } - else { - i2cp->state = I2C_READY; - } - osalSysUnlock(); - return rdymsg; -} - -#if (I2C_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the I2C bus. - * @details This function tries to gain ownership to the I2C bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cAcquireBus(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - - osalMutexLock(&i2cp->mutex); -} - -/** - * @brief Releases exclusive access to the I2C bus. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cReleaseBus(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - - osalMutexUnlock(&i2cp->mutex); -} -#endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */ - -#endif /* HAL_USE_I2C == TRUE */ - -/** @} */ diff --git a/os/hal/src/i2s.c b/os/hal/src/i2s.c deleted file mode 100644 index 57a43a7e3..000000000 --- a/os/hal/src/i2s.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file i2s.c - * @brief I2S Driver code. - * - * @addtogroup I2S - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief I2S Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void i2sInit(void) { - - i2s_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2SDriver structure. - * - * @param[out] i2sp pointer to the @p I2SDriver object - * - * @init - */ -void i2sObjectInit(I2SDriver *i2sp) { - - i2sp->state = I2S_STOP; - i2sp->config = NULL; -} - -/** - * @brief Configures and activates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] config pointer to the @p I2SConfig object - * - * @api - */ -void i2sStart(I2SDriver *i2sp, const I2SConfig *config) { - - osalDbgCheck((i2sp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), - "invalid state"); - i2sp->config = config; - i2s_lld_start(i2sp); - i2sp->state = I2S_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStop(I2SDriver *i2sp) { - - osalDbgCheck(i2sp != NULL); - - osalSysLock(); - osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), - "invalid state"); - i2s_lld_stop(i2sp); - i2sp->state = I2S_STOP; - osalSysUnlock(); -} - -/** - * @brief Starts a I2S data exchange. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStartExchange(I2SDriver *i2sp) { - - osalDbgCheck(i2sp != NULL); - - osalSysLock(); - osalDbgAssert(i2sp->state == I2S_READY, "not ready"); - i2sStartExchangeI(i2sp); - osalSysUnlock(); -} - -/** - * @brief Stops the ongoing data exchange. - * @details The ongoing data exchange, if any, is stopped, if the driver - * was not active the function does nothing. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStopExchange(I2SDriver *i2sp) { - - osalDbgCheck((i2sp != NULL)); - - osalSysLock(); - osalDbgAssert((i2sp->state == I2S_READY) || - (i2sp->state == I2S_ACTIVE) || - (i2sp->state == I2S_COMPLETE), - "invalid state"); - i2sStopExchangeI(i2sp); - osalSysUnlock(); -} - -#endif /* HAL_USE_I2S == TRUE */ - -/** @} */ diff --git a/os/hal/src/icu.c b/os/hal/src/icu.c deleted file mode 100644 index ab42dc8ce..000000000 --- a/os/hal/src/icu.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file icu.c - * @brief ICU Driver code. - * - * @addtogroup ICU - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief ICU Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void icuInit(void) { - - icu_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p ICUDriver structure. - * - * @param[out] icup pointer to the @p ICUDriver object - * - * @init - */ -void icuObjectInit(ICUDriver *icup) { - - icup->state = ICU_STOP; - icup->config = NULL; -} - -/** - * @brief Configures and activates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * @param[in] config pointer to the @p ICUConfig object - * - * @api - */ -void icuStart(ICUDriver *icup, const ICUConfig *config) { - - osalDbgCheck((icup != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), - "invalid state"); - icup->config = config; - icu_lld_start(icup); - icup->state = ICU_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuStop(ICUDriver *icup) { - - osalDbgCheck(icup != NULL); - - osalSysLock(); - osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), - "invalid state"); - icu_lld_stop(icup); - icup->state = ICU_STOP; - osalSysUnlock(); -} - -/** - * @brief Starts the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuStartCapture(ICUDriver *icup) { - - osalDbgCheck(icup != NULL); - - osalSysLock(); - osalDbgAssert(icup->state == ICU_READY, "invalid state"); - icuStartCaptureI(icup); - osalSysUnlock(); -} - -/** - * @brief Waits for a completed capture. - * @note The operation could be performed in polled mode depending on. - * @note In order to use this function notifications must be disabled. - * @pre The driver must be in @p ICU_WAITING or @p ICU_ACTIVE states. - * @post After the capture is available the driver is in @p ICU_ACTIVE - * state. If a capture fails then the driver is in @p ICU_WAITING - * state. - * - * @param[in] icup pointer to the @p ICUDriver object - * @return The capture status. - * @retval false if the capture is successful. - * @retval true if a timer overflow occurred. - * - * @api - */ -bool icuWaitCapture(ICUDriver *icup) { - bool result; - - osalDbgCheck(icup != NULL); - - osalSysLock(); - osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE), - "invalid state"); - osalDbgAssert(icuAreNotificationsEnabledX(icup) == false, - "notifications enabled"); - result = icu_lld_wait_capture(icup); - icup->state = result ? ICU_WAITING : ICU_ACTIVE; - osalSysUnlock(); - - return result; -} - -/** - * @brief Stops the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuStopCapture(ICUDriver *icup) { - - osalDbgCheck(icup != NULL); - - osalSysLock(); - osalDbgAssert((icup->state == ICU_READY) || (icup->state == ICU_WAITING) || - (icup->state == ICU_ACTIVE), - "invalid state"); - icuStopCaptureI(icup); - osalSysUnlock(); -} - -/** - * @brief Enables notifications. - * @pre The ICU unit must have been activated using @p icuStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuEnableNotifications(ICUDriver *icup) { - - osalDbgCheck(icup != NULL); - - osalSysLock(); - osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE), - "invalid state"); - icuEnableNotificationsI(icup); - osalSysUnlock(); -} - -/** - * @brief Disables notifications. - * @pre The ICU unit must have been activated using @p icuStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuDisableNotifications(ICUDriver *icup) { - - osalDbgCheck(icup != NULL); - - osalSysLock(); - osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE), - "invalid state"); - icuDisableNotificationsI(icup); - osalSysUnlock(); -} - -#endif /* HAL_USE_ICU == TRUE */ - -/** @} */ diff --git a/os/hal/src/mac.c b/os/hal/src/mac.c deleted file mode 100644 index 18add7560..000000000 --- a/os/hal/src/mac.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file mac.c - * @brief MAC Driver code. - * - * @addtogroup MAC - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if (MAC_USE_ZERO_COPY == TRUE) && (MAC_SUPPORTS_ZERO_COPY == FALSE) -#error "MAC_USE_ZERO_COPY not supported by this implementation" -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief MAC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void macInit(void) { - - mac_lld_init(); -} - -/** - * @brief Initialize the standard part of a @p MACDriver structure. - * - * @param[out] macp pointer to the @p MACDriver object - * - * @init - */ -void macObjectInit(MACDriver *macp) { - - macp->state = MAC_STOP; - macp->config = NULL; - osalThreadQueueObjectInit(&macp->tdqueue); - osalThreadQueueObjectInit(&macp->rdqueue); -#if MAC_USE_EVENTS == TRUE - osalEventObjectInit(&macp->rdevent); -#endif -} - -/** - * @brief Configures and activates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] config pointer to the @p MACConfig object - * - * @api - */ -void macStart(MACDriver *macp, const MACConfig *config) { - - osalDbgCheck((macp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert(macp->state == MAC_STOP, - "invalid state"); - macp->config = config; - mac_lld_start(macp); - macp->state = MAC_ACTIVE; - osalSysUnlock(); -} - -/** - * @brief Deactivates the MAC peripheral. - * - * @param[in] macp pointer to the @p MACDriver object - * - * @api - */ -void macStop(MACDriver *macp) { - - osalDbgCheck(macp != NULL); - - osalSysLock(); - osalDbgAssert((macp->state == MAC_STOP) || (macp->state == MAC_ACTIVE), - "invalid state"); - mac_lld_stop(macp); - macp->state = MAC_STOP; - osalSysUnlock(); -} - -/** - * @brief Allocates a transmission descriptor. - * @details One of the available transmission descriptors is locked and - * returned. If a descriptor is not currently available then the - * invoking thread is queued until one is freed. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK the descriptor was obtained. - * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized. - * - * @api - */ -msg_t macWaitTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp, - systime_t timeout) { - msg_t msg; - systime_t now; - - osalDbgCheck((macp != NULL) && (tdp != NULL)); - osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); - - while (((msg = mac_lld_get_transmit_descriptor(macp, tdp)) != MSG_OK) && - (timeout > (systime_t)0)) { - osalSysLock(); - now = osalOsGetSystemTimeX(); - msg = osalThreadEnqueueTimeoutS(&macp->tdqueue, timeout); - if (msg == MSG_TIMEOUT) { - osalSysUnlock(); - break; - } - if (timeout != TIME_INFINITE) { - timeout -= (osalOsGetSystemTimeX() - now); - } - osalSysUnlock(); - } - return msg; -} - -/** - * @brief Releases a transmit descriptor and starts the transmission of the - * enqueued data as a single frame. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * - * @api - */ -void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { - - osalDbgCheck(tdp != NULL); - - mac_lld_release_transmit_descriptor(tdp); -} - -/** - * @brief Waits for a received frame. - * @details Stops until a frame is received and buffered. If a frame is - * not immediately available then the invoking thread is queued - * until one is received. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK the descriptor was obtained. - * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized. - * - * @api - */ -msg_t macWaitReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp, - systime_t timeout) { - msg_t msg; - systime_t now; - - osalDbgCheck((macp != NULL) && (rdp != NULL)); - osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); - - while (((msg = mac_lld_get_receive_descriptor(macp, rdp)) != MSG_OK) && - (timeout > (systime_t)0)) { - osalSysLock(); - now = osalOsGetSystemTimeX(); - msg = osalThreadEnqueueTimeoutS(&macp->rdqueue, timeout); - if (msg == MSG_TIMEOUT) { - osalSysUnlock(); - break; - } - if (timeout != TIME_INFINITE) { - timeout -= (osalOsGetSystemTimeX() - now); - } - osalSysUnlock(); - } - return msg; -} - -/** - * @brief Releases a receive descriptor. - * @details The descriptor and its buffer are made available for more incoming - * frames. - * - * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure - * - * @api - */ -void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { - - osalDbgCheck(rdp != NULL); - - mac_lld_release_receive_descriptor(rdp); -} - -/** - * @brief Updates and returns the link status. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The link status. - * @retval true if the link is active. - * @retval false if the link is down. - * - * @api - */ -bool macPollLinkStatus(MACDriver *macp) { - - osalDbgCheck(macp != NULL); - osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); - - return mac_lld_poll_link_status(macp); -} - -#endif /* HAL_USE_MAC == TRUE */ - -/** @} */ diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c deleted file mode 100644 index acb0d6d2e..000000000 --- a/os/hal/src/mmc_spi.c +++ /dev/null @@ -1,918 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Parts of this file have been contributed by Matthias Blaicher. - */ - -/** - * @file mmc_spi.c - * @brief MMC over SPI driver code. - * - * @addtogroup MMC_SPI - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/* Forward declarations required by mmc_vmt.*/ -static bool mmc_read(void *instance, uint32_t startblk, - uint8_t *buffer, uint32_t n); -static bool mmc_write(void *instance, uint32_t startblk, - const uint8_t *buffer, uint32_t n); - -/** - * @brief Virtual methods table. - */ -static const struct MMCDriverVMT mmc_vmt = { - (bool (*)(void *))mmc_lld_is_card_inserted, - (bool (*)(void *))mmc_lld_is_write_protected, - (bool (*)(void *))mmcConnect, - (bool (*)(void *))mmcDisconnect, - mmc_read, - mmc_write, - (bool (*)(void *))mmcSync, - (bool (*)(void *, BlockDeviceInfo *))mmcGetInfo -}; - -/** - * @brief Lookup table for CRC-7 ( based on polynomial x^7 + x^3 + 1). - */ -static const uint8_t crc7_lookup_table[256] = { - 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, - 0x6c, 0x65, 0x7e, 0x77, 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, - 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 0x32, 0x3b, 0x20, 0x29, - 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, - 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, - 0x47, 0x4e, 0x55, 0x5c, 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, - 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 0x7d, 0x74, 0x6f, 0x66, - 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, - 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, - 0x3a, 0x33, 0x28, 0x21, 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, - 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5a, - 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, - 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, - 0x34, 0x3d, 0x26, 0x2f, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, - 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x6a, 0x63, 0x78, 0x71, - 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, - 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, - 0x49, 0x40, 0x5b, 0x52, 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, - 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 0x17, 0x1e, 0x05, 0x0c, - 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, - 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, - 0x62, 0x6b, 0x70, 0x79 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static bool mmc_read(void *instance, uint32_t startblk, - uint8_t *buffer, uint32_t n) { - - if (mmcStartSequentialRead((MMCDriver *)instance, startblk)) { - return HAL_FAILED; - } - - while (n > 0U) { - if (mmcSequentialRead((MMCDriver *)instance, buffer)) { - return HAL_FAILED; - } - buffer += MMCSD_BLOCK_SIZE; - n--; - } - - if (mmcStopSequentialRead((MMCDriver *)instance)) { - return HAL_FAILED; - } - return HAL_SUCCESS; -} - -static bool mmc_write(void *instance, uint32_t startblk, - const uint8_t *buffer, uint32_t n) { - - if (mmcStartSequentialWrite((MMCDriver *)instance, startblk)) { - return HAL_FAILED; - } - - while (n > 0U) { - if (mmcSequentialWrite((MMCDriver *)instance, buffer)) { - return HAL_FAILED; - } - buffer += MMCSD_BLOCK_SIZE; - n--; - } - - if (mmcStopSequentialWrite((MMCDriver *)instance)) { - return HAL_FAILED; - } - return HAL_SUCCESS; -} - -/** - * @brief Calculate the MMC standard CRC-7 based on a lookup table. - * - * @param[in] crc start value for CRC - * @param[in] buffer pointer to data buffer - * @param[in] len length of data - * @return Calculated CRC - */ -static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) { - - while (len > 0U) { - crc = crc7_lookup_table[(crc << 1) ^ (*buffer++)]; - len--; - } - return crc; -} - -/** - * @brief Waits an idle condition. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @notapi - */ -static void wait(MMCDriver *mmcp) { - int i; - uint8_t buf[4]; - - for (i = 0; i < 16; i++) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFFU) { - return; - } - } - /* Looks like it is a long wait.*/ - while (true) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFFU) { - break; - } -#if MMC_NICE_WAITING == TRUE - /* Trying to be nice with the other threads.*/ - osalThreadSleepMilliseconds(1); -#endif - } -} - -/** - * @brief Sends a command header. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] cmd the command id - * @param[in] arg the command argument - * - * @notapi - */ -static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { - uint8_t buf[6]; - - /* Wait for the bus to become idle if a write operation was in progress.*/ - wait(mmcp); - - buf[0] = (uint8_t)0x40U | cmd; - buf[1] = (uint8_t)(arg >> 24U); - buf[2] = (uint8_t)(arg >> 16U); - buf[3] = (uint8_t)(arg >> 8U); - buf[4] = (uint8_t)arg; - /* Calculate CRC for command header, shift to right position, add stop bit.*/ - buf[5] = ((crc7(0, buf, 5U) & 0x7FU) << 1U) | 0x01U; - - spiSend(mmcp->config->spip, 6, buf); -} - -/** - * @brief Receives a single byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @return The response as an @p uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t recvr1(MMCDriver *mmcp) { - int i; - uint8_t r1[1]; - - for (i = 0; i < 9; i++) { - spiReceive(mmcp->config->spip, 1, r1); - if (r1[0] != 0xFFU) { - return r1[0]; - } - } - return 0xFFU; -} - -/** - * @brief Receives a three byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] buffer pointer to four bytes wide buffer - * @return First response byte as an @p uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t recvr3(MMCDriver *mmcp, uint8_t* buffer) { - uint8_t r1; - - r1 = recvr1(mmcp); - spiReceive(mmcp->config->spip, 4, buffer); - - return r1; -} - -/** - * @brief Sends a command an returns a single byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] cmd the command id - * @param[in] arg the command argument - * @return The response as an @p uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { - uint8_t r1; - - spiSelect(mmcp->config->spip); - send_hdr(mmcp, cmd, arg); - r1 = recvr1(mmcp); - spiUnselect(mmcp->config->spip); - return r1; -} - -/** - * @brief Sends a command which returns a five bytes response (R3). - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] cmd the command id - * @param[in] arg the command argument - * @param[out] response pointer to four bytes wide uint8_t buffer - * @return The first byte of the response (R1) as an @p - * uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg, - uint8_t *response) { - uint8_t r1; - - spiSelect(mmcp->config->spip); - send_hdr(mmcp, cmd, arg); - r1 = recvr3(mmcp, response); - spiUnselect(mmcp->config->spip); - return r1; -} - -/** - * @brief Reads the CSD. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] cmd command - * @param[out] cxd pointer to the CSD/CID buffer - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @notapi - */ -static bool read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) { - unsigned i; - uint8_t *bp, buf[16]; - - spiSelect(mmcp->config->spip); - send_hdr(mmcp, cmd, 0); - if (recvr1(mmcp) != 0x00U) { - spiUnselect(mmcp->config->spip); - return HAL_FAILED; - } - - /* Wait for data availability.*/ - for (i = 0U; i < MMC_WAIT_DATA; i++) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFEU) { - uint32_t *wp; - - spiReceive(mmcp->config->spip, 16, buf); - bp = buf; - for (wp = &cxd[3]; wp >= cxd; wp--) { - *wp = ((uint32_t)bp[0] << 24U) | ((uint32_t)bp[1] << 16U) | - ((uint32_t)bp[2] << 8U) | (uint32_t)bp[3]; - bp += 4; - } - - /* CRC ignored then end of transaction. */ - spiIgnore(mmcp->config->spip, 2); - spiUnselect(mmcp->config->spip); - - return HAL_SUCCESS; - } - } - return HAL_FAILED; -} - -/** - * @brief Waits that the card reaches an idle state. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @notapi - */ -static void sync(MMCDriver *mmcp) { - uint8_t buf[1]; - - spiSelect(mmcp->config->spip); - while (true) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFFU) { - break; - } -#if MMC_NICE_WAITING == TRUE - /* Trying to be nice with the other threads.*/ - osalThreadSleepMilliseconds(1); -#endif - } - spiUnselect(mmcp->config->spip); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief MMC over SPI driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void mmcInit(void) { - -} - -/** - * @brief Initializes an instance. - * - * @param[out] mmcp pointer to the @p MMCDriver object - * - * @init - */ -void mmcObjectInit(MMCDriver *mmcp) { - - mmcp->vmt = &mmc_vmt; - mmcp->state = BLK_STOP; - mmcp->config = NULL; - mmcp->block_addresses = false; -} - -/** - * @brief Configures and activates the MMC peripheral. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] config pointer to the @p MMCConfig object. - * - * @api - */ -void mmcStart(MMCDriver *mmcp, const MMCConfig *config) { - - osalDbgCheck((mmcp != NULL) && (config != NULL)); - osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), - "invalid state"); - - mmcp->config = config; - mmcp->state = BLK_ACTIVE; -} - -/** - * @brief Disables the MMC peripheral. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @api - */ -void mmcStop(MMCDriver *mmcp) { - - osalDbgCheck(mmcp != NULL); - osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), - "invalid state"); - - spiStop(mmcp->config->spip); - mmcp->state = BLK_STOP; -} - -/** - * @brief Performs the initialization procedure on the inserted card. - * @details This function should be invoked when a card is inserted and - * brings the driver in the @p MMC_READY state where it is possible - * to perform read and write operations. - * @note It is possible to invoke this function from the insertion event - * handler. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded and the driver is now - * in the @p MMC_READY state. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcConnect(MMCDriver *mmcp) { - unsigned i; - uint8_t r3[4]; - - osalDbgCheck(mmcp != NULL); - - osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), - "invalid state"); - - /* Connection procedure in progress.*/ - mmcp->state = BLK_CONNECTING; - mmcp->block_addresses = false; - - /* Slow clock mode and 128 clock pulses.*/ - spiStart(mmcp->config->spip, mmcp->config->lscfg); - spiIgnore(mmcp->config->spip, 16); - - /* SPI mode selection.*/ - i = 0; - while (true) { - if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01U) { - break; - } - if (++i >= MMC_CMD0_RETRY) { - goto failed; - } - osalThreadSleepMilliseconds(10); - } - - /* Try to detect if this is a high capacity card and switch to block - addresses if possible. - This method is based on "How to support SDC Ver2 and high capacity cards" - by ElmChan.*/ - if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND, - MMCSD_CMD8_PATTERN, r3) != 0x05U) { - - /* Switch to SDHC mode.*/ - i = 0; - while (true) { - /*lint -save -e9007 [13.5] Side effect unimportant.*/ - if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) == 0x01U) && - (send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND, 0x400001AAU, r3) == 0x00U)) { - /*lint -restore*/ - break; - } - - if (++i >= MMC_ACMD41_RETRY) { - goto failed; - } - osalThreadSleepMilliseconds(10); - } - - /* Execute dedicated read on OCR register */ - (void) send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3); - - /* Check if CCS is set in response. Card operates in block mode if set.*/ - if ((r3[0] & 0x40U) != 0U) { - mmcp->block_addresses = true; - } - } - - /* Initialization.*/ - i = 0; - while (true) { - uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0); - if (b == 0x00U) { - break; - } - if (b != 0x01U) { - goto failed; - } - if (++i >= MMC_CMD1_RETRY) { - goto failed; - } - osalThreadSleepMilliseconds(10); - } - - /* Initialization complete, full speed.*/ - spiStart(mmcp->config->spip, mmcp->config->hscfg); - - /* Setting block size.*/ - if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN, - MMCSD_BLOCK_SIZE) != 0x00U) { - goto failed; - } - - /* Determine capacity.*/ - if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd)) { - goto failed; - } - - mmcp->capacity = _mmcsd_get_capacity(mmcp->csd); - if (mmcp->capacity == 0U) { - goto failed; - } - - if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid)) { - goto failed; - } - - mmcp->state = BLK_READY; - return HAL_SUCCESS; - - /* Connection failed, state reset to BLK_ACTIVE.*/ -failed: - spiStop(mmcp->config->spip); - mmcp->state = BLK_ACTIVE; - return HAL_FAILED; -} - -/** - * @brief Brings the driver in a state safe for card removal. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @return The operation status. - * - * @retval HAL_SUCCESS the operation succeeded and the driver is now - * in the @p MMC_INSERTED state. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcDisconnect(MMCDriver *mmcp) { - - osalDbgCheck(mmcp != NULL); - - osalSysLock(); - osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), - "invalid state"); - if (mmcp->state == BLK_ACTIVE) { - osalSysUnlock(); - return HAL_SUCCESS; - } - mmcp->state = BLK_DISCONNECTING; - osalSysUnlock(); - - /* Wait for the pending write operations to complete.*/ - spiStart(mmcp->config->spip, mmcp->config->hscfg); - sync(mmcp); - - spiStop(mmcp->config->spip); - mmcp->state = BLK_ACTIVE; - return HAL_SUCCESS; -} - -/** - * @brief Starts a sequential read. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] startblk first block to read - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { - - osalDbgCheck(mmcp != NULL); - osalDbgAssert(mmcp->state == BLK_READY, "invalid state"); - - /* Read operation in progress.*/ - mmcp->state = BLK_READING; - - /* (Re)starting the SPI in case it has been reprogrammed externally, it can - happen if the SPI bus is shared among multiple peripherals.*/ - spiStart(mmcp->config->spip, mmcp->config->hscfg); - spiSelect(mmcp->config->spip); - - if (mmcp->block_addresses) { - send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk); - } - else { - send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE); - } - - if (recvr1(mmcp) != 0x00U) { - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return HAL_FAILED; - } - return HAL_SUCCESS; -} - -/** - * @brief Reads a block within a sequential read operation. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] buffer pointer to the read buffer - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { - unsigned i; - - osalDbgCheck((mmcp != NULL) && (buffer != NULL)); - - if (mmcp->state != BLK_READING) { - return HAL_FAILED; - } - - for (i = 0; i < MMC_WAIT_DATA; i++) { - spiReceive(mmcp->config->spip, 1, buffer); - if (buffer[0] == 0xFEU) { - spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer); - /* CRC ignored. */ - spiIgnore(mmcp->config->spip, 2); - return HAL_SUCCESS; - } - } - /* Timeout.*/ - spiUnselect(mmcp->config->spip); - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return HAL_FAILED; -} - -/** - * @brief Stops a sequential read gracefully. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcStopSequentialRead(MMCDriver *mmcp) { - static const uint8_t stopcmd[] = { - (uint8_t)(0x40U | MMCSD_CMD_STOP_TRANSMISSION), 0, 0, 0, 0, 1, 0xFF - }; - - osalDbgCheck(mmcp != NULL); - - if (mmcp->state != BLK_READING) { - return HAL_FAILED; - } - - spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd); -/* result = recvr1(mmcp) != 0x00U;*/ - /* Note, ignored r1 response, it can be not zero, unknown issue.*/ - (void) recvr1(mmcp); - - /* Read operation finished.*/ - spiUnselect(mmcp->config->spip); - mmcp->state = BLK_READY; - return HAL_SUCCESS; -} - -/** - * @brief Starts a sequential write. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] startblk first block to write - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { - - osalDbgCheck(mmcp != NULL); - osalDbgAssert(mmcp->state == BLK_READY, "invalid state"); - - /* Write operation in progress.*/ - mmcp->state = BLK_WRITING; - - spiStart(mmcp->config->spip, mmcp->config->hscfg); - spiSelect(mmcp->config->spip); - if (mmcp->block_addresses) { - send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk); - } - else { - send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk * MMCSD_BLOCK_SIZE); - } - - if (recvr1(mmcp) != 0x00U) { - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return HAL_FAILED; - } - return HAL_SUCCESS; -} - -/** - * @brief Writes a block within a sequential write operation. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] buffer pointer to the write buffer - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { - static const uint8_t start[] = {0xFF, 0xFC}; - uint8_t b[1]; - - osalDbgCheck((mmcp != NULL) && (buffer != NULL)); - - if (mmcp->state != BLK_WRITING) { - return HAL_FAILED; - } - - spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ - spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ - spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */ - spiReceive(mmcp->config->spip, 1, b); - if ((b[0] & 0x1FU) == 0x05U) { - wait(mmcp); - return HAL_SUCCESS; - } - - /* Error.*/ - spiUnselect(mmcp->config->spip); - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return HAL_FAILED; -} - -/** - * @brief Stops a sequential write gracefully. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcStopSequentialWrite(MMCDriver *mmcp) { - static const uint8_t stop[] = {0xFD, 0xFF}; - - osalDbgCheck(mmcp != NULL); - - if (mmcp->state != BLK_WRITING) { - return HAL_FAILED; - } - - spiSend(mmcp->config->spip, sizeof(stop), stop); - spiUnselect(mmcp->config->spip); - - /* Write operation finished.*/ - mmcp->state = BLK_READY; - return HAL_SUCCESS; -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcSync(MMCDriver *mmcp) { - - osalDbgCheck(mmcp != NULL); - - if (mmcp->state != BLK_READY) { - return HAL_FAILED; - } - - /* Synchronization operation in progress.*/ - mmcp->state = BLK_SYNCING; - - spiStart(mmcp->config->spip, mmcp->config->hscfg); - sync(mmcp); - - /* Synchronization operation finished.*/ - mmcp->state = BLK_READY; - return HAL_SUCCESS; -} - -/** - * @brief Returns the media info. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] bdip pointer to a @p BlockDeviceInfo structure - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) { - - osalDbgCheck((mmcp != NULL) && (bdip != NULL)); - - if (mmcp->state != BLK_READY) { - return HAL_FAILED; - } - - bdip->blk_num = mmcp->capacity; - bdip->blk_size = MMCSD_BLOCK_SIZE; - - return HAL_SUCCESS; -} - -/** - * @brief Erases blocks. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] startblk starting block number - * @param[in] endblk ending block number - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) { - - osalDbgCheck((mmcp != NULL)); - - /* Erase operation in progress.*/ - mmcp->state = BLK_WRITING; - - /* Handling command differences between HC and normal cards.*/ - if (!mmcp->block_addresses) { - startblk *= MMCSD_BLOCK_SIZE; - endblk *= MMCSD_BLOCK_SIZE; - } - - if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk) != 0x00U) { - goto failed; - } - - if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk) != 0x00U) { - goto failed; - } - - if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0) != 0x00U) { - goto failed; - } - - mmcp->state = BLK_READY; - return HAL_SUCCESS; - - /* Command failed, state reset to BLK_ACTIVE.*/ -failed: - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return HAL_FAILED; -} - -#endif /* HAL_USE_MMC_SPI == TRUE */ - -/** @} */ diff --git a/os/hal/src/pal.c b/os/hal/src/pal.c deleted file mode 100644 index f75e8d481..000000000 --- a/os/hal/src/pal.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file pal.c - * @brief I/O Ports Abstraction Layer code. - * - * @addtogroup PAL - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Read from an I/O bus. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The function internally uses the @p palReadGroup() macro. The use - * of this function is preferred when you value code size, readability - * and error checking over speed. - * @note The function can be called from any context. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @return The bus logical states. - * - * @special - */ -ioportmask_t palReadBus(IOBus *bus) { - - osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); - - return palReadGroup(bus->portid, bus->mask, bus->offset); -} - -/** - * @brief Write to an I/O bus. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The function can be called from any context. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] bits the bits to be written on the I/O bus. Values exceeding - * the bus width are masked so most significant bits are - * lost. - * - * @special - */ -void palWriteBus(IOBus *bus, ioportmask_t bits) { - - osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); - - palWriteGroup(bus->portid, bus->mask, bus->offset, bits); -} - -/** - * @brief Programs a bus with the specified mode. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p osalSysLock() and - * @p osalSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The function can be called from any context. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] mode the mode - * - * @special - */ -void palSetBusMode(IOBus *bus, iomode_t mode) { - - osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); - - palSetGroupMode(bus->portid, bus->mask, bus->offset, mode); -} - -#endif /* HAL_USE_PAL == TRUE */ - -/** @} */ diff --git a/os/hal/src/pwm.c b/os/hal/src/pwm.c deleted file mode 100644 index f74bf534c..000000000 --- a/os/hal/src/pwm.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file pwm.c - * @brief PWM Driver code. - * - * @addtogroup PWM - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief PWM Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void pwmInit(void) { - - pwm_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p PWMDriver structure. - * - * @param[out] pwmp pointer to a @p PWMDriver object - * - * @init - */ -void pwmObjectInit(PWMDriver *pwmp) { - - pwmp->state = PWM_STOP; - pwmp->config = NULL; - pwmp->enabled = 0; - pwmp->channels = 0; -#if defined(PWM_DRIVER_EXT_INIT_HOOK) - PWM_DRIVER_EXT_INIT_HOOK(pwmp); -#endif -} - -/** - * @brief Configures and activates the PWM peripheral. - * @note Starting a driver that is already in the @p PWM_READY state - * disables all the active channels. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] config pointer to a @p PWMConfig object - * - * @api - */ -void pwmStart(PWMDriver *pwmp, const PWMConfig *config) { - - osalDbgCheck((pwmp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), - "invalid state"); - pwmp->config = config; - pwmp->period = config->period; - pwm_lld_start(pwmp); - pwmp->enabled = 0; - pwmp->state = PWM_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the PWM peripheral. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @api - */ -void pwmStop(PWMDriver *pwmp) { - - osalDbgCheck(pwmp != NULL); - - osalSysLock(); - osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), - "invalid state"); - pwm_lld_stop(pwmp); - pwmp->enabled = 0; - pwmp->state = PWM_STOP; - osalSysUnlock(); -} - -/** - * @brief Changes the period the PWM peripheral. - * @details This function changes the period of a PWM unit that has already - * been activated using @p pwmStart(). - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The PWM unit period is changed to the new value. - * @note If a period is specified that is shorter than the pulse width - * programmed in one of the channels then the behavior is not - * guaranteed. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] period new cycle time in ticks - * - * @api - */ -void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) { - - osalDbgCheck(pwmp != NULL); - - osalSysLock(); - osalDbgAssert(pwmp->state == PWM_READY, "invalid state"); - pwmChangePeriodI(pwmp, period); - osalSysUnlock(); -} - -/** - * @brief Enables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is active using the specified configuration. - * @note Depending on the hardware implementation this function has - * effect starting on the next cycle (recommended implementation) - * or immediately (fallback implementation). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * @param[in] width PWM pulse width as clock pulses number - * - * @api - */ -void pwmEnableChannel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width) { - - osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); - - osalSysLock(); - - osalDbgAssert(pwmp->state == PWM_READY, "not ready"); - - pwmEnableChannelI(pwmp, channel, width); - - osalSysUnlock(); -} - -/** - * @brief Disables a PWM channel and its notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is disabled and its output line returned to the - * idle state. - * @note Depending on the hardware implementation this function has - * effect starting on the next cycle (recommended implementation) - * or immediately (fallback implementation). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @api - */ -void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) { - - osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); - - osalSysLock(); - - osalDbgAssert(pwmp->state == PWM_READY, "not ready"); - - pwmDisableChannelI(pwmp, channel); - - osalSysUnlock(); -} - -/** - * @brief Enables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @api - */ -void pwmEnablePeriodicNotification(PWMDriver *pwmp) { - - osalDbgCheck(pwmp != NULL); - - osalSysLock(); - - osalDbgAssert(pwmp->state == PWM_READY, "not ready"); - osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback"); - - pwmEnablePeriodicNotificationI(pwmp); - - osalSysUnlock(); -} - -/** - * @brief Disables the periodic activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @api - */ -void pwmDisablePeriodicNotification(PWMDriver *pwmp) { - - osalDbgCheck(pwmp != NULL); - - osalSysLock(); - - osalDbgAssert(pwmp->state == PWM_READY, "not ready"); - osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback"); - - pwmDisablePeriodicNotificationI(pwmp); - - osalSysUnlock(); -} - -/** - * @brief Enables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already enabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @api - */ -void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) { - - osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); - - osalSysLock(); - - osalDbgAssert(pwmp->state == PWM_READY, "not ready"); - osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U, - "channel not enabled"); - osalDbgAssert(pwmp->config->channels[channel].callback != NULL, - "undefined channel callback"); - - pwmEnableChannelNotificationI(pwmp, channel); - - osalSysUnlock(); -} - -/** - * @brief Disables a channel de-activation edge notification. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @pre The channel must have been activated using @p pwmEnableChannel(). - * @note If the notification is already disabled then the call has no effect. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...channels-1) - * - * @api - */ -void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) { - - osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); - - osalSysLock(); - - osalDbgAssert(pwmp->state == PWM_READY, "not ready"); - osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U, - "channel not enabled"); - osalDbgAssert(pwmp->config->channels[channel].callback != NULL, - "undefined channel callback"); - - pwmDisableChannelNotificationI(pwmp, channel); - - osalSysUnlock(); -} - -#endif /* HAL_USE_PWM == TRUE */ - -/** @} */ diff --git a/os/hal/src/rtc.c b/os/hal/src/rtc.c deleted file mode 100644 index 252bb7ab1..000000000 --- a/os/hal/src/rtc.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file rtc.c - * @brief RTC Driver code. - * - * @addtogroup RTC - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/* - * Lookup table with months' length - */ -static const uint8_t month_len[12] = { - 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief RTC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void rtcInit(void) { - - rtc_lld_init(); -} - -/** - * @brief Initializes a generic RTC driver object. - * @details The HW dependent part of the initialization has to be performed - * outside, usually in the hardware initialization code. - * - * @param[out] rtcp pointer to RTC driver structure - * - * @init - */ -void rtcObjectInit(RTCDriver *rtcp) { - -#if RTC_HAS_STORAGE == TRUE - rtcp->vmt = &_rtc_lld_vmt; -#else - (void)rtcp; -#endif -} - -/** - * @brief Set current time. - * @note This function can be called from any context but limitations - * could be imposed by the low level implementation. It is - * guaranteed that the function can be called from thread - * context. - * @note The function can be reentrant or not reentrant depending on - * the low level implementation. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCDateTime structure - * - * @special - */ -void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec) { - - osalDbgCheck((rtcp != NULL) && (timespec != NULL)); - - rtc_lld_set_time(rtcp, timespec); -} - -/** - * @brief Get current time. - * @note This function can be called from any context but limitations - * could be imposed by the low level implementation. It is - * guaranteed that the function can be called from thread - * context. - * @note The function can be reentrant or not reentrant depending on - * the low level implementation. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @special - */ -void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec) { - - osalDbgCheck((rtcp != NULL) && (timespec != NULL)); - - rtc_lld_get_time(rtcp, timespec); -} - -#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) -/** - * @brief Set alarm time. - * @note This function can be called from any context but limitations - * could be imposed by the low level implementation. It is - * guaranteed that the function can be called from thread - * context. - * @note The function can be reentrant or not reentrant depending on - * the low level implementation. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[in] alarmspec pointer to a @p RTCAlarm structure or @p NULL - * - * @special - */ -void rtcSetAlarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - - osalDbgCheck((rtcp != NULL) && (alarm < (rtcalarm_t)RTC_ALARMS)); - - rtc_lld_set_alarm(rtcp, alarm, alarmspec); -} - -/** - * @brief Get current alarm. - * @note If an alarm has not been set then the returned alarm specification - * is not meaningful. - * @note This function can be called from any context but limitations - * could be imposed by the low level implementation. It is - * guaranteed that the function can be called from thread - * context. - * @note The function can be reentrant or not reentrant depending on - * the low level implementation. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] alarm alarm identifier - * @param[out] alarmspec pointer to a @p RTCAlarm structure - * - * @special - */ -void rtcGetAlarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec) { - - osalDbgCheck((rtcp != NULL) && - (alarm < (rtcalarm_t)RTC_ALARMS) && - (alarmspec != NULL)); - - rtc_lld_get_alarm(rtcp, alarm, alarmspec); -} -#endif /* RTC_ALARMS > 0 */ - -#if (RTC_SUPPORTS_CALLBACKS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Enables or disables RTC callbacks. - * @details This function enables or disables the callback, use a @p NULL - * pointer in order to disable it. - * @note This function can be called from any context but limitations - * could be imposed by the low level implementation. It is - * guaranteed that the function can be called from thread - * context. - * @note The function can be reentrant or not reentrant depending on - * the low level implementation. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL - * - * @special - */ -void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) { - - osalDbgCheck(rtcp != NULL); - - rtc_lld_set_callback(rtcp, callback); -} -#endif /* RTC_SUPPORTS_CALLBACKS == TRUE */ - -/** - * @brief Convert @p RTCDateTime to broken-down time structure. - * - * @param[in] timespec pointer to a @p RTCDateTime structure - * @param[out] timp pointer to a broken-down time structure - * @param[out] tv_msec pointer to milliseconds value or @p NULL - * - * @api - */ -void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec, - struct tm *timp, - uint32_t *tv_msec) { - int sec; - - timp->tm_year = (int)timespec->year + (1980 - 1900); - timp->tm_mon = (int)timespec->month - 1; - timp->tm_mday = (int)timespec->day; - timp->tm_isdst = (int)timespec->dstflag; - timp->tm_wday = (int)timespec->dayofweek - 1; - - sec = (int)timespec->millisecond / 1000; - timp->tm_hour = sec / 3600; - sec %= 3600; - timp->tm_min = sec / 60; - timp->tm_sec = sec % 60; - - if (NULL != tv_msec) { - *tv_msec = (uint32_t)timespec->millisecond % 1000U; - } -} - -/** - * @brief Convert broken-down time structure to @p RTCDateTime. - * - * @param[in] timp pointer to a broken-down time structure - * @param[in] tv_msec milliseconds value - * @param[out] timespec pointer to a @p RTCDateTime structure - * - * @api - */ -void rtcConvertStructTmToDateTime(const struct tm *timp, - uint32_t tv_msec, - RTCDateTime *timespec) { - - /*lint -save -e9034 [10.4] Verified assignments to bit fields.*/ - timespec->year = (uint32_t)timp->tm_year - (1980U - 1900U); - timespec->month = (uint32_t)timp->tm_mon + 1U; - timespec->day = (uint32_t)timp->tm_mday; - timespec->dayofweek = (uint32_t)timp->tm_wday + 1U; - if (-1 == timp->tm_isdst) { - timespec->dstflag = 0U; /* set zero if dst is unknown */ - } - else { - timespec->dstflag = (uint32_t)timp->tm_isdst; - } - /*lint -restore*/ - /*lint -save -e9033 [10.8] Verified assignments to bit fields.*/ - timespec->millisecond = tv_msec + (uint32_t)(((timp->tm_hour * 3600) + - (timp->tm_min * 60) + - timp->tm_sec) * 1000); - /*lint -restore*/ -} - -/** - * @brief Get current time in format suitable for usage in FAT file system. - * @note The information about day of week and DST is lost in DOS - * format, the second field loses its least significant bit. - * - * @param[out] timespec pointer to a @p RTCDateTime structure - * @return FAT date/time value. - * - * @api - */ -uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec) { - uint32_t fattime; - uint32_t sec, min, hour, day, month; - - sec = timespec->millisecond / 1000U; - hour = sec / 3600U; - sec %= 3600U; - min = sec / 60U; - sec %= 60U; - day = timespec->day; - month = timespec->month; - - /* handle DST flag */ - if (1U == timespec->dstflag) { - hour += 1U; - if (hour == 24U) { - hour = 0U; - day += 1U; - if (day > month_len[month - 1U]) { - day = 1U; - month += 1U; - } - } - } - - fattime = sec >> 1U; - fattime |= min << 5U; - fattime |= hour << 11U; - fattime |= day << 16U; - fattime |= month << 21U; - fattime |= (uint32_t)timespec->year << 25U; - - return fattime; -} - -#endif /* HAL_USE_RTC == TRUE */ - -/** @} */ diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c deleted file mode 100644 index bd2c0bef6..000000000 --- a/os/hal/src/sdc.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file sdc.c - * @brief SDC Driver code. - * - * @addtogroup SDC - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/** - * @brief MMC switch mode. - */ -typedef enum { - MMC_SWITCH_COMMAND_SET = 0, - MMC_SWITCH_SET_BITS = 1, - MMC_SWITCH_CLEAR_BITS = 2, - MMC_SWITCH_WRITE_BYTE = 3 -} mmc_switch_t; - -/** - * @brief SDC switch mode. - */ -typedef enum { - SD_SWITCH_CHECK = 0, - SD_SWITCH_SET = 1 -} sd_switch_t; - -/** - * @brief SDC switch function. - */ -typedef enum { - SD_SWITCH_FUNCTION_SPEED = 0, - SD_SWITCH_FUNCTION_CMD_SYSTEM = 1, - SD_SWITCH_FUNCTION_DRIVER_STRENGTH = 2, - SD_SWITCH_FUNCTION_CURRENT_LIMIT = 3 -} sd_switch_function_t; - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Virtual methods table. - */ -static const struct SDCDriverVMT sdc_vmt = { - (bool (*)(void *))sdc_lld_is_card_inserted, - (bool (*)(void *))sdc_lld_is_write_protected, - (bool (*)(void *))sdcConnect, - (bool (*)(void *))sdcDisconnect, - (bool (*)(void *, uint32_t, uint8_t *, uint32_t))sdcRead, - (bool (*)(void *, uint32_t, const uint8_t *, uint32_t))sdcWrite, - (bool (*)(void *))sdcSync, - (bool (*)(void *, BlockDeviceInfo *))sdcGetInfo -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ -/** - * @brief Detects card mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool mode_detect(SDCDriver *sdcp) { - uint32_t resp[1]; - - /* V2.0 cards detection.*/ - if (!sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_IF_COND, - MMCSD_CMD8_PATTERN, resp)) { - sdcp->cardmode = SDC_MODE_CARDTYPE_SDV20; - /* Voltage verification.*/ - if (((resp[0] >> 8U) & 0xFU) != 1U) { - return HAL_FAILED; - } - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || - MMCSD_R1_ERROR(resp[0])) { - return HAL_FAILED; - } - } - else { - /* MMC or SD V1.1 detection.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || - MMCSD_R1_ERROR(resp[0])) { - sdcp->cardmode = SDC_MODE_CARDTYPE_MMC; - } - else { - sdcp->cardmode = SDC_MODE_CARDTYPE_SDV11; - - /* Reset error flag illegal command.*/ - sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); - } - } - - return HAL_SUCCESS; -} - -/** - * @brief Init procedure for MMC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool mmc_init(SDCDriver *sdcp) { - uint32_t ocr; - unsigned i; - uint32_t resp[1]; - - ocr = 0xC0FF8000U; - i = 0; - while (true) { - if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_INIT, ocr, resp)) { - return HAL_FAILED; - } - if ((resp[0] & 0x80000000U) != 0U) { - if ((resp[0] & 0x40000000U) != 0U) { - sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY; - } - break; - } - if (++i >= (unsigned)SDC_INIT_RETRY) { - return HAL_FAILED; - } - osalThreadSleepMilliseconds(10); - } - - return HAL_SUCCESS; -} - -/** - * @brief Init procedure for SDC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_init(SDCDriver *sdcp) { - unsigned i; - uint32_t ocr; - uint32_t resp[1]; - - if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_SDV20) { - ocr = 0xC0100000U; - } - else { - ocr = 0x80100000U; - } - - i = 0; - while (true) { - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || - MMCSD_R1_ERROR(resp[0])) { - return HAL_FAILED; - } - if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_APP_OP_COND, ocr, resp)) { - return HAL_FAILED; - } - if ((resp[0] & 0x80000000U) != 0U) { - if ((resp[0] & 0x40000000U) != 0U) { - sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY; - } - break; - } - if (++i >= (unsigned)SDC_INIT_RETRY) { - return HAL_FAILED; - } - osalThreadSleepMilliseconds(10); - } - - return HAL_SUCCESS; -} - -/** - * @brief Constructs CMD6 argument for MMC. - * - * @param[in] access EXT_CSD access mode - * @param[in] idx EXT_CSD byte number - * @param[in] value value to be written in target field - * @param[in] cmd_set switch current command set - * - * @return CMD6 argument. - * - * @notapi - */ -static uint32_t mmc_cmd6_construct(mmc_switch_t access, uint32_t idx, - uint32_t value, uint32_t cmd_set) { - - osalDbgAssert(idx <= 191U, "This field is not writable"); - osalDbgAssert(cmd_set < 8U, "This field has only 3 bits"); - - return ((uint32_t)access << 24U) | (idx << 16U) | (value << 8U) | cmd_set; -} - -/** - * @brief Constructs CMD6 argument for SDC. - * - * @param[in] mode switch/test mode - * @param[in] function function number to be switched - * @param[in] value value to be written in target function - * - * @return CMD6 argument. - * - * @notapi - */ -static uint32_t sdc_cmd6_construct(sd_switch_t mode, - sd_switch_function_t function, - uint32_t value) { - uint32_t ret = 0xFFFFFF; - - osalDbgAssert((value < 16U), "This field has only 4 bits"); - - ret &= ~((uint32_t)0xFU << ((uint32_t)function * 4U)); - ret |= value << ((uint32_t)function * 4U); - return ret | ((uint32_t)mode << 31U); -} - -/** - * @brief Extracts information from CMD6 answer. - * - * @param[in] function function number to be switched - * @param[in] buf buffer with answer - * - * @return extracted answer. - * - * @notapi - */ -static uint16_t sdc_cmd6_extract_info(sd_switch_function_t function, - const uint8_t *buf) { - - unsigned start = 12U - ((unsigned)function * 2U); - - return ((uint16_t)buf[start] << 8U) | (uint16_t)buf[start + 1U]; -} - -/** - * @brief Checks status after switching using CMD6. - * - * @param[in] function function number to be switched - * @param[in] buf buffer with answer - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_cmd6_check_status(sd_switch_function_t function, - const uint8_t *buf) { - - uint32_t tmp; - uint32_t status; - - tmp = ((uint32_t)buf[14] << 16U) | - ((uint32_t)buf[15] << 8U) | - (uint32_t)buf[16]; - status = (tmp >> ((uint32_t)function * 4U)) & 0xFU; - if (0xFU != status) { - return HAL_SUCCESS; - } - return HAL_FAILED; -} - -/** - * @brief Reads supported bus clock and switch SDC to appropriate mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] clk pointer to clock enum - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) { - uint32_t cmdarg; - const size_t N = 64; - uint8_t tmp[N]; - - /* Safe default.*/ - *clk = SDC_CLK_25MHz; - - /* Looks like only "high capacity" cards produce meaningful results during - this clock detection procedure.*/ - if (0U == _mmcsd_get_slice(sdcp->csd, MMCSD_CSD_10_CSD_STRUCTURE_SLICE)) { - *clk = SDC_CLK_25MHz; - return HAL_SUCCESS; - } - - /* Read switch functions' register.*/ - if (sdc_lld_read_special(sdcp, tmp, N, MMCSD_CMD_SWITCH, 0)) { - return HAL_FAILED; - } - - /* Check card capabilities parsing acquired data.*/ - if ((sdc_cmd6_extract_info(SD_SWITCH_FUNCTION_SPEED, tmp) & 2U) == 2U) { - /* Construct command to set the bus speed.*/ - cmdarg = sdc_cmd6_construct(SD_SWITCH_SET, SD_SWITCH_FUNCTION_SPEED, 1); - - /* Write constructed command and read operation status in single call.*/ - if (sdc_lld_read_special(sdcp, tmp, N, MMCSD_CMD_SWITCH, cmdarg)) { - return HAL_FAILED; - } - - /* Check card answer for success status bits.*/ - if (HAL_SUCCESS == sdc_cmd6_check_status(SD_SWITCH_FUNCTION_SPEED, tmp)) { - *clk = SDC_CLK_50MHz; - } - else { - *clk = SDC_CLK_25MHz; - } - } - - return HAL_SUCCESS; -} - -/** - * @brief Reads supported bus clock and switch MMC to appropriate mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] clk pointer to clock enum - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool mmc_detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) { - uint32_t cmdarg; - uint32_t resp[1]; - uint8_t *scratchpad = sdcp->config->scratchpad; - - /* Safe default.*/ - *clk = SDC_CLK_25MHz; - - /* Use safe default when there is no space for data.*/ - if (NULL == scratchpad) { - return HAL_SUCCESS; - } - - cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 185, 1, 0); - if (!(sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SWITCH, cmdarg, resp) || - MMCSD_R1_ERROR(resp[0]))) { - *clk = SDC_CLK_50MHz; - } - - return HAL_SUCCESS; -} - -/** - * @brief Reads supported bus clock and switch card to appropriate mode. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] clk pointer to clock enum - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) { - - if (SDC_MODE_CARDTYPE_MMC == (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK)) { - return mmc_detect_bus_clk(sdcp, clk); - } - return sdc_detect_bus_clk(sdcp, clk); -} - -/** - * @brief Sets bus width for SDC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool sdc_set_bus_width(SDCDriver *sdcp) { - uint32_t resp[1]; - - if (SDC_MODE_1BIT == sdcp->config->bus_width) { - /* Nothing to do. Bus is already in 1bit mode.*/ - return HAL_SUCCESS; - } - else if (SDC_MODE_4BIT == sdcp->config->bus_width) { - sdc_lld_set_bus_mode(sdcp, SDC_MODE_4BIT); - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, sdcp->rca, resp) || - MMCSD_R1_ERROR(resp[0])) { - return HAL_FAILED; - } - - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BUS_WIDTH, 2, resp) || - MMCSD_R1_ERROR(resp[0])) { - return HAL_FAILED; - } - } - else { - /* SD card does not support 8bit bus.*/ - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Sets bus width for MMC. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -static bool mmc_set_bus_width(SDCDriver *sdcp) { - uint32_t resp[1]; - uint32_t cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 0, 0); - - switch(sdcp->config->bus_width){ - case SDC_MODE_1BIT: - /* Nothing to do. Bus is already in 1bit mode.*/ - return HAL_SUCCESS; - case SDC_MODE_4BIT: - cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 1, 0); - break; - case SDC_MODE_8BIT: - cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 2, 0); - break; - default: - osalDbgAssert(false, "unexpected case"); - break; - } - - sdc_lld_set_bus_mode(sdcp, sdcp->config->bus_width); - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SWITCH, cmdarg, resp) || - MMCSD_R1_ERROR(resp[0])) { - return HAL_FAILED; - } - - return HAL_SUCCESS; -} - -/** - * @brief Wait for the card to complete pending operations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @notapi - */ -bool _sdc_wait_for_transfer_state(SDCDriver *sdcp) { - uint32_t resp[1]; - - while (true) { - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_STATUS, - sdcp->rca, resp) || - MMCSD_R1_ERROR(resp[0])) { - return HAL_FAILED; - } - - switch (MMCSD_R1_STS(resp[0])) { - case MMCSD_STS_TRAN: - return HAL_SUCCESS; - case MMCSD_STS_DATA: - case MMCSD_STS_RCV: - case MMCSD_STS_PRG: -#if SDC_NICE_WAITING == TRUE - osalThreadSleepMilliseconds(1); -#endif - continue; - default: - /* The card should have been initialized so any other state is not - valid and is reported as an error.*/ - return HAL_FAILED; - } - } -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief SDC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void sdcInit(void) { - - sdc_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p SDCDriver structure. - * - * @param[out] sdcp pointer to the @p SDCDriver object - * - * @init - */ -void sdcObjectInit(SDCDriver *sdcp) { - - sdcp->vmt = &sdc_vmt; - sdcp->state = BLK_STOP; - sdcp->errors = SDC_NO_ERROR; - sdcp->config = NULL; - sdcp->capacity = 0; -} - -/** - * @brief Configures and activates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] config pointer to the @p SDCConfig object, can be @p NULL if - * the driver supports a default configuration or - * requires no configuration - * - * @api - */ -void sdcStart(SDCDriver *sdcp, const SDCConfig *config) { - - osalDbgCheck(sdcp != NULL); - - osalSysLock(); - osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), - "invalid state"); - sdcp->config = config; - sdc_lld_start(sdcp); - sdcp->state = BLK_ACTIVE; - osalSysUnlock(); -} - -/** - * @brief Deactivates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @api - */ -void sdcStop(SDCDriver *sdcp) { - - osalDbgCheck(sdcp != NULL); - - osalSysLock(); - osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), - "invalid state"); - sdc_lld_stop(sdcp); - sdcp->state = BLK_STOP; - osalSysUnlock(); -} - -/** - * @brief Performs the initialization procedure on the inserted card. - * @details This function should be invoked when a card is inserted and - * brings the driver in the @p BLK_READY state where it is possible - * to perform read and write operations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @api - */ -bool sdcConnect(SDCDriver *sdcp) { - uint32_t resp[1]; - sdcbusclk_t clk = SDC_CLK_25MHz; - - osalDbgCheck(sdcp != NULL); - osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), - "invalid state"); - - /* Connection procedure in progress.*/ - sdcp->state = BLK_CONNECTING; - - /* Card clock initialization.*/ - sdc_lld_start_clk(sdcp); - - /* Enforces the initial card state.*/ - sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); - - /* Detect card type.*/ - if (HAL_FAILED == mode_detect(sdcp)) { - goto failed; - } - - /* Perform specific initialization procedure.*/ - if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) { - if (HAL_FAILED == mmc_init(sdcp)) { - goto failed; - } - } - else { - if (HAL_FAILED == sdc_init(sdcp)) { - goto failed; - } - } - - /* Reads CID.*/ - if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_ALL_SEND_CID, 0, sdcp->cid)) { - goto failed; - } - - /* Asks for the RCA.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_RELATIVE_ADDR, - 0, &sdcp->rca)) { - goto failed; - } - - /* Reads CSD.*/ - if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_SEND_CSD, - sdcp->rca, sdcp->csd)) { - goto failed; - } - - /* Selects the card for operations.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEL_DESEL_CARD, - sdcp->rca, resp)) { - goto failed; - } - - /* Switches to high speed.*/ - if (HAL_SUCCESS != detect_bus_clk(sdcp, &clk)) { - goto failed; - } - sdc_lld_set_data_clk(sdcp, clk); - - /* Reads extended CSD if needed and possible.*/ - if (SDC_MODE_CARDTYPE_MMC == (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK)) { - - /* The card is a MMC, checking if it is a large device.*/ - if (_mmcsd_get_slice(sdcp->csd, MMCSD_CSD_MMC_CSD_STRUCTURE_SLICE) > 1U) { - uint8_t *ext_csd = sdcp->config->scratchpad; - - /* Size detection requires the buffer.*/ - if (NULL == ext_csd) { - goto failed; - } - - if(sdc_lld_read_special(sdcp, ext_csd, 512, MMCSD_CMD_SEND_EXT_CSD, 0)) { - goto failed; - } - - /* Capacity from the EXT_CSD.*/ - sdcp->capacity = _mmcsd_get_capacity_ext(ext_csd); - } - else { - /* Capacity from the normal CSD.*/ - sdcp->capacity = _mmcsd_get_capacity(sdcp->csd); - } - } - else { - /* The card is an SDC, capacity from the normal CSD.*/ - sdcp->capacity = _mmcsd_get_capacity(sdcp->csd); - } - - /* Block length fixed at 512 bytes.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BLOCKLEN, - MMCSD_BLOCK_SIZE, resp) || - MMCSD_R1_ERROR(resp[0])) { - goto failed; - } - - /* Switches to wide bus mode.*/ - switch (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) { - case SDC_MODE_CARDTYPE_SDV11: - case SDC_MODE_CARDTYPE_SDV20: - if (HAL_FAILED == sdc_set_bus_width(sdcp)) { - goto failed; - } - break; - case SDC_MODE_CARDTYPE_MMC: - if (HAL_FAILED == mmc_set_bus_width(sdcp)) { - goto failed; - } - break; - default: - /* Unknown type.*/ - goto failed; - } - - /* Initialization complete.*/ - sdcp->state = BLK_READY; - return HAL_SUCCESS; - - /* Connection failed, state reset to BLK_ACTIVE.*/ -failed: - sdc_lld_stop_clk(sdcp); - sdcp->state = BLK_ACTIVE; - return HAL_FAILED; -} - -/** - * @brief Brings the driver in a state safe for card removal. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @api - */ -bool sdcDisconnect(SDCDriver *sdcp) { - - osalDbgCheck(sdcp != NULL); - - osalSysLock(); - osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), - "invalid state"); - if (sdcp->state == BLK_ACTIVE) { - osalSysUnlock(); - return HAL_SUCCESS; - } - sdcp->state = BLK_DISCONNECTING; - osalSysUnlock(); - - /* Waits for eventual pending operations completion.*/ - if (_sdc_wait_for_transfer_state(sdcp)) { - sdc_lld_stop_clk(sdcp); - sdcp->state = BLK_ACTIVE; - return HAL_FAILED; - } - - /* Card clock stopped.*/ - sdc_lld_stop_clk(sdcp); - sdcp->state = BLK_ACTIVE; - return HAL_SUCCESS; -} - -/** - * @brief Reads one or more blocks. - * @pre The driver must be in the @p BLK_READY state after a successful - * sdcConnect() invocation. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] n number of blocks to read - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @api - */ -bool sdcRead(SDCDriver *sdcp, uint32_t startblk, uint8_t *buf, uint32_t n) { - bool status; - - osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0U)); - osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); - - if ((startblk + n - 1U) > sdcp->capacity){ - sdcp->errors |= SDC_OVERFLOW_ERROR; - return HAL_FAILED; - } - - /* Read operation in progress.*/ - sdcp->state = BLK_READING; - - status = sdc_lld_read(sdcp, startblk, buf, n); - - /* Read operation finished.*/ - sdcp->state = BLK_READY; - return status; -} - -/** - * @brief Writes one or more blocks. - * @pre The driver must be in the @p BLK_READY state after a successful - * sdcConnect() invocation. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval HAL_SUCCESS operation succeeded. - * @retval HAL_FAILED operation failed. - * - * @api - */ -bool sdcWrite(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n) { - bool status; - - osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0U)); - osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); - - if ((startblk + n - 1U) > sdcp->capacity){ - sdcp->errors |= SDC_OVERFLOW_ERROR; - return HAL_FAILED; - } - - /* Write operation in progress.*/ - sdcp->state = BLK_WRITING; - - status = sdc_lld_write(sdcp, startblk, buf, n); - - /* Write operation finished.*/ - sdcp->state = BLK_READY; - return status; -} - -/** - * @brief Returns the errors mask associated to the previous operation. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @return The errors mask. - * - * @api - */ -sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp) { - sdcflags_t flags; - - osalDbgCheck(sdcp != NULL); - osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); - - osalSysLock(); - flags = sdcp->errors; - sdcp->errors = SDC_NO_ERROR; - osalSysUnlock(); - return flags; -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool sdcSync(SDCDriver *sdcp) { - bool result; - - osalDbgCheck(sdcp != NULL); - - if (sdcp->state != BLK_READY) { - return HAL_FAILED; - } - - /* Synchronization operation in progress.*/ - sdcp->state = BLK_SYNCING; - - result = sdc_lld_sync(sdcp); - - /* Synchronization operation finished.*/ - sdcp->state = BLK_READY; - return result; -} - -/** - * @brief Returns the media info. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] bdip pointer to a @p BlockDeviceInfo structure - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) { - - osalDbgCheck((sdcp != NULL) && (bdip != NULL)); - - if (sdcp->state != BLK_READY) { - return HAL_FAILED; - } - - bdip->blk_num = sdcp->capacity; - bdip->blk_size = MMCSD_BLOCK_SIZE; - - return HAL_SUCCESS; -} - -/** - * @brief Erases the supplied blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk starting block number - * @param[in] endblk ending block number - * - * @return The operation status. - * @retval HAL_SUCCESS the operation succeeded. - * @retval HAL_FAILED the operation failed. - * - * @api - */ -bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) { - uint32_t resp[1]; - - osalDbgCheck((sdcp != NULL)); - osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); - - /* Erase operation in progress.*/ - sdcp->state = BLK_WRITING; - - /* Handling command differences between HC and normal cards.*/ - if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) != 0U) { - startblk *= MMCSD_BLOCK_SIZE; - endblk *= MMCSD_BLOCK_SIZE; - } - - if (_sdc_wait_for_transfer_state(sdcp)) { - goto failed; - } - - if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_START, - startblk, resp) != HAL_SUCCESS) || - MMCSD_R1_ERROR(resp[0])) { - goto failed; - } - - if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_END, - endblk, resp) != HAL_SUCCESS) || - MMCSD_R1_ERROR(resp[0])) { - goto failed; - } - - if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE, - 0, resp) != HAL_SUCCESS) || - MMCSD_R1_ERROR(resp[0])) { - goto failed; - } - - /* Quick sleep to allow it to transition to programming or receiving state */ - /* TODO: ??????????????????????????? */ - - /* Wait for it to return to transfer state to indicate it has finished erasing */ - if (_sdc_wait_for_transfer_state(sdcp)) { - goto failed; - } - - sdcp->state = BLK_READY; - return HAL_SUCCESS; - -failed: - sdcp->state = BLK_READY; - return HAL_FAILED; -} - -#endif /* HAL_USE_SDC == TRUE */ - -/** @} */ - diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c deleted file mode 100644 index a0956ba9a..000000000 --- a/os/hal/src/serial.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file serial.c - * @brief Serial Driver code. - * - * @addtogroup SERIAL - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/* - * Interface implementation, the following functions just invoke the equivalent - * queue-level function or macro. - */ - -static size_t write(void *ip, const uint8_t *bp, size_t n) { - - return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, - n, TIME_INFINITE); -} - -static size_t read(void *ip, uint8_t *bp, size_t n) { - - return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, - n, TIME_INFINITE); -} - -static msg_t put(void *ip, uint8_t b) { - - return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, TIME_INFINITE); -} - -static msg_t get(void *ip) { - - return iqGetTimeout(&((SerialDriver *)ip)->iqueue, TIME_INFINITE); -} - -static msg_t putt(void *ip, uint8_t b, systime_t timeout) { - - return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout); -} - -static msg_t gett(void *ip, systime_t timeout) { - - return iqGetTimeout(&((SerialDriver *)ip)->iqueue, timeout); -} - -static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) { - - return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, timeout); -} - -static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) { - - return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, timeout); -} - -static const struct SerialDriverVMT vmt = { - write, read, put, get, - putt, gett, writet, readt -}; - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Serial Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void sdInit(void) { - - sd_lld_init(); -} - -/** - * @brief Initializes a generic full duplex driver object. - * @details The HW dependent part of the initialization has to be performed - * outside, usually in the hardware initialization code. - * - * @param[out] sdp pointer to a @p SerialDriver structure - * @param[in] inotify pointer to a callback function that is invoked when - * some data is read from the Queue. The value can be - * @p NULL. - * @param[in] onotify pointer to a callback function that is invoked when - * some data is written in the Queue. The value can be - * @p NULL. - * - * @init - */ -void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { - - sdp->vmt = &vmt; - osalEventObjectInit(&sdp->event); - sdp->state = SD_STOP; - iqObjectInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); - oqObjectInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); -} - -/** - * @brief Configures and starts the driver. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration. - * If this parameter is set to @p NULL then a default - * configuration is used. - * - * @api - */ -void sdStart(SerialDriver *sdp, const SerialConfig *config) { - - osalDbgCheck(sdp != NULL); - - osalSysLock(); - osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), - "invalid state"); - sd_lld_start(sdp, config); - sdp->state = SD_READY; - osalSysUnlock(); -} - -/** - * @brief Stops the driver. - * @details Any thread waiting on the driver's queues will be awakened with - * the message @p MSG_RESET. - * - * @param[in] sdp pointer to a @p SerialDriver object - * - * @api - */ -void sdStop(SerialDriver *sdp) { - - osalDbgCheck(sdp != NULL); - - osalSysLock(); - osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), - "invalid state"); - sd_lld_stop(sdp); - sdp->state = SD_STOP; - oqResetI(&sdp->oqueue); - iqResetI(&sdp->iqueue); - osalOsRescheduleS(); - osalSysUnlock(); -} - -/** - * @brief Handles incoming data. - * @details This function must be called from the input interrupt service - * routine in order to enqueue incoming data and generate the - * related events. - * @note The incoming data event is only generated when the input queue - * becomes non-empty. - * @note In order to gain some performance it is suggested to not use - * this function directly but copy this code directly into the - * interrupt service routine. - * - * @param[in] sdp pointer to a @p SerialDriver structure - * @param[in] b the byte to be written in the driver's Input Queue - * - * @iclass - */ -void sdIncomingDataI(SerialDriver *sdp, uint8_t b) { - - osalDbgCheckClassI(); - osalDbgCheck(sdp != NULL); - - if (iqIsEmptyI(&sdp->iqueue)) - chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE); - if (iqPutI(&sdp->iqueue, b) < MSG_OK) - chnAddFlagsI(sdp, SD_OVERRUN_ERROR); -} - -/** - * @brief Handles outgoing data. - * @details Must be called from the output interrupt service routine in order - * to get the next byte to be transmitted. - * @note In order to gain some performance it is suggested to not use - * this function directly but copy this code directly into the - * interrupt service routine. - * - * @param[in] sdp pointer to a @p SerialDriver structure - * @return The byte value read from the driver's output queue. - * @retval MSG_TIMEOUT if the queue is empty (the lower driver usually - * disables the interrupt source when this happens). - * - * @iclass - */ -msg_t sdRequestDataI(SerialDriver *sdp) { - msg_t b; - - osalDbgCheckClassI(); - osalDbgCheck(sdp != NULL); - - b = oqGetI(&sdp->oqueue); - if (b < MSG_OK) - chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); - return b; -} - -/** - * @brief Direct output check on a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * checks directly the output queue. This is faster but cannot - * be used to check different channels implementations. - * - * @param[in] sdp pointer to a @p SerialDriver structure - * @return The queue status. - * @retval false if the next write operation would not block. - * @retval true if the next write operation would block. - * - * @deprecated - * - * @api - */ -bool sdPutWouldBlock(SerialDriver *sdp) { - bool b; - - osalSysLock(); - b = oqIsFullI(&sdp->oqueue); - osalSysUnlock(); - - return b; -} - -/** - * @brief Direct input check on a @p SerialDriver. - * @note This function bypasses the indirect access to the channel and - * checks directly the input queue. This is faster but cannot - * be used to check different channels implementations. - * - * @param[in] sdp pointer to a @p SerialDriver structure - * @return The queue status. - * @retval false if the next write operation would not block. - * @retval true if the next write operation would block. - * - * @deprecated - * - * @api - */ -bool sdGetWouldBlock(SerialDriver *sdp) { - bool b; - - osalSysLock(); - b = iqIsEmptyI(&sdp->iqueue); - osalSysUnlock(); - - return b; -} - -#endif /* HAL_USE_SERIAL == TRUE */ - -/** @} */ diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c deleted file mode 100644 index 9c21f7b56..000000000 --- a/os/hal/src/serial_usb.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file serial_usb.c - * @brief Serial over USB Driver code. - * - * @addtogroup SERIAL_USB - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/* - * Current Line Coding. - */ -static cdc_linecoding_t linecoding = { - {0x00, 0x96, 0x00, 0x00}, /* 38400. */ - LC_STOP_1, LC_PARITY_NONE, 8 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/* - * Interface implementation. - */ - -static size_t write(void *ip, const uint8_t *bp, size_t n) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return 0; - } - - return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp, - n, TIME_INFINITE); -} - -static size_t read(void *ip, uint8_t *bp, size_t n) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return 0; - } - - return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp, - n, TIME_INFINITE); -} - -static msg_t put(void *ip, uint8_t b) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return MSG_RESET; - } - - return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, TIME_INFINITE); -} - -static msg_t get(void *ip) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return MSG_RESET; - } - - return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, TIME_INFINITE); -} - -static msg_t putt(void *ip, uint8_t b, systime_t timeout) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return MSG_RESET; - } - - return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, timeout); -} - -static msg_t gett(void *ip, systime_t timeout) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return MSG_RESET; - } - - return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, timeout); -} - -static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return 0; - } - - return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp, n, timeout); -} - -static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) { - - if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE) { - return 0; - } - - return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp, n, timeout); -} - -static const struct SerialUSBDriverVMT vmt = { - write, read, put, get, - putt, gett, writet, readt -}; - -/** - * @brief Notification of empty buffer released into the input buffers queue. - * - * @param[in] bqp the buffers queue pointer. - */ -static void ibnotify(io_buffers_queue_t *bqp) { - SerialUSBDriver *sdup = bqGetLinkX(bqp); - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || - (sdup->state != SDU_READY)) { - return; - } - - /* Checking if there is already a transaction ongoing on the endpoint.*/ - if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) { - /* Trying to get a free buffer.*/ - uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue); - if (buf != NULL) { - /* Buffer found, starting a new transaction.*/ - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - } - } -} - -/** - * @brief Notification of filled buffer inserted into the output buffers queue. - * - * @param[in] bqp the buffers queue pointer. - */ -static void obnotify(io_buffers_queue_t *bqp) { - size_t n; - SerialUSBDriver *sdup = bqGetLinkX(bqp); - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || - (sdup->state != SDU_READY)) { - return; - } - - /* Checking if there is already a transaction ongoing on the endpoint.*/ - if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) { - /* Trying to get a full buffer.*/ - uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n); - if (buf != NULL) { - /* Buffer found, starting a new transaction.*/ - usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n); - } - } -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Serial Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void sduInit(void) { -} - -/** - * @brief Initializes a generic full duplex driver object. - * @details The HW dependent part of the initialization has to be performed - * outside, usually in the hardware initialization code. - * - * @param[out] sdup pointer to a @p SerialUSBDriver structure - * - * @init - */ -void sduObjectInit(SerialUSBDriver *sdup) { - - sdup->vmt = &vmt; - osalEventObjectInit(&sdup->event); - sdup->state = SDU_STOP; - ibqObjectInit(&sdup->ibqueue, sdup->ib, - SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER, - ibnotify, sdup); - obqObjectInit(&sdup->obqueue, sdup->ob, - SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER, - obnotify, sdup); -} - -/** - * @brief Configures and starts the driver. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * @param[in] config the serial over USB driver configuration - * - * @api - */ -void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { - USBDriver *usbp = config->usbp; - - osalDbgCheck(sdup != NULL); - - osalSysLock(); - osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), - "invalid state"); - usbp->in_params[config->bulk_in - 1U] = sdup; - usbp->out_params[config->bulk_out - 1U] = sdup; - if (config->int_in > 0U) { - usbp->in_params[config->int_in - 1U] = sdup; - } - sdup->config = config; - sdup->state = SDU_READY; - osalSysUnlock(); -} - -/** - * @brief Stops the driver. - * @details Any thread waiting on the driver's queues will be awakened with - * the message @p MSG_RESET. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * - * @api - */ -void sduStop(SerialUSBDriver *sdup) { - USBDriver *usbp = sdup->config->usbp; - - osalDbgCheck(sdup != NULL); - - osalSysLock(); - osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), - "invalid state"); - - /* Driver in stopped state.*/ - usbp->in_params[sdup->config->bulk_in - 1U] = NULL; - usbp->out_params[sdup->config->bulk_out - 1U] = NULL; - if (sdup->config->int_in > 0U) { - usbp->in_params[sdup->config->int_in - 1U] = NULL; - } - sdup->state = SDU_STOP; - - /* Enforces a disconnection.*/ - sduDisconnectI(sdup); - osalOsRescheduleS(); - osalSysUnlock(); -} - -/** - * @brief USB device disconnection handler. - * @note If this function is not called from an ISR then an explicit call - * to @p osalOsRescheduleS() in necessary afterward. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * - * @iclass - */ -void sduDisconnectI(SerialUSBDriver *sdup) { - - /* Queues reset in order to signal the driver stop to the application.*/ - chnAddFlagsI(sdup, CHN_DISCONNECTED); - ibqResetI(&sdup->ibqueue); - obqResetI(&sdup->obqueue); -} - -/** - * @brief USB device configured handler. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * - * @iclass - */ -void sduConfigureHookI(SerialUSBDriver *sdup) { - uint8_t *buf; - - ibqResetI(&sdup->ibqueue); - obqResetI(&sdup->obqueue); - chnAddFlagsI(sdup, CHN_CONNECTED); - - /* Starts the first OUT transaction immediately.*/ - buf = ibqGetEmptyBufferI(&sdup->ibqueue); - - osalDbgAssert(buf != NULL, "no free buffer"); - - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); -} - -/** - * @brief Default requests hook. - * @details Applications wanting to use the Serial over USB driver can use - * this function as requests hook in the USB configuration. - * The following requests are emulated: - * - CDC_GET_LINE_CODING. - * - CDC_SET_LINE_CODING. - * - CDC_SET_CONTROL_LINE_STATE. - * . - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The hook status. - * @retval true Message handled internally. - * @retval false Message not handled. - */ -bool sduRequestsHook(USBDriver *usbp) { - - if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { - switch (usbp->setup[1]) { - case CDC_GET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); - return true; - case CDC_SET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); - return true; - case CDC_SET_CONTROL_LINE_STATE: - /* Nothing to do, there are no control lines.*/ - usbSetupTransfer(usbp, NULL, 0, NULL); - return true; - default: - return false; - } - } - return false; -} - -/** - * @brief SOF handler. - * @details The SOF interrupt is used for automatic flushing of incomplete - * buffers pending in the output queue. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * - * @iclass - */ -void sduSOFHookI(SerialUSBDriver *sdup) { - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || - (sdup->state != SDU_READY)) { - return; - } - - /* If there is already a transaction ongoing then another one cannot be - started.*/ - if (usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) { - return; - } - - /* Checking if there only a buffer partially filled, if so then it is - enforced in the queue and transmitted.*/ - if (obqTryFlushI(&sdup->obqueue)) { - size_t n; - uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n); - - osalDbgAssert(buf != NULL, "queue is empty"); - - usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n); - } -} - -/** - * @brief Default data transmitted callback. - * @details The application must use this function as callback for the IN - * data endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep IN endpoint number - */ -void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { - uint8_t *buf; - size_t n; - SerialUSBDriver *sdup = usbp->in_params[ep - 1U]; - - if (sdup == NULL) { - return; - } - - osalSysLockFromISR(); - - /* Signaling that space is available in the output queue.*/ - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); - - /* Freeing the buffer just transmitted, if it was not a zero size packet.*/ - if (usbp->epc[ep]->in_state->txsize > 0U) { - obqReleaseEmptyBufferI(&sdup->obqueue); - } - - /* Checking if there is a buffer ready for transmission.*/ - buf = obqGetFullBufferI(&sdup->obqueue, &n); - - if (buf != NULL) { - /* The endpoint cannot be busy, we are in the context of the callback, - so it is safe to transmit without a check.*/ - usbStartTransmitI(usbp, ep, buf, n); - } - else if ((usbp->epc[ep]->in_state->txsize > 0U) && - ((usbp->epc[ep]->in_state->txsize & - ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) { - /* Transmit zero sized packet in case the last one has maximum allowed - size. Otherwise the recipient may expect more data coming soon and - not return buffered data to app. See section 5.8.3 Bulk Transfer - Packet Size Constraints of the USB Specification document.*/ - usbStartTransmitI(usbp, ep, usbp->setup, 0); - - } - else { - /* Nothing to transmit.*/ - } - - osalSysUnlockFromISR(); -} - -/** - * @brief Default data received callback. - * @details The application must use this function as callback for the OUT - * data endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep OUT endpoint number - */ -void sduDataReceived(USBDriver *usbp, usbep_t ep) { - uint8_t *buf; - SerialUSBDriver *sdup = usbp->out_params[ep - 1U]; - - if (sdup == NULL) { - return; - } - - osalSysLockFromISR(); - - /* Signaling that data is available in the input queue.*/ - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); - - /* Posting the filled buffer in the queue.*/ - ibqPostFullBufferI(&sdup->ibqueue, - usbGetReceiveTransactionSizeX(sdup->config->usbp, - sdup->config->bulk_out)); - - /* The endpoint cannot be busy, we are in the context of the callback, - so a packet is in the buffer for sure. Trying to get a free buffer - for the next transaction.*/ - buf = ibqGetEmptyBufferI(&sdup->ibqueue); - if (buf != NULL) { - /* Buffer found, starting a new transaction.*/ - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - } - osalSysUnlockFromISR(); -} - -/** - * @brief Default data received callback. - * @details The application must use this function as callback for the IN - * interrupt endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - */ -void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - (void)ep; -} - -#endif /* HAL_USE_SERIAL_USB == TRUE */ - -/** @} */ diff --git a/os/hal/src/spi.c b/os/hal/src/spi.c deleted file mode 100644 index 90907e8f4..000000000 --- a/os/hal/src/spi.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file spi.c - * @brief SPI Driver code. - * - * @addtogroup SPI - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief SPI Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void spiInit(void) { - - spi_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p SPIDriver structure. - * - * @param[out] spip pointer to the @p SPIDriver object - * - * @init - */ -void spiObjectInit(SPIDriver *spip) { - - spip->state = SPI_STOP; - spip->config = NULL; -#if SPI_USE_WAIT == TRUE - spip->thread = NULL; -#endif -#if SPI_USE_MUTUAL_EXCLUSION == TRUE - osalMutexObjectInit(&spip->mutex); -#endif -#if defined(SPI_DRIVER_EXT_INIT_HOOK) - SPI_DRIVER_EXT_INIT_HOOK(spip); -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] config pointer to the @p SPIConfig object - * - * @api - */ -void spiStart(SPIDriver *spip, const SPIConfig *config) { - - osalDbgCheck((spip != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), - "invalid state"); - spip->config = config; - spi_lld_start(spip); - spip->state = SPI_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the SPI peripheral. - * @note Deactivating the peripheral also enforces a release of the slave - * select line. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiStop(SPIDriver *spip) { - - osalDbgCheck(spip != NULL); - - osalSysLock(); - osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), - "invalid state"); - spi_lld_stop(spip); - spip->state = SPI_STOP; - osalSysUnlock(); -} - -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiSelect(SPIDriver *spip) { - - osalDbgCheck(spip != NULL); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - spiSelectI(spip); - osalSysUnlock(); -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiUnselect(SPIDriver *spip) { - - osalDbgCheck(spip != NULL); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - spiUnselectI(spip); - osalSysUnlock(); -} - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @api - */ -void spiStartIgnore(SPIDriver *spip, size_t n) { - - osalDbgCheck((spip != NULL) && (n > 0U)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - spiStartIgnoreI(spip, n); - osalSysUnlock(); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiStartExchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - osalDbgCheck((spip != NULL) && (n > 0U) && - (rxbuf != NULL) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - spiStartExchangeI(spip, n, txbuf, rxbuf); - osalSysUnlock(); -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @api - */ -void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { - - osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - spiStartSendI(spip, n, txbuf); - osalSysUnlock(); -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { - - osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - spiStartReceiveI(spip, n, rxbuf); - osalSysUnlock(); -} - -#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Ignores data on the SPI bus. - * @details This synchronous function performs the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @api - */ -void spiIgnore(SPIDriver *spip, size_t n) { - - osalDbgCheck((spip != NULL) && (n > 0U)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, "has callback"); - spiStartIgnoreI(spip, n); - (void) osalThreadSuspendS(&spip->thread); - osalSysUnlock(); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This synchronous function performs a simultaneous transmit/receive - * operation. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiExchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - osalDbgCheck((spip != NULL) && (n > 0U) && - (rxbuf != NULL) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, "has callback"); - spiStartExchangeI(spip, n, txbuf, rxbuf); - (void) osalThreadSuspendS(&spip->thread); - osalSysUnlock(); -} - -/** - * @brief Sends data over the SPI bus. - * @details This synchronous function performs a transmit operation. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @api - */ -void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { - - osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, "has callback"); - spiStartSendI(spip, n, txbuf); - (void) osalThreadSuspendS(&spip->thread); - osalSysUnlock(); -} - -/** - * @brief Receives data from the SPI bus. - * @details This synchronous function performs a receive operation. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { - - osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL)); - - osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, "has callback"); - spiStartReceiveI(spip, n, rxbuf); - (void) osalThreadSuspendS(&spip->thread); - osalSysUnlock(); -} -#endif /* SPI_USE_WAIT == TRUE */ - -#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the SPI bus. - * @details This function tries to gain ownership to the SPI bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiAcquireBus(SPIDriver *spip) { - - osalDbgCheck(spip != NULL); - - osalMutexLock(&spip->mutex); -} - -/** - * @brief Releases exclusive access to the SPI bus. - * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiReleaseBus(SPIDriver *spip) { - - osalDbgCheck(spip != NULL); - - osalMutexUnlock(&spip->mutex); -} -#endif /* SPI_USE_MUTUAL_EXCLUSION == TRUE */ - -#endif /* HAL_USE_SPI == TRUE */ - -/** @} */ diff --git a/os/hal/src/st.c b/os/hal/src/st.c deleted file mode 100644 index cf654f882..000000000 --- a/os/hal/src/st.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file st.c - * @brief ST Driver code. - * - * @addtogroup ST - * @{ - */ - -#include "hal.h" - -#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief ST Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void stInit(void) { - - st_lld_init(); -} - - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @param[in] abstime the time to be set for the first alarm - * - * @api - */ -void stStartAlarm(systime_t abstime) { - - osalDbgAssert(stIsAlarmActive() == false, "already active"); - - st_lld_start_alarm(abstime); -} - -/** - * @brief Stops the alarm interrupt. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @api - */ -void stStopAlarm(void) { - - st_lld_stop_alarm(); -} - -/** - * @brief Sets the alarm time. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @param[in] abstime the time to be set for the next alarm - * - * @api - */ -void stSetAlarm(systime_t abstime) { - - osalDbgAssert(stIsAlarmActive() != false, "not active"); - - st_lld_set_alarm(abstime); -} - -/** - * @brief Returns the current alarm time. - * @note This functionality is only available in free running mode, the - * behavior in periodic mode is undefined. - * - * @return The currently set alarm time. - * - * @api - */ -systime_t stGetAlarm(void) { - - osalDbgAssert(stIsAlarmActive() != false, "not active"); - - return st_lld_get_alarm(); -} - -#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ - -/** @} */ diff --git a/os/hal/src/uart.c b/os/hal/src/uart.c deleted file mode 100644 index 7bf0e5d74..000000000 --- a/os/hal/src/uart.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file uart.c - * @brief UART Driver code. - * - * @addtogroup UART - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief UART Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void uartInit(void) { - - uart_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p UARTDriver structure. - * - * @param[out] uartp pointer to the @p UARTDriver object - * - * @init - */ -void uartObjectInit(UARTDriver *uartp) { - - uartp->state = UART_STOP; - uartp->txstate = UART_TX_IDLE; - uartp->rxstate = UART_RX_IDLE; - uartp->config = NULL; -#if UART_USE_WAIT == TRUE - uartp->early = false; - uartp->threadrx = NULL; - uartp->threadtx = NULL; -#endif /* UART_USE_WAIT */ -#if UART_USE_MUTUAL_EXCLUSION == TRUE - osalMutexObjectInit(&uartp->mutex); -#endif /* UART_USE_MUTUAL_EXCLUSION */ - - /* Optional, user-defined initializer.*/ -#if defined(UART_DRIVER_EXT_INIT_HOOK) - UART_DRIVER_EXT_INIT_HOOK(uartp); -#endif -} - -/** - * @brief Configures and activates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] config pointer to the @p UARTConfig object - * - * @api - */ -void uartStart(UARTDriver *uartp, const UARTConfig *config) { - - osalDbgCheck((uartp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), - "invalid state"); - - uartp->config = config; - uart_lld_start(uartp); - uartp->state = UART_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @api - */ -void uartStop(UARTDriver *uartp) { - - osalDbgCheck(uartp != NULL); - - osalSysLock(); - osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), - "invalid state"); - - uart_lld_stop(uartp); - uartp->state = UART_STOP; - uartp->txstate = UART_TX_IDLE; - uartp->rxstate = UART_RX_IDLE; - osalSysUnlock(); -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @api - */ -void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf) { - - osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); - - uart_lld_start_send(uartp, n, txbuf); - uartp->txstate = UART_TX_ACTIVE; - osalSysUnlock(); -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @iclass - */ -void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) { - - osalDbgCheckClassI(); - osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL)); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); - - uart_lld_start_send(uartp, n, txbuf); - uartp->txstate = UART_TX_ACTIVE; -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * @retval 0 There was no transmit operation in progress. - * - * @api - */ -size_t uartStopSend(UARTDriver *uartp) { - size_t n; - - osalDbgCheck(uartp != NULL); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "not active"); - - if (uartp->txstate == UART_TX_ACTIVE) { - n = uart_lld_stop_send(uartp); - uartp->txstate = UART_TX_IDLE; - } - else { - n = 0; - } - osalSysUnlock(); - - return n; -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * @retval 0 There was no transmit operation in progress. - * - * @iclass - */ -size_t uartStopSendI(UARTDriver *uartp) { - - osalDbgCheckClassI(); - osalDbgCheck(uartp != NULL); - osalDbgAssert(uartp->state == UART_READY, "not active"); - - if (uartp->txstate == UART_TX_ACTIVE) { - size_t n = uart_lld_stop_send(uartp); - uartp->txstate = UART_TX_IDLE; - return n; - } - return 0; -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to receive - * @param[in] rxbuf the pointer to the receive buffer - * - * @api - */ -void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) { - - osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL)); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); - - uart_lld_start_receive(uartp, n, rxbuf); - uartp->rxstate = UART_RX_ACTIVE; - osalSysUnlock(); -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @iclass - */ -void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) { - - osalDbgCheckClassI(); - osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL)); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); - - uart_lld_start_receive(uartp, n, rxbuf); - uartp->rxstate = UART_RX_ACTIVE; -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * @retval 0 There was no receive operation in progress. - * - * @api - */ -size_t uartStopReceive(UARTDriver *uartp) { - size_t n; - - osalDbgCheck(uartp != NULL); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "not active"); - - if (uartp->rxstate == UART_RX_ACTIVE) { - n = uart_lld_stop_receive(uartp); - uartp->rxstate = UART_RX_IDLE; - } - else { - n = 0; - } - osalSysUnlock(); - - return n; -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * @retval 0 There was no receive operation in progress. - * - * @iclass - */ -size_t uartStopReceiveI(UARTDriver *uartp) { - - osalDbgCheckClassI(); - osalDbgCheck(uartp != NULL); - osalDbgAssert(uartp->state == UART_READY, "not active"); - - if (uartp->rxstate == UART_RX_ACTIVE) { - size_t n = uart_lld_stop_receive(uartp); - uartp->rxstate = UART_RX_IDLE; - return n; - } - return 0; -} - -#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Performs a transmission on the UART peripheral. - * @note The function returns when the specified number of frames have been - * sent to the UART or on timeout. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in,out] np number of data frames to transmit, on exit the number - * of frames actually transmitted - * @param[in] txbuf the pointer to the transmit buffer - * @param[in] timeout operation timeout - * @return The operation status. - * @retval MSG_OK if the operation completed successfully. - * @retval MSG_TIMEOUT if the operation timed out. - * - * @api - */ -msg_t uartSendTimeout(UARTDriver *uartp, size_t *np, - const void *txbuf, systime_t timeout) { - msg_t msg; - - osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); - - /* Transmission start.*/ - uartp->early = true; - uart_lld_start_send(uartp, *np, txbuf); - uartp->txstate = UART_TX_ACTIVE; - - /* Waiting for result.*/ - msg = osalThreadSuspendTimeoutS(&uartp->threadtx, timeout); - if (msg != MSG_OK) { - *np = uartStopSendI(uartp); - } - osalSysUnlock(); - - return msg; -} - -/** - * @brief Performs a transmission on the UART peripheral. - * @note The function returns when the specified number of frames have been - * physically transmitted or on timeout. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in,out] np number of data frames to transmit, on exit the number - * of frames actually transmitted - * @param[in] txbuf the pointer to the transmit buffer - * @param[in] timeout operation timeout - * @return The operation status. - * @retval MSG_OK if the operation completed successfully. - * @retval MSG_TIMEOUT if the operation timed out. - * - * @api - */ -msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np, - const void *txbuf, systime_t timeout) { - msg_t msg; - - osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL)); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); - - /* Transmission start.*/ - uartp->early = false; - uart_lld_start_send(uartp, *np, txbuf); - uartp->txstate = UART_TX_ACTIVE; - - /* Waiting for result.*/ - msg = osalThreadSuspendTimeoutS(&uartp->threadtx, timeout); - if (msg != MSG_OK) { - *np = uartStopSendI(uartp); - } - osalSysUnlock(); - - return msg; -} - -/** - * @brief Performs a receive operation on the UART peripheral. - * @note The function returns when the specified number of frames have been - * received or on error/timeout. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in,out] np number of data frames to receive, on exit the number - * of frames actually received - * @param[in] rxbuf the pointer to the receive buffer - * @param[in] timeout operation timeout - * - * @return The operation status. - * @retval MSG_OK if the operation completed successfully. - * @retval MSG_TIMEOUT if the operation timed out. - * @retval MSG_RESET in case of a receive error. - * - * @api - */ -msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np, - void *rxbuf, systime_t timeout) { - msg_t msg; - - osalDbgCheck((uartp != NULL) && (*np > 0U) && (rxbuf != NULL)); - - osalSysLock(); - osalDbgAssert(uartp->state == UART_READY, "is active"); - osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); - - /* Receive start.*/ - uart_lld_start_receive(uartp, *np, rxbuf); - uartp->rxstate = UART_RX_ACTIVE; - - /* Waiting for result.*/ - msg = osalThreadSuspendTimeoutS(&uartp->threadrx, timeout); - if (msg != MSG_OK) { - *np = uartStopReceiveI(uartp); - } - osalSysUnlock(); - - return msg; -} -#endif - -#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the UART bus. - * @details This function tries to gain ownership to the UART bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @api - */ -void uartAcquireBus(UARTDriver *uartp) { - - osalDbgCheck(uartp != NULL); - - osalMutexLock(&uartp->mutex); -} - -/** - * @brief Releases exclusive access to the UART bus. - * @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @api - */ -void uartReleaseBus(UARTDriver *uartp) { - - osalDbgCheck(uartp != NULL); - - osalMutexUnlock(&uartp->mutex); -} -#endif - -#endif /* HAL_USE_UART == TRUE */ - -/** @} */ diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c deleted file mode 100644 index d9fbc091a..000000000 --- a/os/hal/src/usb.c +++ /dev/null @@ -1,950 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file usb.c - * @brief USB Driver code. - * - * @addtogroup USB - * @{ - */ - -#include - -#include "hal.h" - -#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint8_t zero_status[] = {0x00, 0x00}; -static const uint8_t active_status[] ={0x00, 0x00}; -static const uint8_t halted_status[] = {0x01, 0x00}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static uint16_t get_hword(uint8_t *p) { - uint16_t hw; - - hw = (uint16_t)*p++; - hw |= (uint16_t)*p << 8U; - return hw; -} - -/** - * @brief SET ADDRESS transaction callback. - * - * @param[in] usbp pointer to the @p USBDriver object - */ -static void set_address(USBDriver *usbp) { - - usbp->address = usbp->setup[2]; - usb_lld_set_address(usbp); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_ADDRESS); - usbp->state = USB_SELECTED; -} - -/** - * @brief Standard requests handler. - * @details This is the standard requests default handler, most standard - * requests are handled here, the user can override the standard - * handling using the @p requests_hook_cb hook in the - * @p USBConfig structure. - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The request handling exit code. - * @retval false Request not recognized by the handler or error. - * @retval true Request handled. - */ -static bool default_handler(USBDriver *usbp) { - const USBDescriptor *dp; - - /* Decoding the request.*/ - switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | - USB_RTYPE_TYPE_MASK)) | - ((uint32_t)usbp->setup[1] << 8U))) { - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_STATUS << 8): - /* Just returns the current status word.*/ - usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL); - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8): - /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature - number is handled as an error.*/ - if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { - usbp->status &= ~2U; - usbSetupTransfer(usbp, NULL, 0, NULL); - return true; - } - return false; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_FEATURE << 8): - /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature - number is handled as an error.*/ - if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { - usbp->status |= 2U; - usbSetupTransfer(usbp, NULL, 0, NULL); - return true; - } - return false; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_ADDRESS << 8): - /* The SET_ADDRESS handling can be performed here or postponed after - the status packed depending on the USB_SET_ADDRESS_MODE low - driver setting.*/ -#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS - if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) && - (usbp->setup[1] == USB_REQ_SET_ADDRESS)) { - set_address(usbp); - } - usbSetupTransfer(usbp, NULL, 0, NULL); -#else - usbSetupTransfer(usbp, NULL, 0, set_address); -#endif - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8): - /* Handling descriptor requests from the host.*/ - dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], - usbp->setup[2], - get_hword(&usbp->setup[4])); - if (dp == NULL) { - return false; - } - /*lint -save -e9005 [11.8] Removing const is fine.*/ - usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); - /*lint -restore*/ - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_CONFIGURATION << 8): - /* Returning the last selected configuration.*/ - usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_CONFIGURATION << 8): - /* Handling configuration selection from the host.*/ - usbp->configuration = usbp->setup[2]; - if (usbp->configuration == 0U) { - usbp->state = USB_SELECTED; - } - else { - usbp->state = USB_ACTIVE; - } - _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); - usbSetupTransfer(usbp, NULL, 0, NULL); - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_STATUS << 8): - case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SYNCH_FRAME << 8): - /* Just sending two zero bytes, the application can change the behavior - using a hook..*/ - /*lint -save -e9005 [11.8] Removing const is fine.*/ - usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL); - /*lint -restore*/ - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_GET_STATUS << 8): - /* Sending the EP status.*/ - if ((usbp->setup[4] & 0x80U) != 0U) { - switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) { - case EP_STATUS_STALLED: - /*lint -save -e9005 [11.8] Removing const is fine.*/ - usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); - /*lint -restore*/ - return true; - case EP_STATUS_ACTIVE: - /*lint -save -e9005 [11.8] Removing const is fine.*/ - usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); - /*lint -restore*/ - return true; - case EP_STATUS_DISABLED: - default: - return false; - } - } - else { - switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) { - case EP_STATUS_STALLED: - /*lint -save -e9005 [11.8] Removing const is fine.*/ - usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); - /*lint -restore*/ - return true; - case EP_STATUS_ACTIVE: - /*lint -save -e9005 [11.8] Removing const is fine.*/ - usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); - /*lint -restore*/ - return true; - case EP_STATUS_DISABLED: - default: - return false; - } - } - case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8): - /* Only ENDPOINT_HALT is handled as feature.*/ - if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) { - return false; - } - /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/ - if ((usbp->setup[4] & 0x0FU) != 0U) { - if ((usbp->setup[4] & 0x80U) != 0U) { - usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU); - } - else { - usb_lld_clear_out(usbp, usbp->setup[4] & 0x0FU); - } - } - usbSetupTransfer(usbp, NULL, 0, NULL); - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SET_FEATURE << 8): - /* Only ENDPOINT_HALT is handled as feature.*/ - if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) { - return false; - } - /* Stalling the EP, not valid for EP0, it is ignored in that case.*/ - if ((usbp->setup[4] & 0x0FU) != 0U) { - if ((usbp->setup[4] & 0x80U) != 0U) { - usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU); - } - else { - usb_lld_stall_out(usbp, usbp->setup[4] & 0x0FU); - } - } - usbSetupTransfer(usbp, NULL, 0, NULL); - return true; - case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_DESCRIPTOR << 8): - case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8): - case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_FEATURE << 8): - case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_INTERFACE << 8): - case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_INTERFACE << 8): - /* All the above requests are not handled here, if you need them then - use the hook mechanism and provide handling.*/ - default: - return false; - } -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief USB Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void usbInit(void) { - - usb_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p USBDriver structure. - * - * @param[out] usbp pointer to the @p USBDriver object - * - * @init - */ -void usbObjectInit(USBDriver *usbp) { - unsigned i; - - usbp->state = USB_STOP; - usbp->config = NULL; - for (i = 0; i < (unsigned)USB_MAX_ENDPOINTS; i++) { - usbp->in_params[i] = NULL; - usbp->out_params[i] = NULL; - } - usbp->transmitting = 0; - usbp->receiving = 0; -} - -/** - * @brief Configures and activates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] config pointer to the @p USBConfig object - * - * @api - */ -void usbStart(USBDriver *usbp, const USBConfig *config) { - unsigned i; - - osalDbgCheck((usbp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY), - "invalid state"); - usbp->config = config; - for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { - usbp->epc[i] = NULL; - } - usb_lld_start(usbp); - usbp->state = USB_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @api - */ -void usbStop(USBDriver *usbp) { - unsigned i; - - osalDbgCheck(usbp != NULL); - - osalSysLock(); - osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) || - (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) || - (usbp->state == USB_SUSPENDED), - "invalid state"); - usb_lld_stop(usbp); - usbp->state = USB_STOP; - - /* Resetting all ongoing synchronous operations.*/ - for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { -#if USB_USE_WAIT == TRUE - if (usbp->epc[i] != NULL) { - if (usbp->epc[i]->in_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); - } - if (usbp->epc[i]->out_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); - } - } -#endif - usbp->epc[i] = NULL; - } - osalOsRescheduleS(); - osalSysUnlock(); -} - -/** - * @brief Enables an endpoint. - * @details This function enables an endpoint, both IN and/or OUT directions - * depending on the configuration structure. - * @note This function must be invoked in response of a SET_CONFIGURATION - * or SET_INTERFACE message. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[in] epcp the endpoint configuration - * - * @iclass - */ -void usbInitEndpointI(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp) { - - osalDbgCheckClassI(); - osalDbgCheck((usbp != NULL) && (epcp != NULL)); - osalDbgAssert(usbp->state == USB_ACTIVE, - "invalid state"); - osalDbgAssert(usbp->epc[ep] == NULL, "already initialized"); - - /* Logically enabling the endpoint in the USBDriver structure.*/ - usbp->epc[ep] = epcp; - - /* Clearing the state structures, custom fields as well.*/ - if (epcp->in_state != NULL) { - memset(epcp->in_state, 0, sizeof(USBInEndpointState)); - } - if (epcp->out_state != NULL) { - memset(epcp->out_state, 0, sizeof(USBOutEndpointState)); - } - - /* Low level endpoint activation.*/ - usb_lld_init_endpoint(usbp, ep); -} - -/** - * @brief Disables all the active endpoints. - * @details This function disables all the active endpoints except the - * endpoint zero. - * @note This function must be invoked in response of a SET_CONFIGURATION - * message with configuration number zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @iclass - */ -void usbDisableEndpointsI(USBDriver *usbp) { - unsigned i; - - osalDbgCheckClassI(); - osalDbgCheck(usbp != NULL); - osalDbgAssert(usbp->state == USB_SELECTED, "invalid state"); - - usbp->transmitting &= ~1U; - usbp->receiving &= ~1U; - for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { -#if USB_USE_WAIT == TRUE - /* Signaling the event to threads waiting on endpoints.*/ - if (usbp->epc[i] != NULL) { - osalSysLockFromISR(); - if (usbp->epc[i]->in_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); - } - if (usbp->epc[i]->out_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); - } - osalSysUnlockFromISR(); - } -#endif - usbp->epc[i] = NULL; - } - - /* Low level endpoints deactivation.*/ - usb_lld_disable_endpoints(usbp); -} - -/** - * @brief Starts a receive transaction on an OUT endpoint. - * @note This function is meant to be called from ISR context outside - * critical zones because there is a potentially slow operation - * inside. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the received data - * @param[in] n transaction size. It is recommended a multiple of - * the packet size because the excess is discarded. - * - * @iclass - */ -void usbStartReceiveI(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n) { - USBOutEndpointState *osp; - - osalDbgCheckClassI(); - osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS)); - osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving"); - - /* Marking the endpoint as active.*/ - usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); - - /* Setting up the transfer.*/ - /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ - osp = usbp->epc[ep]->out_state; - /*lint -restore*/ - osp->rxbuf = buf; - osp->rxsize = n; - osp->rxcnt = 0; -#if USB_USE_WAIT == TRUE - osp->thread = NULL; -#endif - - /* Starting transfer.*/ - usb_lld_start_out(usbp, ep); -} - -/** - * @brief Starts a transmit transaction on an IN endpoint. - * @note This function is meant to be called from ISR context outside - * critical zones because there is a potentially slow operation - * inside. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[in] buf buffer where to fetch the data to be transmitted - * @param[in] n transaction size - * - * @iclass - */ -void usbStartTransmitI(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { - USBInEndpointState *isp; - - osalDbgCheckClassI(); - osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS)); - osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting"); - - /* Marking the endpoint as active.*/ - usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); - - /* Setting up the transfer.*/ - /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ - isp = usbp->epc[ep]->in_state; - /*lint -restore*/ - isp->txbuf = buf; - isp->txsize = n; - isp->txcnt = 0; -#if USB_USE_WAIT == TRUE - isp->thread = NULL; -#endif - - /* Starting transfer.*/ - usb_lld_start_in(usbp, ep); -} - -#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Performs a receive transaction on an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the received data - * @param[in] n transaction size. It is recommended a multiple of - * the packet size because the excess is discarded. - * - * @return The received effective data size, it can be less than - * the amount specified. - * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation - * has been aborted by an USB reset or a transition to - * the @p USB_SUSPENDED state. - * - * @api - */ -msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { - msg_t msg; - - osalSysLock(); - - if (usbGetDriverStateI(usbp) != USB_ACTIVE) { - osalSysUnlock(); - return MSG_RESET; - } - - usbStartReceiveI(usbp, ep, buf, n); - msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread); - osalSysUnlock(); - - return msg; -} - -/** - * @brief Performs a transmit transaction on an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[in] buf buffer where to fetch the data to be transmitted - * @param[in] n transaction size - * - * @return The operation status. - * @retval MSG_OK operation performed successfully. - * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation - * has been aborted by an USB reset or a transition to - * the @p USB_SUSPENDED state. - * - * @api - */ -msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) { - msg_t msg; - - osalSysLock(); - - if (usbGetDriverStateI(usbp) != USB_ACTIVE) { - osalSysUnlock(); - return MSG_RESET; - } - - usbStartTransmitI(usbp, ep, buf, n); - msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread); - osalSysUnlock(); - - return msg; -} -#endif /* USB_USE_WAIT == TRUE */ - -/** - * @brief Stalls an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @return The operation status. - * @retval false Endpoint stalled. - * @retval true Endpoint busy, not stalled. - * - * @iclass - */ -bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) { - - osalDbgCheckClassI(); - osalDbgCheck(usbp != NULL); - - if (usbGetReceiveStatusI(usbp, ep)) { - return true; - } - - usb_lld_stall_out(usbp, ep); - return false; -} - -/** - * @brief Stalls an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @return The operation status. - * @retval false Endpoint stalled. - * @retval true Endpoint busy, not stalled. - * - * @iclass - */ -bool usbStallTransmitI(USBDriver *usbp, usbep_t ep) { - - osalDbgCheckClassI(); - osalDbgCheck(usbp != NULL); - - if (usbGetTransmitStatusI(usbp, ep)) { - return true; - } - - usb_lld_stall_in(usbp, ep); - return false; -} - -/** - * @brief USB reset routine. - * @details This function must be invoked when an USB bus reset condition is - * detected. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void _usb_reset(USBDriver *usbp) { - unsigned i; - - /* State transition.*/ - usbp->state = USB_READY; - - /* Resetting internal state.*/ - usbp->status = 0; - usbp->address = 0; - usbp->configuration = 0; - usbp->transmitting = 0; - usbp->receiving = 0; - - /* Invalidates all endpoints into the USBDriver structure.*/ - for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { -#if USB_USE_WAIT == TRUE - /* Signaling the event to threads waiting on endpoints.*/ - if (usbp->epc[i] != NULL) { - osalSysLockFromISR(); - if (usbp->epc[i]->in_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); - } - if (usbp->epc[i]->out_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); - } - osalSysUnlockFromISR(); - } -#endif - usbp->epc[i] = NULL; - } - - /* EP0 state machine initialization.*/ - usbp->ep0state = USB_EP0_WAITING_SETUP; - - /* Low level reset.*/ - usb_lld_reset(usbp); - - /* Notification of reset event.*/ - _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); -} - -/** - * @brief USB suspend routine. - * @details This function must be invoked when an USB bus suspend condition is - * detected. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void _usb_suspend(USBDriver *usbp) { - - /* State transition.*/ - usbp->state = USB_SUSPENDED; - - /* Notification of suspend event.*/ - _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND); - - /* Signaling the event to threads waiting on endpoints.*/ -#if USB_USE_WAIT == TRUE - { - unsigned i; - - for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { - if (usbp->epc[i] != NULL) { - osalSysLockFromISR(); - if (usbp->epc[i]->in_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); - } - if (usbp->epc[i]->out_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); - } - osalSysUnlockFromISR(); - } - } - } -#endif -} - -/** - * @brief USB wake-up routine. - * @details This function must be invoked when an USB bus wake-up condition is - * detected. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void _usb_wakeup(USBDriver *usbp) { - - /* State transition.*/ - usbp->state = USB_ACTIVE; - - /* Notification of suspend event.*/ - _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); -} - -/** - * @brief Default EP0 SETUP callback. - * @details This function is used by the low level driver as default handler - * for EP0 SETUP events. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number, always zero - * - * @notapi - */ -void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { - size_t max; - - usbp->ep0state = USB_EP0_WAITING_SETUP; - usbReadSetup(usbp, ep, usbp->setup); - - /* First verify if the application has an handler installed for this - request.*/ - /*lint -save -e9007 [13.5] No side effects, it is intentional.*/ - if ((usbp->config->requests_hook_cb == NULL) || - !(usbp->config->requests_hook_cb(usbp))) { - /*lint -restore*/ - /* Invoking the default handler, if this fails then stalls the - endpoint zero as error.*/ - /*lint -save -e9007 [13.5] No side effects, it is intentional.*/ - if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) || - !default_handler(usbp)) { - /*lint -restore*/ - /* Error response, the state machine goes into an error state, the low - level layer will have to reset it to USB_EP0_WAITING_SETUP after - receiving a SETUP packet.*/ - usb_lld_stall_in(usbp, 0); - usb_lld_stall_out(usbp, 0); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); - usbp->ep0state = USB_EP0_ERROR; - return; - } - } -#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW) - if (usbp->setup[1] == USB_REQ_SET_ADDRESS) { - /* Zero-length packet sent by hardware */ - return; - } -#endif - /* Transfer preparation. The request handler must have populated - correctly the fields ep0next, ep0n and ep0endcb using the macro - usbSetupTransfer().*/ - max = (size_t)get_hword(&usbp->setup[6]); - /* The transfer size cannot exceed the specified amount.*/ - if (usbp->ep0n > max) { - usbp->ep0n = max; - } - if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) { - /* IN phase.*/ - if (usbp->ep0n != 0U) { - /* Starts the transmit phase.*/ - usbp->ep0state = USB_EP0_TX; - osalSysLockFromISR(); - usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n); - osalSysUnlockFromISR(); - } - else { - /* No transmission phase, directly receiving the zero sized status - packet.*/ - usbp->ep0state = USB_EP0_WAITING_STS; -#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - osalSysLockFromISR(); - usbStartReceiveI(usbp, 0, NULL, 0); - osalSysUnlockFromISR(); -#else - usb_lld_end_setup(usbp, ep); -#endif - } - } - else { - /* OUT phase.*/ - if (usbp->ep0n != 0U) { - /* Starts the receive phase.*/ - usbp->ep0state = USB_EP0_RX; - osalSysLockFromISR(); - usbStartReceiveI(usbp, 0, usbp->ep0next, usbp->ep0n); - osalSysUnlockFromISR(); - } - else { - /* No receive phase, directly sending the zero sized status - packet.*/ - usbp->ep0state = USB_EP0_SENDING_STS; -#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - osalSysLockFromISR(); - usbStartTransmitI(usbp, 0, NULL, 0); - osalSysUnlockFromISR(); -#else - usb_lld_end_setup(usbp, ep); -#endif - } - } -} - -/** - * @brief Default EP0 IN callback. - * @details This function is used by the low level driver as default handler - * for EP0 IN events. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number, always zero - * - * @notapi - */ -void _usb_ep0in(USBDriver *usbp, usbep_t ep) { - size_t max; - - (void)ep; - switch (usbp->ep0state) { - case USB_EP0_TX: - max = (size_t)get_hword(&usbp->setup[6]); - /* If the transmitted size is less than the requested size and it is a - multiple of the maximum packet size then a zero size packet must be - transmitted.*/ - if ((usbp->ep0n < max) && - ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) { - osalSysLockFromISR(); - usbStartTransmitI(usbp, 0, NULL, 0); - osalSysUnlockFromISR(); - usbp->ep0state = USB_EP0_WAITING_TX0; - return; - } - /* Falls into, it is intentional.*/ - case USB_EP0_WAITING_TX0: - /* Transmit phase over, receiving the zero sized status packet.*/ - usbp->ep0state = USB_EP0_WAITING_STS; -#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - osalSysLockFromISR(); - usbStartReceiveI(usbp, 0, NULL, 0); - osalSysUnlockFromISR(); -#else - usb_lld_end_setup(usbp, ep); -#endif - return; - case USB_EP0_SENDING_STS: - /* Status packet sent, invoking the callback if defined.*/ - if (usbp->ep0endcb != NULL) { - usbp->ep0endcb(usbp); - } - usbp->ep0state = USB_EP0_WAITING_SETUP; - return; - case USB_EP0_WAITING_SETUP: - case USB_EP0_WAITING_STS: - case USB_EP0_RX: - /* All the above are invalid states in the IN phase.*/ - osalDbgAssert(false, "EP0 state machine error"); - /* Falling through is intentional.*/ - case USB_EP0_ERROR: - /* Error response, the state machine goes into an error state, the low - level layer will have to reset it to USB_EP0_WAITING_SETUP after - receiving a SETUP packet.*/ - usb_lld_stall_in(usbp, 0); - usb_lld_stall_out(usbp, 0); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); - usbp->ep0state = USB_EP0_ERROR; - return; - default: - osalDbgAssert(false, "EP0 state machine invalid state"); - } -} - -/** - * @brief Default EP0 OUT callback. - * @details This function is used by the low level driver as default handler - * for EP0 OUT events. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number, always zero - * - * @notapi - */ -void _usb_ep0out(USBDriver *usbp, usbep_t ep) { - - (void)ep; - switch (usbp->ep0state) { - case USB_EP0_RX: - /* Receive phase over, sending the zero sized status packet.*/ - usbp->ep0state = USB_EP0_SENDING_STS; -#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - osalSysLockFromISR(); - usbStartTransmitI(usbp, 0, NULL, 0); - osalSysUnlockFromISR(); -#else - usb_lld_end_setup(usbp, ep); -#endif - return; - case USB_EP0_WAITING_STS: - /* Status packet received, it must be zero sized, invoking the callback - if defined.*/ -#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) { - break; - } -#endif - if (usbp->ep0endcb != NULL) { - usbp->ep0endcb(usbp); - } - usbp->ep0state = USB_EP0_WAITING_SETUP; - return; - case USB_EP0_WAITING_SETUP: - case USB_EP0_TX: - case USB_EP0_WAITING_TX0: - case USB_EP0_SENDING_STS: - /* All the above are invalid states in the IN phase.*/ - osalDbgAssert(false, "EP0 state machine error"); - /* Falling through is intentional.*/ - case USB_EP0_ERROR: - /* Error response, the state machine goes into an error state, the low - level layer will have to reset it to USB_EP0_WAITING_SETUP after - receiving a SETUP packet.*/ - usb_lld_stall_in(usbp, 0); - usb_lld_stall_out(usbp, 0); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); - usbp->ep0state = USB_EP0_ERROR; - return; - default: - osalDbgAssert(false, "EP0 state machine invalid state"); - } -} - -#endif /* HAL_USE_USB == TRUE */ - -/** @} */ diff --git a/os/hal/src/wdg.c b/os/hal/src/wdg.c deleted file mode 100644 index a764864a4..000000000 --- a/os/hal/src/wdg.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file wdg.c - * @brief WDG Driver code. - * - * @addtogroup WDG - * @{ - */ - -#include "hal.h" - -#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief WDG Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void wdgInit(void) { - - wdg_lld_init(); -} - -/** - * @brief Configures and activates the WDG peripheral. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * @param[in] config pointer to the @p WDGConfig object - * - * @api - */ -void wdgStart(WDGDriver *wdgp, const WDGConfig *config) { - - osalDbgCheck((wdgp != NULL) && (config != NULL)); - - osalSysLock(); - osalDbgAssert((wdgp->state == WDG_STOP) || (wdgp->state == WDG_READY), - "invalid state"); - wdgp->config = config; - wdg_lld_start(wdgp); - wdgp->state = WDG_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the WDG peripheral. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * - * @api - */ -void wdgStop(WDGDriver *wdgp) { - - osalDbgCheck(wdgp != NULL); - - osalSysLock(); - osalDbgAssert((wdgp->state == WDG_STOP) || (wdgp->state == WDG_READY), - "invalid state"); - wdg_lld_stop(wdgp); - wdgp->state = WDG_STOP; - osalSysUnlock(); -} - -/** - * @brief Resets WDG's counter. - * - * @param[in] wdgp pointer to the @p WDGDriver object - * - * @api - */ -void wdgReset(WDGDriver *wdgp) { - - osalDbgCheck(wdgp != NULL); - - osalSysLock(); - osalDbgAssert(wdgp->state == WDG_READY, "not ready"); - wdgResetI(wdgp); - osalSysUnlock(); -} - -#endif /* HAL_USE_WDG == TRUE */ - -/** @} */ -- cgit v1.2.3