sama_onewire.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /**
  14. * @file SAMA5D2x/sama_onewire.c
  15. * @brief SAMA ONEWIRE support code.
  16. *
  17. * @addtogroup SAMA5D2x_ONEWIRE
  18. * @{
  19. */
  20. #include "hal.h"
  21. #if (SAMA_USE_ONEWIRE) || defined(__DOXYGEN__)
  22. /*===========================================================================*/
  23. /* Driver local definitions. */
  24. /*===========================================================================*/
  25. /**
  26. * @name Delays in standard speed mode.
  27. * @{
  28. */
  29. #define A US2RTC(SAMA_PCK, 6)
  30. #define B US2RTC(SAMA_PCK, 64)
  31. #define C US2RTC(SAMA_PCK, 60)
  32. #define D US2RTC(SAMA_PCK, 10)
  33. #define E US2RTC(SAMA_PCK, 9)
  34. #define F US2RTC(SAMA_PCK, 55)
  35. #define G US2RTC(SAMA_PCK, 0)
  36. #define H US2RTC(SAMA_PCK, 480)
  37. #define I US2RTC(SAMA_PCK, 70)
  38. #define J US2RTC(SAMA_PCK, 410)
  39. /** @} */
  40. #if SAMA_HAL_IS_SECURE
  41. #define PAD_INPUT_MODE PAL_SAMA_FUNC_GPIO | \
  42. PAL_SAMA_DIR_INPUT | \
  43. PAL_SAMA_OPD_OPENDRAIN | \
  44. PAL_SAMA_PUEN_PULLUP | \
  45. PAL_MODE_SECURE
  46. #define PAD_OUTPUT_MODE PAL_SAMA_FUNC_GPIO | \
  47. PAL_SAMA_DIR_OUTPUT | \
  48. PAL_SAMA_OPD_OPENDRAIN | \
  49. PAL_SAMA_PUEN_PULLUP | \
  50. PAL_MODE_SECURE
  51. #else
  52. #define PAD_INPUT_MODE PAL_SAMA_FUNC_GPIO | \
  53. PAL_SAMA_DIR_INPUT | \
  54. PAL_SAMA_OPD_OPENDRAIN | \
  55. PAL_SAMA_PUEN_PULLUP
  56. #define PAD_OUTPUT_MODE PAL_SAMA_FUNC_GPIO | \
  57. PAL_SAMA_DIR_OUTPUT | \
  58. PAL_SAMA_OPD_OPENDRAIN | \
  59. PAL_SAMA_PUEN_PULLUP
  60. #endif /* SAMA_HAL_IS_SECURE */
  61. /*===========================================================================*/
  62. /* Driver local macros. */
  63. /*===========================================================================*/
  64. /**
  65. * @brief Set ONEWIRE pin in output mode.
  66. *
  67. * @param[in] onewp pointer to a ONEWIRE driver.
  68. *
  69. * @notapi
  70. */
  71. #define onewireSetPinOutput(onewp) { \
  72. palSetLineMode(onewp->config->line, PAD_OUTPUT_MODE); \
  73. }
  74. /**
  75. * @brief Set ONEWIRE pin in input mode.
  76. *
  77. * @param[in] onewp pointer to a ONEWIRE driver.
  78. *
  79. * @notapi
  80. */
  81. #define onewireSetPinInput(onewp) { \
  82. palSetLineMode(onewp->config->line, PAD_INPUT_MODE); \
  83. }
  84. /*===========================================================================*/
  85. /* Driver exported variables. */
  86. /*===========================================================================*/
  87. ONEWIREDriver ONEWD0;
  88. /*===========================================================================*/
  89. /* Driver interrupt handlers. */
  90. /*===========================================================================*/
  91. /*===========================================================================*/
  92. /* Driver local variables. */
  93. /*===========================================================================*/
  94. /*===========================================================================*/
  95. /* Driver local functions. */
  96. /*===========================================================================*/
  97. /**
  98. * @brief Low level ONEWIRE driver initialization.
  99. *
  100. * @notapi
  101. */
  102. void onewire_lld_init(void) {
  103. onewireObjectInit(&ONEWD0);
  104. }
  105. /**
  106. * @brief Configures and activates the ONEWIRE pin.
  107. *
  108. * @param[in] onewp pointer to the @p ONEWIREDriver object
  109. *
  110. * @notapi
  111. */
  112. void onewire_lld_start(ONEWIREDriver *onewp) {
  113. /* Set the ONEWIRE pin in output mode. */
  114. onewireSetPinOutput(onewp);
  115. }
  116. /**
  117. * @brief Deactivates the ONEWIRE driver.
  118. *
  119. * @param[in] onewp pointer to the @p ONEWIREDriver object
  120. *
  121. * @notapi
  122. */
  123. void onewire_lld_stop(ONEWIREDriver *onewp) {
  124. (void) onewp;
  125. }
  126. /**
  127. * @brief Send a Reset on ONEWIRE pin.
  128. * The reset detect the slave presence on the pin
  129. * and ready it for a command.
  130. *
  131. * @param[in] onewp pointer to the @p ONEWIREDriver object
  132. * @return result result of the reset, if 0 a slave is detected
  133. *
  134. * @notapi
  135. */
  136. bool onewire_lld_reset(ONEWIREDriver *onewp) {
  137. bool result = TRUE;
  138. /* At the beginning set the pin in output mode. */
  139. onewireSetPinOutput(onewp);
  140. /* Wait 0 microseconds. */
  141. chSysPolledDelayX(G);
  142. /* Drives pin low. */
  143. palClearLine(onewp->config->line);
  144. /* Wait 480 microseconds. */
  145. chSysPolledDelayX(H);
  146. /* Drives pin high. */
  147. palSetLine(onewp->config->line);
  148. /* Wait 70 microseconds. */
  149. chSysPolledDelayX(I);
  150. /* Set the pin in input mode. */
  151. onewireSetPinInput(onewp);
  152. /* Read the pin logic state. */
  153. result = palReadLine(onewp->config->line);
  154. /* Wait 410 microseconds. */
  155. chSysPolledDelayX(J);
  156. return result;
  157. }
  158. /**
  159. * @brief Write a bit through ONEWIRE pin.
  160. *
  161. * @param[in] onewp pointer to the @p ONEWIREDriver object
  162. * @param[in] value bit value to write
  163. *
  164. * @notapi
  165. */
  166. void onewire_lld_write_bit(ONEWIREDriver *onewp, uint8_t value) {
  167. osalDbgAssert((value == 0u) || (value == 1u),
  168. "invalid value");
  169. /* Set the pin in output mode. */
  170. onewireSetPinOutput(onewp);
  171. if (value) {
  172. /* Write '1' bit */
  173. /* Drives pin low. */
  174. palClearLine(onewp->config->line);
  175. /* Wait 6 microsecond. */
  176. chSysPolledDelayX(A);
  177. /* Drives pin high. */
  178. palSetLine(onewp->config->line);
  179. /* Wait 64 microseconds to complete the time slot and recovery. */
  180. chSysPolledDelayX(B);
  181. }
  182. else {
  183. /* Write '0' bit */
  184. /* Drives pin low. */
  185. palClearLine(onewp->config->line);
  186. /* Wait 60 microsecond. */
  187. chSysPolledDelayX(C);
  188. /* Drives pin high. */
  189. palSetLine(onewp->config->line);
  190. /* Wait 10 microseconds for recovery. */
  191. chSysPolledDelayX(D);
  192. }
  193. }
  194. /**
  195. * @brief Read a bit through ONEWIRE pin.
  196. *
  197. * @param[in] onewp pointer to the @p ONEWIREDriver object
  198. * @return value bit read
  199. *
  200. * @notapi
  201. */
  202. uint8_t onewire_lld_read_bit(ONEWIREDriver *onewp) {
  203. uint8_t value;
  204. /* At the beginning set the pin in output mode. */
  205. onewireSetPinOutput(onewp);
  206. /* Drives pin low. */
  207. palClearLine(onewp->config->line);
  208. /* Wait 6 microsecond. */
  209. chSysPolledDelayX(A);
  210. /* Drives pin high. */
  211. palSetLine(onewp->config->line);
  212. /* Wait 9 microseconds. */
  213. chSysPolledDelayX(E);
  214. /* Set the pin in input mode. */
  215. onewireSetPinInput(onewp);
  216. /* Read the pin logic state. */
  217. value = palReadLine(onewp->config->line);
  218. /* Wait 55 microseconds. */
  219. chSysPolledDelayX(F);
  220. return value;
  221. }
  222. /**
  223. * @brief Write a byte through ONEWIRE pin.
  224. *
  225. * @param[in] onewp pointer to the @p ONEWIREDriver object
  226. * @param[in] byte byte to write
  227. *
  228. * @notapi
  229. */
  230. void onewire_lld_write_byte(ONEWIREDriver *onewp, uint8_t byte) {
  231. uint8_t i;
  232. /* Loop to write each bit in the byte, LS-bit first */
  233. for (i = 0; i < 8; i++) {
  234. onewire_lld_write_bit(onewp, (byte & 0x01));
  235. /* Shift the data byte for the next bit */
  236. byte >>= 1;
  237. }
  238. }
  239. /**
  240. * @brief Read a byte through ONEWIRE pin.
  241. *
  242. * @param[in] onewp pointer to the @p ONEWIREDriver object
  243. * return value byte read
  244. *
  245. * @notapi
  246. */
  247. uint8_t onewire_lld_read_byte(ONEWIREDriver *onewp) {
  248. uint8_t i;
  249. uint8_t value = 0;
  250. for (i = 0; i < 8; i++) {
  251. /* Shift the result to get it ready for the next bit */
  252. value >>= 1;
  253. /* If result is one, then set MS bit */
  254. if (onewire_lld_read_bit(onewp))
  255. value |= 0x80;
  256. }
  257. return value;
  258. }
  259. /*===========================================================================*/
  260. /* Driver exported functions. */
  261. /*===========================================================================*/
  262. /**
  263. * @brief ONEWIRE driver initialization.
  264. *
  265. * @api
  266. */
  267. void onewireInit(void) {
  268. onewire_lld_init();
  269. }
  270. /**
  271. * @brief Initializes the standard part of a @p ONEWIREDriver structure.
  272. *
  273. * @param[out] onewp pointer to the @p ONEWIREDriver object
  274. *
  275. * @init
  276. */
  277. void onewireObjectInit(ONEWIREDriver *onewp) {
  278. onewp->state = ONEW_STOP;
  279. onewp->config = NULL;
  280. osalMutexObjectInit(&onewp->mutex);
  281. }
  282. /**
  283. * @brief Configures and activates the ONEWIRE pin.
  284. *
  285. * @param[in] onewp pointer to the @p ONEWIREDriver object
  286. * @param[in] config pointer to the @p ONEWIREConfig object
  287. *
  288. * @api
  289. */
  290. void onewireStart(ONEWIREDriver *onewp, const ONEWIREConfig *config) {
  291. osalDbgCheck((onewp != NULL) && (config != NULL));
  292. osalSysLock();
  293. osalDbgAssert((onewp->state == ONEW_STOP) || (onewp->state == ONEW_READY),
  294. "invalid state");
  295. onewp->config = config;
  296. onewire_lld_start(onewp);
  297. onewp->state = ONEW_READY;
  298. osalSysUnlock();
  299. }
  300. /**
  301. * @brief Deactivates the ONEWIRE driver.
  302. *
  303. * @param[in] onewp pointer to the @p ONEWIREDriver object
  304. *
  305. * @api
  306. */
  307. void onewireStop(ONEWIREDriver *onewp) {
  308. osalDbgCheck(onewp != NULL);
  309. osalSysLock();
  310. osalDbgAssert((onewp->state == ONEW_STOP) || (onewp->state == ONEW_READY),
  311. "invalid state");
  312. onewire_lld_stop(onewp);
  313. onewp->config = NULL;
  314. onewp->state = ONEW_STOP;
  315. osalSysUnlock();
  316. }
  317. /**
  318. * @brief Write a block of bytes through ONEWIRE pin.
  319. *
  320. * @param[in] onewp pointer to the @p ONEWIREDriver object
  321. * @param[in] txbuf the pointer to the transmit buffer
  322. * @param[in] n number of bytes to write
  323. *
  324. * @api
  325. */
  326. void onewireWriteBlockI(ONEWIREDriver *onewp, uint8_t *txbuf, size_t n) {
  327. uint32_t i;
  328. (onewp)->state = ONEW_ACTIVE;
  329. for (i = 0; i < n; i++) {
  330. onewire_lld_write_byte(onewp, txbuf[i]);
  331. }
  332. }
  333. /**
  334. * @brief Write a block of bytes through ONEWIRE pin.
  335. *
  336. * @param[in] onewp pointer to the @p ONEWIREDriver object
  337. * @param[in] txbuf the pointer to the transmit buffer
  338. * @param[in] n number of bytes to write
  339. *
  340. * @api
  341. */
  342. void onewireWriteBlock(ONEWIREDriver *onewp, uint8_t *txbuf, size_t n) {
  343. osalDbgCheck(onewp != NULL);
  344. osalSysLock();
  345. osalDbgAssert(onewp->state == ONEW_READY, "not ready");
  346. onewireWriteBlockI(onewp, txbuf, n);
  347. (onewp)->state = ONEW_READY;
  348. osalSysUnlock();
  349. }
  350. /**
  351. * @brief Read a block of bytes through ONEWIRE pin.
  352. *
  353. * @param[in] onewp pointer to the @p ONEWIREDriver object
  354. * @param[out]rxbuf pointer to the receive buffer
  355. * @param[in] n number of bytes to read
  356. *
  357. * @api
  358. */
  359. void onewireReadBlockI(ONEWIREDriver *onewp, uint8_t *rxbuf, size_t n) {
  360. uint32_t i;
  361. (onewp)->state = ONEW_ACTIVE;
  362. for (i = 0; i < n; i++) {
  363. rxbuf[i] = onewire_lld_read_byte(onewp);
  364. }
  365. }
  366. /**
  367. * @brief Read a block of bytes through ONEWIRE pin.
  368. *
  369. * @param[in] onewirep pointer to the @p ONEWIREDriver object
  370. * @param[out]rxbuf pointer to the receive buffer
  371. * @param[in] n number of bytes to read
  372. *
  373. * @api
  374. */
  375. void onewireReadBlock(ONEWIREDriver *onewp, uint8_t *rxbuf, size_t n) {
  376. osalDbgCheck(onewp != NULL);
  377. // osalSysLock();
  378. osalDbgAssert(onewp->state == ONEW_READY, "not ready");
  379. onewireReadBlockI(onewp, rxbuf, n);
  380. (onewp)->state = ONEW_READY;
  381. // osalSysUnlock();
  382. }
  383. /**
  384. * @brief Send a Reset on ONEWIRE pin.
  385. * The reset detect the slave presence on the pin
  386. * and ready it for a command.
  387. *
  388. * @param[in] onewp pointer to the @p ONEWIREDriver object
  389. * @return result result of the reset, if 0 a slave is detected
  390. *
  391. * @api
  392. */
  393. bool onewireReset(ONEWIREDriver *onewp) {
  394. bool detect = TRUE;
  395. osalDbgCheck(onewp != NULL);
  396. osalSysLock();
  397. osalDbgAssert(onewp->state == ONEW_READY,
  398. "invalid state");
  399. detect = onewire_lld_reset(onewp);
  400. osalSysUnlock();
  401. return detect;
  402. }
  403. /*
  404. * @brief Sends a command.
  405. *
  406. * @param[in] onewp pointer to the @p ONEWIREDriver object
  407. * @param[in] cmdp pointer command byte
  408. *
  409. * @api
  410. */
  411. void onewireCommandI(ONEWIREDriver *onewp, uint8_t *cmdp, size_t n) {
  412. uint32_t i;
  413. (onewp)->state = ONEW_ACTIVE;
  414. for (i = 0; i < n; i++) {
  415. onewire_lld_write_byte(onewp, cmdp[i]);
  416. }
  417. }
  418. /*
  419. * @brief Sends a command.
  420. *
  421. * @param[in] onewp pointer to the @p ONEWIREDriver object
  422. * @param[in] cmdp pointer to command
  423. *
  424. * @api
  425. */
  426. void onewireCommand(ONEWIREDriver *onewp, uint8_t *cmdp, size_t n) {
  427. osalDbgCheck((onewp != NULL) && (cmdp != NULL));
  428. // osalSysLock();
  429. osalDbgAssert(onewp->state == ONEW_READY, "not ready");
  430. onewireCommandI(onewp, cmdp, n);
  431. (onewp)->state = ONEW_READY;
  432. // osalSysUnlock();
  433. }
  434. /**
  435. * @brief Gains exclusive access to the ONEWIRE bus.
  436. * @details This function tries to gain ownership to the ONEWIRE bus, if the bus
  437. * is already being used then the invoking thread is queued.
  438. *
  439. * @param[in] onewp pointer to the @p ONEWIREDriver object
  440. *
  441. * @api
  442. */
  443. void onewireAcquireBus(ONEWIREDriver *onewp) {
  444. osalDbgCheck(onewp != NULL);
  445. osalMutexLock(&onewp->mutex);
  446. }
  447. /**
  448. * @brief Releases exclusive access to the ONEWIRE bus.
  449. *
  450. * @param[in] onewp pointer to the @p ONEWIREDriver object
  451. *
  452. * @api
  453. */
  454. void onewireReleaseBus(ONEWIREDriver *onewp) {
  455. osalDbgCheck(onewp != NULL);
  456. osalMutexUnlock(&onewp->mutex);
  457. }
  458. #endif /* SAMA_USE_ONEWIRE == TRUE */
  459. /** @} */