owibus_stm32tim.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Copyright (C) 2013 by Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*!
  35. * \file dev/owibus-stm32tim.c
  36. * \brief Common implementation of One-Wire primitives with dual channel
  37. * STM32 timer, configured at library compile time. This file is
  38. * to be included from bus specific drivers.
  39. *
  40. * The OWI Bus needs to be connected of CH1|2 or CH3|4 of some timer. The
  41. * base pin is set to opendrain, and CNT and CCR1|2 or CCR3|4 are use to
  42. * generate the pulse and capture the rising edge.
  43. *
  44. * \verbatim
  45. * $Id: owibus_stm32tim.c 5638 2014-04-07 13:58:48Z u_bonnes $
  46. * \endverbatim
  47. */
  48. /* Force level to inactive at startup */
  49. #if defined(STM32TIM_OWI_CHANNEL)
  50. #if (STM32TIM_OWI_CHANNEL == 1)
  51. #define STM32TIM_OWI_CCMR CCMR1
  52. #define STM32TIM_OWI_COMPARE CCR1
  53. #define STM32TIM_OWI_CCMODE TIM_CCMR1_CC2S_1 | TIM_CCMR1_OC1M_2
  54. #define STM32TIM_OWI_CAPTURE CCR2
  55. #define STM32TIM_OWI_CCMR_SHIFT 4
  56. #define STM32TIM_OWI_CCER (TIM_CCER_CC2E | TIM_CCER_CC1E | TIM_CCER_CC1P)
  57. #elif (STM32TIM_OWI_CHANNEL == 2)
  58. #define STM32TIM_OWI_CCMR CCMR1
  59. #define STM32TIM_OWI_CCMODE TIM_CCMR1_CC1S_1 | TIM_CCMR1_OC2M_2
  60. #define STM32TIM_OWI_COMPARE CCR2
  61. #define STM32TIM_OWI_CAPTURE CCR1
  62. #define STM32TIM_OWI_CCMR_SHIFT 12
  63. #define STM32TIM_OWI_CCER (TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P)
  64. #elif (STM32TIM_OWI_CHANNEL == 3)
  65. #define STM32TIM_OWI_CCMR CCMR2
  66. #define STM32TIM_OWI_CCMODE TIM_CCMR2_CC4S_1 | TIM_CCMR2_OC3M_2
  67. #define STM32TIM_OWI_COMPARE CCR3
  68. #define STM32TIM_OWI_CAPTURE CCR4
  69. #define STM32TIM_OWI_CCMR_SHIFT 4
  70. #define STM32TIM_OWI_CCER (TIM_CCER_CC4E | TIM_CCER_CC3E | TIM_CCER_CC3P)
  71. #elif (STM32TIM_OWI_CHANNEL == 4)
  72. #define STM32TIM_OWI_CCMR CCMR2
  73. #define STM32TIM_OWI_CCMODE TIM_CCMR2_CC3S_1 | TIM_CCMR2_OC4M_2
  74. #define STM32TIM_OWI_COMPARE CCR4
  75. #define STM32TIM_OWI_CAPTURE CCR3
  76. #define STM32TIM_OWI_CCMR_SHIFT 12
  77. #define STM32TIM_OWI_CCER (TIM_CCER_CC3E | TIM_CCER_CC4E |TIM_CCER_CC4P)
  78. #else
  79. #warning Wrong STM32TIM_OWI_CHANNEL
  80. #endif
  81. #else
  82. #warning STM32TIM_OWI_CHANNEL undefined
  83. #endif
  84. /* There is no timer yet with 3 channels only (20130703) */
  85. #if (STM32TIM_OWI_CHANNEL > STM32_OWITIMER_NCH ) || (STM32_OWITIMER_NCH < 2)
  86. #warning No compagnion timer channel available
  87. #endif
  88. static void Stm32Tim_OwiInterrupt(void *arg)
  89. {
  90. if (TIM_Status(STM32_OWITIMER_BASE) & TIM_SR_UIF) {
  91. TIM_Status(STM32_OWITIMER_BASE) &= ~TIM_SR_UIF; /* Reset Flag*/
  92. NutEventPostFromIrq(&STM32TIM_OWI_MUTEX);
  93. }
  94. }
  95. /*!
  96. * \brief Perform One-Wire transaction.
  97. *
  98. * \param bus Specifies the One-Wire bus.
  99. * \param command Either OWI_CMD_RESET or OWI_CMD_RWBIT.
  100. * \param value The value to send.
  101. *
  102. * \return The value read on success, a negative value otherwise.
  103. */
  104. static int Stm32Tim_OwiTransaction(NUTOWIBUS *bus, int_fast8_t command, int_fast8_t value)
  105. {
  106. TIM_TypeDef *owi_timer = (TIM_TypeDef *)STM32_OWITIMER_BASE;
  107. uint16_t ccmr = owi_timer->STM32TIM_OWI_CCMR;
  108. if (value)
  109. owi_timer->STM32TIM_OWI_COMPARE = -(owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
  110. - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_SYNC_PULSE]);
  111. else
  112. owi_timer->STM32TIM_OWI_COMPARE = -(owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
  113. - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_SYNC_PULSE_LOW]);
  114. owi_timer->CNT = -(owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
  115. - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_SETUP]);
  116. NutEnterCritical();
  117. TIM_IRQEnable(STM32_OWITIMER_BASE);
  118. /* Force active level */
  119. ccmr &= ~( 7 <<(STM32TIM_OWI_CCMR_SHIFT));
  120. ccmr |= ( 5 <<(STM32TIM_OWI_CCMR_SHIFT));
  121. owi_timer->STM32TIM_OWI_CCMR = ccmr;
  122. TIM_StartTimer(STM32_OWITIMER_BASE);
  123. /* Toggle on compare match */
  124. ccmr &= ~( 7 <<(STM32TIM_OWI_CCMR_SHIFT));
  125. ccmr |= ( 3 <<(STM32TIM_OWI_CCMR_SHIFT));
  126. owi_timer->STM32TIM_OWI_CCMR = ccmr;
  127. NutExitCritical();
  128. if(NutEventWait(&STM32TIM_OWI_MUTEX, 10)) {
  129. if (command == OWI_CMD_RESET)
  130. return OWI_PRESENCE_ERR;
  131. else
  132. return OWI_DATA_ERROR;
  133. }
  134. owi_timer->SR = 0;
  135. TIM_IRQDisable(STM32_OWITIMER_BASE);
  136. /* We need to handle 32 and 16 bit counters. Store the value to compare
  137. in timer->capture, so the same thing happens to the top word*/
  138. owi_timer->STM32TIM_OWI_COMPARE =
  139. -( owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RELEASE]
  140. - owi_timervalues_250ns[bus->mode & OWI_OVERDRIVE][command][OWI_PHASE_RW]);
  141. if (owi_timer->STM32TIM_OWI_CAPTURE > owi_timer->STM32TIM_OWI_COMPARE)
  142. return 0;
  143. else
  144. return 1;
  145. }
  146. /*!
  147. * \brief Reset the One-Wire bus and check if device(s) present.
  148. *
  149. * \param bus Specifies the One-Wire bus.
  150. *
  151. * \return OWI_SUCCESS on success, a negative value otherwise.
  152. */
  153. static int Stm32Tim_OwiTouchReset(NUTOWIBUS *bus)
  154. {
  155. return Stm32Tim_OwiTransaction(bus, OWI_CMD_RESET, 1);
  156. }
  157. /*!
  158. * \brief Exchange one bit on the One-Wire bus.
  159. *
  160. * \param bus Specifies the One-Wire bus.
  161. * \param bit Value for the bit to send.
  162. *
  163. * \return The bus state at the read slot on success, a negative value
  164. * otherwise.
  165. */
  166. static int Stm32Tim_OwiRWBit(NUTOWIBUS *bus, uint_fast8_t bit)
  167. {
  168. return Stm32Tim_OwiTransaction(bus, OWI_CMD_RWBIT, bit);
  169. }
  170. /*!
  171. * \brief Write a block of data bits to the One-Wire bus.
  172. *
  173. * \param bus Specifies the One-Wire bus.
  174. * \param data Data bits to send.
  175. * \param len Number of bits to send.
  176. *
  177. * \return OWI_SUCCESS on success, a negative value otherwise.
  178. */
  179. static int Stm32Tim_OwiWriteBlock(
  180. NUTOWIBUS *bus, uint8_t *data, uint_fast8_t len)
  181. {
  182. int res;
  183. int i;
  184. for (i = 0; i < len; i++) {
  185. res = Stm32Tim_OwiRWBit(bus, data[i >> 3] & (1 << (i & 0x7)));
  186. if (res < 0)
  187. return OWI_HW_ERROR;
  188. }
  189. return OWI_SUCCESS;
  190. }
  191. /*!
  192. * \brief Read a block of data bits from the One-Wire bus.
  193. *
  194. * \param bus Specifies the One-Wire bus.
  195. * \param data Data bits received.
  196. * \param len Number of bits to read.
  197. *
  198. * \return OWI_SUCCESS on success, a negative value otherwise.
  199. */
  200. static int Stm32Tim_OwiReadBlock(
  201. NUTOWIBUS *bus, uint8_t *data, uint_fast8_t len)
  202. {
  203. int res;
  204. int i;
  205. memset(data, 0, (len >> 3) + 1);
  206. for (i = 0; i < len; i++) {
  207. res = Stm32Tim_OwiRWBit(bus, 1);
  208. if (res < 0)
  209. return OWI_HW_ERROR;
  210. data[i >> 3] |= (res << (i & 0x7));
  211. }
  212. return OWI_SUCCESS;
  213. }
  214. /*!
  215. * \brief Initailize the driver.
  216. *
  217. * \param bus Specifies the One-Wire bus.
  218. *
  219. * \return OWI_SUCCESS on success, a negative value otherwise.
  220. */
  221. static int Stm32Tim_OwiSetup(NUTOWIBUS *bus)
  222. {
  223. (void) bus;
  224. TIM_TypeDef *owi_timer = (TIM_TypeDef *)STM32_OWITIMER_BASE;
  225. #if !defined(STM32TIM_OWI_PORT) || !defined(STM32TIM_OWI_PIN) ||\
  226. !defined(STM32_OWITIMER_BASE) || !defined(STM32TIM_OWI_CHANNEL)
  227. return OWI_INVALID_HW;
  228. #else
  229. STM32_OWITIMER_CLK();
  230. STM32_OWITIMER_RST();
  231. NutRegisterIrqHandler( &STM32_OWITIMER_SIG, &Stm32Tim_OwiInterrupt, NULL);
  232. owi_timer->PSC = (STM32_OWITIMER_PCLK/2000000L)-1;
  233. TIM_OnePulse(STM32_OWITIMER_BASE);
  234. owi_timer->STM32TIM_OWI_CCMR = STM32TIM_OWI_CCMODE;
  235. owi_timer->CCER = STM32TIM_OWI_CCER;
  236. TIM_Update(STM32_OWITIMER_BASE);
  237. owi_timer->SR = 0;
  238. NutIrqEnable(&STM32_OWITIMER_SIG);
  239. GpioPinConfigSet(STM32TIM_OWI_PORT, STM32TIM_OWI_PIN,
  240. GPIO_CFG_PERIPHAL|GPIO_CFG_OUTPUT|GPIO_CFG_MULTIDRIVE|
  241. GPIO_CFG_PULLUP|GPIO_CFG_INIT_HIGH );
  242. #if defined(MCU_STM32F1)
  243. #if defined(STM32_OWITIMER_REMAP_MASK) && defined(STM32_OWITIMER_REMAP_SHIFT)
  244. CM3REG(AFIO_BASE, AFIO_TypeDef, MAPR) &= ~(STM32_OWITIMER_REMAP_MASK << STM32_OWITIMER_REMAP_SHIFT);
  245. #if defined(STM32TIM_OWI_REMAP)
  246. #if STM32TIM_OWI_REMAP > STM32_OWITIMER_REMAP_MASK
  247. #warning Illegal Remap Value for OWI0
  248. #endif
  249. CM3REG(AFIO_BASE, AFIO_TypeDef, MAPR) |= (STM32TIM_OWI_REMAP<< STM32_OWITIMER_REMAP_SHIFT);
  250. #endif
  251. #endif
  252. #else
  253. GPIO_PinAFConfig((GPIO_TypeDef*)STM32TIM_OWI_PORT, STM32TIM_OWI_PIN, STM32_OWITIMER_AF );
  254. #endif
  255. return OWI_SUCCESS;
  256. #endif