stm32f1_gpio.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  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. * \verbatim
  36. * $Id: stm32f1_gpio.c -1 $
  37. * \endverbatim
  38. */
  39. #include <cfg/os.h>
  40. #include <cfg/arch.h>
  41. #include <cfg/arch/gpio.h>
  42. #include <sys/nutdebug.h>
  43. #include <arch/cm3.h>
  44. #include <dev/gpio.h>
  45. #define NUTGPIOPORT_MAX NUTGPIO_PORTG+1
  46. /*!
  47. * \brief Get pin configuration.
  48. *
  49. * Trying to set undefined ports must be avoided.
  50. * If NUTDEBUG is enabled an assertion will be rised.
  51. *
  52. * \param bank GPIO bank/port number.
  53. * \param bit Bit number of the specified bank/port.
  54. *
  55. * \return Attribute flags of the pin.
  56. uint8_t cnf; */
  57. uint32_t GpioPinConfigGet(int bank, int bit)
  58. {
  59. uint32_t rc = 0;
  60. uint8_t mode;
  61. uint8_t cnf;
  62. uint8_t speed;
  63. GPIO_TypeDef *GPIOx = ((GPIO_TypeDef *)bank);
  64. if( bit < 8 ) {
  65. rc = GPIOx->CRL;
  66. }
  67. else {
  68. rc = GPIOx->CRH;
  69. bit -=8;
  70. }
  71. mode = ( rc >> ( bit * 4 ) );
  72. speed = mode & 0x3;
  73. cnf = ( mode >> 2 ) & 0x3;
  74. mode &= 0x3;
  75. if( mode == 0 ) {
  76. rc = 0;
  77. /* Pin is input */
  78. switch ( cnf ) {
  79. case 0:
  80. /* Input Analog */
  81. rc |= GPIO_CFG_DISABLED;
  82. break;
  83. case 1:
  84. /* Input Floating */
  85. rc = 0;
  86. break; case 2:
  87. /* Input with Pullup */
  88. if (GPIOx->ODR & _BV(bit))
  89. rc |= GPIO_CFG_PULLUP;
  90. else
  91. rc |= GPIO_CFG_PULLDOWN;
  92. break;
  93. }
  94. }
  95. else {
  96. rc = GPIO_CFG_OUTPUT;
  97. /* Pin is output */
  98. switch ( cnf ) {
  99. case 1:
  100. /* Output Open-Drain */
  101. rc |= GPIO_CFG_MULTIDRIVE;
  102. break;
  103. case 2:
  104. /* Output Push-Pull Alternative Function */
  105. rc |= (GPIO_CFG_PERIPHAL);
  106. break;
  107. case 3:
  108. /* Output Open-Drain Alternative Function */
  109. rc |= (GPIO_CFG_PERIPHAL | GPIO_CFG_MULTIDRIVE);
  110. break;
  111. }
  112. switch ( speed) {
  113. case 2 :
  114. rc |= GPIO_CFG_SPEED_SLOW;
  115. break;
  116. case 3 :
  117. rc |= GPIO_CFG_SPEED_FAST;
  118. break;
  119. default :
  120. rc |= GPIO_CFG_SPEED_MED;
  121. }
  122. }
  123. return rc;
  124. }
  125. /*!
  126. * \brief Set port wide pin configuration.
  127. *
  128. * \note This function does not check for undefined ports and pins or
  129. * invalid attributes. If this is required, use GpioPinConfigSet().
  130. * If NUTDEBUG is enabled accessing an undefined port will rise
  131. * an assertion.
  132. *
  133. * \param bank GPIO bank/port number.
  134. * \param mask The given attributes are set for a specific pin, if the
  135. * corresponding bit in this mask is 1.
  136. * \param flags Attribute flags to set.
  137. *
  138. * \return Corrected flags
  139. */
  140. int GpioPortConfigSet(int bank, uint32_t mask, uint32_t flags)
  141. {
  142. uint32_t cxmx = 0; /* Configuration mask */
  143. uint32_t crl, crh, cln;
  144. uint8_t msl, msh;
  145. int i;
  146. GPIO_TypeDef *GPIOx = ((GPIO_TypeDef *)bank);
  147. /* Important: Enable clock of port first
  148. * before trying to configure it!
  149. * Enable GPIO clock source */
  150. CM3BBSET(RCC_BASE, RCC_TypeDef, APB2ENR,
  151. (((bank-GPIOA_BASE)/0x400) + _BI32(RCC_APB2ENR_IOPAEN)));
  152. if (flags & GPIO_CFG_PERIPHAL )
  153. CM3BBSET(RCC_BASE, RCC_TypeDef, APB2ENR,
  154. _BI32(RCC_APB2ENR_AFIOEN));
  155. /* Set the inital value, if given
  156. *
  157. * Otherwise we may introduce unwanted transistions on the port
  158. */
  159. if (flags & GPIO_CFG_INIT_HIGH)
  160. {
  161. if (flags & GPIO_CFG_INIT_LOW)
  162. return -1;
  163. else
  164. GPIOx->BSRR = mask;
  165. }
  166. if (flags & GPIO_CFG_INIT_LOW)
  167. GPIOx->BRR = mask;
  168. /* we can't check for these flags, so clear them */
  169. flags &= ~(GPIO_CFG_INIT_LOW |GPIO_CFG_INIT_HIGH);
  170. /* Pull-up/down can only be configured for input mode*/
  171. if (flags & (GPIO_CFG_OUTPUT|GPIO_CFG_DISABLED))
  172. if(flags & (GPIO_CFG_PULLUP |GPIO_CFG_PULLDOWN))
  173. flags &= ~(GPIO_CFG_PULLUP |GPIO_CFG_PULLDOWN);
  174. /*
  175. * cnf mode Meaning
  176. * 00 00 Input Analog
  177. * 01 00 Input Floating
  178. * 10 00 Input PullUp/Down
  179. * 11 00 Reserved
  180. * 00 xx Output Push-Pull
  181. * 01 xx Output Open-Drain
  182. * 10 xx Output Alternate Push-Pull
  183. * 11 xx Output Alternate Open-Drain
  184. *
  185. * 01 Output mode, max speed 10MHz
  186. * 10 Output mode, max speed 2MHz
  187. * 11 Output mode, max speed 50MHz
  188. */
  189. if( flags & GPIO_CFG_OUTPUT ) {
  190. switch (flags & GPIO_CFG_SPEED)
  191. {
  192. case GPIO_CFG_SPEED_SLOW: cxmx = 0x2; break;
  193. case GPIO_CFG_SPEED_FAST: cxmx = 0x3; break;
  194. default: cxmx = 0x1;
  195. }
  196. /* Configure Open-Drain */
  197. if( flags & GPIO_CFG_MULTIDRIVE )
  198. cxmx |= 0x4;
  199. /* Configure Alternate Function */
  200. if( flags & GPIO_CFG_DISABLED ) {
  201. cxmx |= 0x8;
  202. }
  203. /* Configure Alternate Function */
  204. if( flags & GPIO_CFG_PERIPHAL ) {
  205. cxmx |= 0x8;
  206. }
  207. }
  208. else {
  209. /* Configure pin as input floating */
  210. cxmx = 0x4;
  211. /* Configure pin as input PullUp/Down */
  212. if( flags & (GPIO_CFG_PULLUP |GPIO_CFG_PULLDOWN)) {
  213. cxmx = 0x8;
  214. if (flags & GPIO_CFG_PULLUP)
  215. GPIOx->ODR |= mask;
  216. else
  217. GPIOx->ODR &= ~mask;
  218. }
  219. /* Configure pin as analog input */
  220. if( flags & GPIO_CFG_DISABLED )
  221. cxmx = 0x0;
  222. }
  223. msl = (uint8_t)(mask&0xff);
  224. msh = (uint8_t)(mask>>8);
  225. /* get actual config */
  226. crl = GPIOx->CRL;
  227. crh = GPIOx->CRH;
  228. /* shift in modified values */
  229. for( i = 0; i < 8; i++ ) {
  230. /* mask out actual nibble */
  231. cln = ~(0xf<<(i*4));
  232. /* check if pins 0..7 are affected */
  233. if( msl & _BV(i)) {
  234. crl &= cln; /* mask nibble */
  235. crl |= cxmx; /* write nibble */
  236. }
  237. /* check if pins 8..15 are affected */
  238. if( msh & _BV(i)) {
  239. crh &= cln; /* mask nibble */
  240. crh |= cxmx; /* write nibble */
  241. }
  242. /* shift left configuration for next bit */
  243. cxmx <<= 4;
  244. }
  245. /* write back new config */
  246. GPIOx->CRL = crl;
  247. GPIOx->CRH = crh;
  248. return flags;
  249. }
  250. /*!
  251. * \brief Set pin configuration.
  252. *
  253. * Applications may also use this function to make sure, that a specific
  254. * attribute is available for a specific pin.
  255. *
  256. * \note GPIO pins are typically initialized to a safe state after power
  257. * up. This routine is not able to determine the consequences of
  258. * changing pin configurations. In the worst case you may permanently
  259. * damage your hardware by bad pin settings.
  260. *
  261. * \param bank GPIO bank/port number.
  262. * \param bit Bit number of the specified bank/port.
  263. * \param flags Attribute flags.
  264. *
  265. * \return 0 if all attributes had been set, -1 otherwise.
  266. */
  267. int GpioPinConfigSet(int bank, int bit, uint32_t flags)
  268. {
  269. NUTASSERT(bank<NUTGPIOPORT_MAX);
  270. if (GpioPortConfigSet( bank, _BV( bit ), flags ) !=
  271. GpioPinConfigGet( bank, bit )) {
  272. return -1;
  273. }
  274. return 0;
  275. }
  276. /*!
  277. * \brief Register a GPIO pin interrupt handler.
  278. *
  279. * Generating interrupts on GPIO pin changes is not supported on all
  280. * platforms. In this case dedicated external interrupt pins may
  281. * be used with NutRegisterIrqHandler().
  282. *
  283. * Interrupts are triggered on rising and falling edges. Level triggering
  284. * or triggering on specific edges is not supported.
  285. *
  286. * After registering, interrupts are disabled. Calling GpioIrqEnable()
  287. * is required to activate the interrupt.
  288. *
  289. * The following code fragment registers an interrupt handler which is
  290. * called on each change of bit 4 of the first GPIO port:
  291. * \code
  292. * #include <dev/gpio.h>
  293. *
  294. * static void PinChange(void *arg)
  295. * {
  296. * ...
  297. * }
  298. *
  299. * {
  300. * ...
  301. * GpioPinConfigSet(0, 4, GPIO_CFG_PULLUP);
  302. * GpioRegisterIrqHandler(&sig_GPIO, 4, PinChange, NULL);
  303. * GpioIrqEnable(&sig_GPIO, 4);
  304. * ...
  305. * }
  306. * \endcode
  307. *
  308. * \param sig Bank/port interrupt to be associated with this handler.
  309. * \param bit Bit number of the specified bank/port.
  310. * \param handler This routine will be called by Nut/OS, when the specified
  311. * pin changes its state.
  312. * \param arg Argument to be passed to the interrupt handler routine.
  313. *
  314. * \return 0 on success, -1 otherwise.
  315. */
  316. extern int GpioRegisterIrqHandler(GPIO_SIGNAL * sig, uint8_t bit, void (*handler) (void *), void *arg)
  317. {
  318. int rc = 0;
  319. #if 0
  320. if (bit<5) {
  321. NutRegisterIrqHandler( &sig_INTERRUPT0, void(* handler)(void *), void * arg)
  322. uint32_t afiob = bit/4;
  323. /* Select bank in AFIO_EXTIn */
  324. AFIO->EXTICR[afiob] |= bank<<(afiob*4);
  325. EXTI->
  326. #endif
  327. return rc;
  328. }
  329. /*!
  330. * \brief Enable a specified GPIO interrupt.
  331. *
  332. * A related interrupt handler must have been registered before calling
  333. * this function. See GpioRegisterIrqHandler().
  334. *
  335. * \param sig Interrupt to enable.
  336. * \param bit Bit number of the specified bank/port.
  337. *
  338. * \return 0 on success, -1 otherwise.
  339. */
  340. int GpioIrqEnable(GPIO_SIGNAL * sig, uint8_t bit)
  341. {
  342. return -1;
  343. }
  344. /*!
  345. * \brief Disable a specified GPIO interrupt.
  346. *
  347. * \param sig Interrupt to disable.
  348. * \param bit Bit number of the specified bank/port.
  349. *
  350. * \return 0 on success, -1 otherwise.
  351. */
  352. int GpioIrqDisable(GPIO_SIGNAL * sig, uint8_t bit)
  353. {
  354. return 0;
  355. }