| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /*
- * Copyright (C) 2013 by Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- */
- /*!
- * \file dev/owibus-stm32tim.c
- * \brief Common implementation of One-Wire primitives with dual channel
- * STM32 timer, configured at library compile time. This file is
- * to be included from bus specific drivers.
- *
- * The OWI Bus needs to be connected of CH1|2 or CH3|4 of some timer. The
- * base pin is set to opendrain, and CNT and CCR1|2 or CCR3|4 are use to
- * generate the pulse and capture the rising edge.
- *
- * \verbatim
- * $Id: owibus_stm32tim.c 5638 2014-04-07 13:58:48Z u_bonnes $
- * \endverbatim
- */
- /* Force level to inactive at startup */
- #if defined(STM32TIM_OWI_CHANNEL)
- #if (STM32TIM_OWI_CHANNEL == 1)
- #define STM32TIM_OWI_CCMR CCMR1
- #define STM32TIM_OWI_COMPARE CCR1
- #define STM32TIM_OWI_CCMODE TIM_CCMR1_CC2S_1 | TIM_CCMR1_OC1M_2
- #define STM32TIM_OWI_CAPTURE CCR2
- #define STM32TIM_OWI_CCMR_SHIFT 4
- #define STM32TIM_OWI_CCER (TIM_CCER_CC2E | TIM_CCER_CC1E | TIM_CCER_CC1P)
- #elif (STM32TIM_OWI_CHANNEL == 2)
- #define STM32TIM_OWI_CCMR CCMR1
- #define STM32TIM_OWI_CCMODE TIM_CCMR1_CC1S_1 | TIM_CCMR1_OC2M_2
- #define STM32TIM_OWI_COMPARE CCR2
- #define STM32TIM_OWI_CAPTURE CCR1
- #define STM32TIM_OWI_CCMR_SHIFT 12
- #define STM32TIM_OWI_CCER (TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P)
- #elif (STM32TIM_OWI_CHANNEL == 3)
- #define STM32TIM_OWI_CCMR CCMR2
- #define STM32TIM_OWI_CCMODE TIM_CCMR2_CC4S_1 | TIM_CCMR2_OC3M_2
- #define STM32TIM_OWI_COMPARE CCR3
- #define STM32TIM_OWI_CAPTURE CCR4
- #define STM32TIM_OWI_CCMR_SHIFT 4
- #define STM32TIM_OWI_CCER (TIM_CCER_CC4E | TIM_CCER_CC3E | TIM_CCER_CC3P)
- #elif (STM32TIM_OWI_CHANNEL == 4)
- #define STM32TIM_OWI_CCMR CCMR2
- #define STM32TIM_OWI_CCMODE TIM_CCMR2_CC3S_1 | TIM_CCMR2_OC4M_2
- #define STM32TIM_OWI_COMPARE CCR4
- #define STM32TIM_OWI_CAPTURE CCR3
- #define STM32TIM_OWI_CCMR_SHIFT 12
- #define STM32TIM_OWI_CCER (TIM_CCER_CC3E | TIM_CCER_CC4E |TIM_CCER_CC4P)
- #else
- #warning Wrong STM32TIM_OWI_CHANNEL
- #endif
- #else
- #warning STM32TIM_OWI_CHANNEL undefined
- #endif
- /* There is no timer yet with 3 channels only (20130703) */
- #if (STM32TIM_OWI_CHANNEL > STM32_OWITIMER_NCH ) || (STM32_OWITIMER_NCH < 2)
- #warning No compagnion timer channel available
- #endif
- static void Stm32Tim_OwiInterrupt(void *arg)
- {
- if (TIM_Status(STM32_OWITIMER_BASE) & TIM_SR_UIF) {
- TIM_Status(STM32_OWITIMER_BASE) &= ~TIM_SR_UIF; /* Reset Flag*/
- NutEventPostFromIrq(&STM32TIM_OWI_MUTEX);
- }
- }
- /*!
- * \brief Perform One-Wire transaction.
- *
- * \param bus Specifies the One-Wire bus.
- * \param command Either OWI_CMD_RESET or OWI_CMD_RWBIT.
- * \param value The value to send.
- *
- * \return The value read on success, a negative value otherwise.
- */
- static int Stm32Tim_OwiTransaction(NUTOWIBUS *bus, int_fast8_t command, int_fast8_t value)
- {
- TIM_TypeDef *owi_timer = (TIM_TypeDef *)STM32_OWITIMER_BASE;
- uint16_t ccmr = owi_timer->STM32TIM_OWI_CCMR;
- if (value)
- owi_timer->STM32TIM_OWI_COMPARE = -(owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
- - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_SYNC_PULSE]);
- else
- owi_timer->STM32TIM_OWI_COMPARE = -(owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
- - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_SYNC_PULSE_LOW]);
- owi_timer->CNT = -(owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
- - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_SETUP]);
- NutEnterCritical();
- TIM_IRQEnable(STM32_OWITIMER_BASE);
- /* Force active level */
- ccmr &= ~( 7 <<(STM32TIM_OWI_CCMR_SHIFT));
- ccmr |= ( 5 <<(STM32TIM_OWI_CCMR_SHIFT));
- owi_timer->STM32TIM_OWI_CCMR = ccmr;
- TIM_StartTimer(STM32_OWITIMER_BASE);
- /* Toggle on compare match */
- ccmr &= ~( 7 <<(STM32TIM_OWI_CCMR_SHIFT));
- ccmr |= ( 3 <<(STM32TIM_OWI_CCMR_SHIFT));
- owi_timer->STM32TIM_OWI_CCMR = ccmr;
- NutExitCritical();
- if(NutEventWait(&STM32TIM_OWI_MUTEX, 10)) {
- if (command == OWI_CMD_RESET)
- return OWI_PRESENCE_ERR;
- else
- return OWI_DATA_ERROR;
- }
- owi_timer->SR = 0;
- TIM_IRQDisable(STM32_OWITIMER_BASE);
- /* We need to handle 32 and 16 bit counters. Store the value to compare
- in timer->capture, so the same thing happens to the top word*/
- owi_timer->STM32TIM_OWI_COMPARE =
- -( owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
- - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RW]);
- if (owi_timer->STM32TIM_OWI_CAPTURE > owi_timer->STM32TIM_OWI_COMPARE)
- return 0;
- else
- return 1;
- }
- /*!
- * \brief Reset the One-Wire bus and check if device(s) present.
- *
- * \param bus Specifies the One-Wire bus.
- *
- * \return OWI_SUCCESS on success, a negative value otherwise.
- */
- static int Stm32Tim_OwiTouchReset(NUTOWIBUS *bus)
- {
- return Stm32Tim_OwiTransaction(bus, OWI_CMD_RESET, 1);
- }
- /*!
- * \brief Exchange one bit on the One-Wire bus.
- *
- * \param bus Specifies the One-Wire bus.
- * \param bit Value for the bit to send.
- *
- * \return The bus state at the read slot on success, a negative value
- * otherwise.
- */
- static int Stm32Tim_OwiRWBit(NUTOWIBUS *bus, uint_fast8_t bit)
- {
- return Stm32Tim_OwiTransaction(bus, OWI_CMD_RWBIT, bit);
- }
- /*!
- * \brief Write a block of data bits to the One-Wire bus.
- *
- * \param bus Specifies the One-Wire bus.
- * \param data Data bits to send.
- * \param len Number of bits to send.
- *
- * \return OWI_SUCCESS on success, a negative value otherwise.
- */
- static int Stm32Tim_OwiWriteBlock(
- NUTOWIBUS *bus, uint8_t *data, uint_fast8_t len)
- {
- int res;
- int i;
- for (i = 0; i < len; i++) {
- res = Stm32Tim_OwiRWBit(bus, data[i >> 3] & (1 << (i & 0x7)));
- if (res < 0)
- return OWI_HW_ERROR;
- }
- return OWI_SUCCESS;
- }
- /*!
- * \brief Read a block of data bits from the One-Wire bus.
- *
- * \param bus Specifies the One-Wire bus.
- * \param data Data bits received.
- * \param len Number of bits to read.
- *
- * \return OWI_SUCCESS on success, a negative value otherwise.
- */
- static int Stm32Tim_OwiReadBlock(
- NUTOWIBUS *bus, uint8_t *data, uint_fast8_t len)
- {
- int res;
- int i;
- memset(data, 0, (len >> 3) + 1);
- for (i = 0; i < len; i++) {
- res = Stm32Tim_OwiRWBit(bus, 1);
- if (res < 0)
- return OWI_HW_ERROR;
- data[i >> 3] |= (res << (i & 0x7));
- }
- return OWI_SUCCESS;
- }
- /*!
- * \brief Initailize the driver.
- *
- * \param bus Specifies the One-Wire bus.
- *
- * \return OWI_SUCCESS on success, a negative value otherwise.
- */
- static int Stm32Tim_OwiSetup(NUTOWIBUS *bus)
- {
- (void) bus;
- TIM_TypeDef *owi_timer = (TIM_TypeDef *)STM32_OWITIMER_BASE;
- #if !defined(STM32TIM_OWI_PORT) || !defined(STM32TIM_OWI_PIN) ||\
- !defined(STM32_OWITIMER_BASE) || !defined(STM32TIM_OWI_CHANNEL)
- return OWI_INVALID_HW;
- #else
- STM32_OWITIMER_CLK();
- STM32_OWITIMER_RST();
- NutRegisterIrqHandler( &STM32_OWITIMER_SIG, &Stm32Tim_OwiInterrupt, NULL);
- owi_timer->PSC = (STM32_OWITIMER_PCLK/2000000L)-1;
- TIM_OnePulse(STM32_OWITIMER_BASE);
- owi_timer->STM32TIM_OWI_CCMR = STM32TIM_OWI_CCMODE;
- owi_timer->CCER = STM32TIM_OWI_CCER;
- TIM_Update(STM32_OWITIMER_BASE);
- owi_timer->SR = 0;
- NutIrqEnable(&STM32_OWITIMER_SIG);
- GpioPinConfigSet(STM32TIM_OWI_PORT, STM32TIM_OWI_PIN,
- GPIO_CFG_PERIPHAL|GPIO_CFG_OUTPUT|GPIO_CFG_MULTIDRIVE|
- GPIO_CFG_PULLUP|GPIO_CFG_INIT_HIGH );
- #if defined(MCU_STM32F1)
- #if defined(STM32_OWITIMER_REMAP_MASK) && defined(STM32_OWITIMER_REMAP_SHIFT)
- CM3REG(AFIO_BASE, AFIO_TypeDef, MAPR) &= ~(STM32_OWITIMER_REMAP_MASK << STM32_OWITIMER_REMAP_SHIFT);
- #if defined(STM32TIM_OWI_REMAP)
- #if STM32TIM_OWI_REMAP > STM32_OWITIMER_REMAP_MASK
- #warning Illegal Remap Value for OWI0
- #endif
- CM3REG(AFIO_BASE, AFIO_TypeDef, MAPR) |= (STM32TIM_OWI_REMAP<< STM32_OWITIMER_REMAP_SHIFT);
- #endif
- #endif
- #else
- GPIO_PinAFConfig((GPIO_TypeDef*)STM32TIM_OWI_PORT, STM32TIM_OWI_PIN, STM32_OWITIMER_AF );
- #endif
- return OWI_SUCCESS;
- #endif
|