em_gpio.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /***************************************************************************//**
  2. * @file
  3. * @brief General Purpose IO (GPIO) peripheral API
  4. * devices.
  5. * @author Energy Micro AS
  6. * @version 3.0.0
  7. *******************************************************************************
  8. * @section License
  9. * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
  10. *******************************************************************************
  11. *
  12. * Permission is granted to anyone to use this software for any purpose,
  13. * including commercial applications, and to alter it and redistribute it
  14. * freely, subject to the following restrictions:
  15. *
  16. * 1. The origin of this software must not be misrepresented; you must not
  17. * claim that you wrote the original software.
  18. * 2. Altered source versions must be plainly marked as such, and must not be
  19. * misrepresented as being the original software.
  20. * 3. This notice may not be removed or altered from any source distribution.
  21. *
  22. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  23. * obligation to support this Software. Energy Micro AS is providing the
  24. * Software "AS IS", with no express or implied warranties of any kind,
  25. * including, but not limited to, any implied warranties of merchantability
  26. * or fitness for any particular purpose or warranties against infringement
  27. * of any proprietary rights of a third party.
  28. *
  29. * Energy Micro AS will not be liable for any consequential, incidental, or
  30. * special damages, or any other relief, or for any claim by any third party,
  31. * arising from your use of this Software.
  32. *
  33. ******************************************************************************/
  34. #include "em_gpio.h"
  35. #include "em_bitband.h"
  36. #include "em_assert.h"
  37. /***************************************************************************//**
  38. * @addtogroup EM_Library
  39. * @{
  40. ******************************************************************************/
  41. /***************************************************************************//**
  42. * @addtogroup GPIO
  43. * @brief General Purpose Input/Output (GPIO) API
  44. * @{
  45. ******************************************************************************/
  46. /*******************************************************************************
  47. ******************************* DEFINES ***********************************
  48. ******************************************************************************/
  49. /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
  50. /** Validation of pin typically usable in assert statements. */
  51. #define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3)
  52. /** Validation of pin typically usable in assert statements. */
  53. #define GPIO_PIN_VALID(pin) ((pin) < 16)
  54. /** Validation of port typically usable in assert statements. */
  55. #define GPIO_PORT_VALID(port) ((port) <= gpioPortF)
  56. /** @endcond */
  57. /*******************************************************************************
  58. ************************** GLOBAL FUNCTIONS *******************************
  59. ******************************************************************************/
  60. /***************************************************************************//**
  61. * @brief
  62. * Sets the pin location of the debug pins (Serial Wire interface).
  63. *
  64. * @note
  65. * Changing the pins used for debugging uncontrolled, may result in a lockout.
  66. *
  67. * @param[in] location
  68. * The debug pin location to use (0-3).
  69. ******************************************************************************/
  70. void GPIO_DbgLocationSet(unsigned int location)
  71. {
  72. EFM_ASSERT(location < AFCHANLOC_MAX);
  73. GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |
  74. (location << _GPIO_ROUTE_SWLOCATION_SHIFT);
  75. }
  76. /***************************************************************************//**
  77. * @brief
  78. * Sets the drive mode for a GPIO port.
  79. *
  80. * @param[in] port
  81. * The GPIO port to access.
  82. *
  83. * @param[in] mode
  84. * Drive mode to use for port.
  85. ******************************************************************************/
  86. void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)
  87. {
  88. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));
  89. GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))
  90. | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);
  91. }
  92. /***************************************************************************//**
  93. * @brief
  94. * Configure GPIO interrupt.
  95. *
  96. * @details
  97. * If reconfiguring a GPIO interrupt that is already enabled, it is generally
  98. * recommended to disable it first, see GPIO_Disable().
  99. *
  100. * The actual GPIO interrupt handler must be in place before enabling the
  101. * interrupt.
  102. *
  103. * Notice that any pending interrupt for the selected pin is cleared by this
  104. * function.
  105. *
  106. * @note
  107. * A certain pin number can only be associated with one port. Ie, if GPIO
  108. * interrupt 1 is assigned to port A/pin 1, then it is not possibly to use
  109. * pin 1 from any other ports for interrupts. Please refer to the reference
  110. * manual.
  111. *
  112. * @param[in] port
  113. * The port to associate with @p pin.
  114. *
  115. * @param[in] pin
  116. * The GPIO interrupt number (= port pin).
  117. *
  118. * @param[in] risingEdge
  119. * Set to true if interrupts shall be enabled on rising edge, otherwise false.
  120. *
  121. * @param[in] fallingEdge
  122. * Set to true if interrupts shall be enabled on falling edge, otherwise false.
  123. *
  124. * @param[in] enable
  125. * Set to true if interrupt shall be enabled after configuration completed,
  126. * false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().
  127. ******************************************************************************/
  128. void GPIO_IntConfig(GPIO_Port_TypeDef port,
  129. unsigned int pin,
  130. bool risingEdge,
  131. bool fallingEdge,
  132. bool enable)
  133. {
  134. uint32_t tmp;
  135. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  136. /* There are two registers controlling the interrupt configuration:
  137. * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls
  138. * pins 8-15. */
  139. if (pin < 8)
  140. {
  141. GPIO->EXTIPSELL = (GPIO->EXTIPSELL & ~(0xF << (4 * pin))) |
  142. (port << (4 * pin));
  143. }
  144. else
  145. {
  146. tmp = pin - 8;
  147. GPIO->EXTIPSELH = (GPIO->EXTIPSELH & ~(0xF << (4 * tmp))) |
  148. (port << (4 * tmp));
  149. }
  150. /* Enable/disable rising edge */
  151. BITBAND_Peripheral(&(GPIO->EXTIRISE), pin, (unsigned int)risingEdge);
  152. /* Enable/disable falling edge */
  153. BITBAND_Peripheral(&(GPIO->EXTIFALL), pin, (unsigned int)fallingEdge);
  154. /* Clear any pending interrupt */
  155. GPIO->IFC = 1 << pin;
  156. /* Finally enable/disable interrupt */
  157. BITBAND_Peripheral(&(GPIO->IEN), pin, (unsigned int)enable);
  158. }
  159. /***************************************************************************//**
  160. * @brief
  161. * Read the pad value for a single pin in a GPIO port.
  162. *
  163. * @param[in] port
  164. * The GPIO port to access.
  165. *
  166. * @param[in] pin
  167. * The pin number to read.
  168. *
  169. * @return
  170. * The pin value, 0 or 1.
  171. ******************************************************************************/
  172. unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
  173. {
  174. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  175. return((unsigned int)((GPIO->P[port].DIN >> pin) & 0x1));
  176. }
  177. /***************************************************************************//**
  178. * @brief
  179. * Set the mode for a GPIO pin.
  180. *
  181. * @param[in] port
  182. * The GPIO port to access.
  183. *
  184. * @param[in] pin
  185. * The pin number in the port.
  186. *
  187. * @param[in] mode
  188. * The desired pin mode.
  189. *
  190. * @param[in] out
  191. * Value to set for pin in DOUT register. The DOUT setting is important for
  192. * even some input mode configurations, determining pull-up/down direction.
  193. * Notice that this parameter is not used if disabling a pin, leaving the
  194. * corresponding DOUT bit unchanged.
  195. ******************************************************************************/
  196. void GPIO_PinModeSet(GPIO_Port_TypeDef port,
  197. unsigned int pin,
  198. GPIO_Mode_TypeDef mode,
  199. unsigned int out)
  200. {
  201. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  202. /* If disabling pin, do not modify DOUT in order to reduce chance for */
  203. /* glitch/spike (may not be sufficient precaution in all use cases) */
  204. if (mode != gpioModeDisabled)
  205. {
  206. if (out)
  207. {
  208. GPIO->P[port].DOUTSET = 1 << pin;
  209. }
  210. else
  211. {
  212. GPIO->P[port].DOUTCLR = 1 << pin;
  213. }
  214. }
  215. /* There are two registers controlling the pins for each port. The MODEL
  216. * register controls pins 0-7 and MODEH controls pins 8-15. */
  217. if (pin < 8)
  218. {
  219. GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xF << (pin * 4))) |
  220. (mode << (pin * 4));
  221. }
  222. else
  223. {
  224. GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xF << ((pin - 8) * 4))) |
  225. (mode << ((pin - 8) * 4));
  226. }
  227. if (mode == gpioModeDisabled)
  228. {
  229. if (out)
  230. {
  231. GPIO->P[port].DOUTSET = 1 << pin;
  232. }
  233. else
  234. {
  235. GPIO->P[port].DOUTCLR = 1 << pin;
  236. }
  237. }
  238. }
  239. /***************************************************************************//**
  240. * @brief
  241. * Set a single pin in GPIO data out port register to 0.
  242. *
  243. * @note
  244. * In order for the setting to take effect on the output pad, the pin must
  245. * have been configured properly. If not, it will take effect whenever the
  246. * pin has been properly configured.
  247. *
  248. * @param[in] port
  249. * The GPIO port to access.
  250. *
  251. * @param[in] pin
  252. * The pin to set.
  253. ******************************************************************************/
  254. void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin)
  255. {
  256. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  257. GPIO->P[port].DOUTCLR = 1 << pin;
  258. }
  259. /***************************************************************************//**
  260. * @brief
  261. * Get current setting for a pin in a GPIO port data out register.
  262. *
  263. * @param[in] port
  264. * The GPIO port to access.
  265. *
  266. * @param[in] pin
  267. * The pin to get setting for.
  268. *
  269. * @return
  270. * The DOUT setting for the requested pin, 0 or 1.
  271. ******************************************************************************/
  272. unsigned int GPIO_PinOutGet(GPIO_Port_TypeDef port, unsigned int pin)
  273. {
  274. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  275. return((unsigned int)((GPIO->P[port].DOUT >> pin) & 0x1));
  276. }
  277. /***************************************************************************//**
  278. * @brief
  279. * Set a single pin in GPIO data out register to 1.
  280. *
  281. * @note
  282. * In order for the setting to take effect on the output pad, the pin must
  283. * have been configured properly. If not, it will take effect whenever the
  284. * pin has been properly configured.
  285. *
  286. * @param[in] port
  287. * The GPIO port to access.
  288. *
  289. * @param[in] pin
  290. * The pin to set.
  291. ******************************************************************************/
  292. void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin)
  293. {
  294. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  295. GPIO->P[port].DOUTSET = 1 << pin;
  296. }
  297. /***************************************************************************//**
  298. * @brief
  299. * Toggle a single pin in GPIO port data out register.
  300. *
  301. * @note
  302. * In order for the setting to take effect on the output pad, the pin must
  303. * have been configured properly. If not, it will take effect whenever the
  304. * pin has been properly configured.
  305. *
  306. * @param[in] port
  307. * The GPIO port to access.
  308. *
  309. * @param[in] pin
  310. * The pin to toggle.
  311. ******************************************************************************/
  312. void GPIO_PinOutToggle(GPIO_Port_TypeDef port, unsigned int pin)
  313. {
  314. EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_PIN_VALID(pin));
  315. GPIO->P[port].DOUTTGL = 1 << pin;
  316. }
  317. /***************************************************************************//**
  318. * @brief
  319. * Read the pad values for GPIO port.
  320. *
  321. * @param[in] port
  322. * The GPIO port to access.
  323. ******************************************************************************/
  324. uint32_t GPIO_PortInGet(GPIO_Port_TypeDef port)
  325. {
  326. EFM_ASSERT(GPIO_PORT_VALID(port));
  327. return(GPIO->P[port].DIN & _GPIO_P_DIN_DIN_MASK);
  328. }
  329. /***************************************************************************//**
  330. * @brief
  331. * Set bits in DOUT register for a port to 0.
  332. *
  333. * @note
  334. * In order for the setting to take effect on the output pad, the pin must
  335. * have been configured properly. If not, it will take effect whenever the
  336. * pin has been properly configured.
  337. *
  338. * @param[in] port
  339. * The GPIO port to access.
  340. *
  341. * @param[in] pins
  342. * Bit mask for bits to clear in DOUT register.
  343. ******************************************************************************/
  344. void GPIO_PortOutClear(GPIO_Port_TypeDef port, uint32_t pins)
  345. {
  346. EFM_ASSERT(GPIO_PORT_VALID(port));
  347. GPIO->P[port].DOUTCLR = pins & _GPIO_P_DOUTCLR_DOUTCLR_MASK;
  348. }
  349. /***************************************************************************//**
  350. * @brief
  351. * Get current setting for a GPIO port data out register.
  352. *
  353. * @param[in] port
  354. * The GPIO port to access.
  355. *
  356. * @return
  357. * The data out setting for the requested port.
  358. ******************************************************************************/
  359. uint32_t GPIO_PortOutGet(GPIO_Port_TypeDef port)
  360. {
  361. EFM_ASSERT(GPIO_PORT_VALID(port));
  362. return(GPIO->P[port].DOUT & _GPIO_P_DOUT_DOUT_MASK);
  363. }
  364. /***************************************************************************//**
  365. * @brief
  366. * Set bits GPIO data out register to 1.
  367. *
  368. * @note
  369. * In order for the setting to take effect on the respective output pads, the
  370. * pins must have been configured properly. If not, it will take effect
  371. * whenever the pin has been properly configured.
  372. *
  373. * @param[in] port
  374. * The GPIO port to access.
  375. *
  376. * @param[in] pins
  377. * Bit mask for bits to set to 1 in DOUT register.
  378. ******************************************************************************/
  379. void GPIO_PortOutSet(GPIO_Port_TypeDef port, uint32_t pins)
  380. {
  381. EFM_ASSERT(GPIO_PORT_VALID(port));
  382. GPIO->P[port].DOUTSET = pins & _GPIO_P_DOUTSET_DOUTSET_MASK;
  383. }
  384. /***************************************************************************//**
  385. * @brief
  386. * Set GPIO port data out register.
  387. *
  388. * @note
  389. * In order for the setting to take effect on the respective output pads, the
  390. * pins must have been configured properly. If not, it will take effect
  391. * whenever the pin has been properly configured.
  392. *
  393. * @param[in] port
  394. * The GPIO port to access.
  395. *
  396. * @param[in] val
  397. * Value to write to port data out register.
  398. *
  399. * @param[in] mask
  400. * Mask indicating which bits to modify.
  401. ******************************************************************************/
  402. void GPIO_PortOutSetVal(GPIO_Port_TypeDef port, uint32_t val, uint32_t mask)
  403. {
  404. EFM_ASSERT(GPIO_PORT_VALID(port));
  405. GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
  406. }
  407. /***************************************************************************//**
  408. * @brief
  409. * Toggle a single pin in GPIO port data out register.
  410. *
  411. * @note
  412. * In order for the setting to take effect on the output pad, the pin must
  413. * have been configured properly. If not, it will take effect whenever the
  414. * pin has been properly configured.
  415. *
  416. * @param[in] port
  417. * The GPIO port to access.
  418. *
  419. * @param[in] pins
  420. * Bitmask with pins to toggle.
  421. ******************************************************************************/
  422. void GPIO_PortOutToggle(GPIO_Port_TypeDef port, uint32_t pins)
  423. {
  424. EFM_ASSERT(GPIO_PORT_VALID(port));
  425. GPIO->P[port].DOUTTGL = pins & _GPIO_P_DOUTTGL_DOUTTGL_MASK;
  426. }
  427. /** @} (end addtogroup GPIO) */
  428. /** @} (end addtogroup EM_Library) */