SerialBase.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* mbed Microcontroller Library
  2. * Copyright (c) 2006-2013 ARM Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "drivers/SerialBase.h"
  17. #include "platform/mbed_wait_api.h"
  18. #include "platform/mbed_critical.h"
  19. #include "platform/mbed_power_mgmt.h"
  20. #if DEVICE_SERIAL
  21. namespace mbed {
  22. SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
  23. #if DEVICE_SERIAL_ASYNCH
  24. _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
  25. _rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL),
  26. _rx_callback(NULL),
  27. #endif
  28. _serial(), _baud(baud)
  29. {
  30. // No lock needed in the constructor
  31. for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
  32. _irq[i] = NULL;
  33. }
  34. serial_init(&_serial, tx, rx);
  35. serial_baud(&_serial, _baud);
  36. serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
  37. }
  38. void SerialBase::baud(int baudrate)
  39. {
  40. lock();
  41. serial_baud(&_serial, baudrate);
  42. _baud = baudrate;
  43. unlock();
  44. }
  45. void SerialBase::format(int bits, Parity parity, int stop_bits)
  46. {
  47. lock();
  48. serial_format(&_serial, bits, (SerialParity)parity, stop_bits);
  49. unlock();
  50. }
  51. int SerialBase::readable()
  52. {
  53. lock();
  54. int ret = serial_readable(&_serial);
  55. unlock();
  56. return ret;
  57. }
  58. int SerialBase::writeable()
  59. {
  60. lock();
  61. int ret = serial_writable(&_serial);
  62. unlock();
  63. return ret;
  64. }
  65. void SerialBase::attach(Callback<void()> func, IrqType type)
  66. {
  67. lock();
  68. // Disable interrupts when attaching interrupt handler
  69. core_util_critical_section_enter();
  70. if (func) {
  71. // lock deep sleep only the first time
  72. if (!_irq[type]) {
  73. sleep_manager_lock_deep_sleep();
  74. }
  75. _irq[type] = func;
  76. serial_irq_set(&_serial, (SerialIrq)type, 1);
  77. } else {
  78. // unlock deep sleep only the first time
  79. if (_irq[type]) {
  80. sleep_manager_unlock_deep_sleep();
  81. }
  82. _irq[type] = NULL;
  83. serial_irq_set(&_serial, (SerialIrq)type, 0);
  84. }
  85. core_util_critical_section_exit();
  86. unlock();
  87. }
  88. void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type)
  89. {
  90. SerialBase *handler = (SerialBase *)id;
  91. if (handler->_irq[irq_type]) {
  92. handler->_irq[irq_type]();
  93. }
  94. }
  95. int SerialBase::_base_getc()
  96. {
  97. // Mutex is already held
  98. return serial_getc(&_serial);
  99. }
  100. int SerialBase::_base_putc(int c)
  101. {
  102. // Mutex is already held
  103. serial_putc(&_serial, c);
  104. return c;
  105. }
  106. void SerialBase::send_break()
  107. {
  108. lock();
  109. // Wait for 1.5 frames before clearing the break condition
  110. // This will have different effects on our platforms, but should
  111. // ensure that we keep the break active for at least one frame.
  112. // We consider a full frame (1 start bit + 8 data bits bits +
  113. // 1 parity bit + 2 stop bits = 12 bits) for computation.
  114. // One bit time (in us) = 1000000/_baud
  115. // Twelve bits: 12000000/baud delay
  116. // 1.5 frames: 18000000/baud delay
  117. serial_break_set(&_serial);
  118. wait_us(18000000 / _baud);
  119. serial_break_clear(&_serial);
  120. unlock();
  121. }
  122. void SerialBase::lock()
  123. {
  124. // Stub
  125. }
  126. void SerialBase:: unlock()
  127. {
  128. // Stub
  129. }
  130. SerialBase::~SerialBase()
  131. {
  132. // No lock needed in destructor
  133. // Detaching interrupts releases the sleep lock if it was locked
  134. for (int irq = 0; irq < IrqCnt; irq++) {
  135. attach(NULL, (IrqType)irq);
  136. }
  137. }
  138. #if DEVICE_SERIAL_FC
  139. void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2)
  140. {
  141. lock();
  142. FlowControl flow_type = (FlowControl)type;
  143. switch (type) {
  144. case RTS:
  145. serial_set_flow_control(&_serial, flow_type, flow1, NC);
  146. break;
  147. case CTS:
  148. serial_set_flow_control(&_serial, flow_type, NC, flow1);
  149. break;
  150. case RTSCTS:
  151. case Disabled:
  152. serial_set_flow_control(&_serial, flow_type, flow1, flow2);
  153. break;
  154. default:
  155. break;
  156. }
  157. unlock();
  158. }
  159. #endif
  160. #if DEVICE_SERIAL_ASYNCH
  161. int SerialBase::write(const uint8_t *buffer, int length, const event_callback_t &callback, int event)
  162. {
  163. if (serial_tx_active(&_serial)) {
  164. return -1; // transaction ongoing
  165. }
  166. start_write((void *)buffer, length, 8, callback, event);
  167. return 0;
  168. }
  169. int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t &callback, int event)
  170. {
  171. if (serial_tx_active(&_serial)) {
  172. return -1; // transaction ongoing
  173. }
  174. start_write((void *)buffer, length, 16, callback, event);
  175. return 0;
  176. }
  177. void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event)
  178. {
  179. _tx_callback = callback;
  180. _thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
  181. sleep_manager_lock_deep_sleep();
  182. serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage);
  183. }
  184. void SerialBase::abort_write(void)
  185. {
  186. // rx might still be active
  187. if (_rx_callback) {
  188. sleep_manager_unlock_deep_sleep();
  189. }
  190. _tx_callback = NULL;
  191. serial_tx_abort_asynch(&_serial);
  192. }
  193. void SerialBase::abort_read(void)
  194. {
  195. // tx might still be active
  196. if (_tx_callback) {
  197. sleep_manager_unlock_deep_sleep();
  198. }
  199. _rx_callback = NULL;
  200. serial_rx_abort_asynch(&_serial);
  201. }
  202. int SerialBase::set_dma_usage_tx(DMAUsage usage)
  203. {
  204. if (serial_tx_active(&_serial)) {
  205. return -1;
  206. }
  207. _tx_usage = usage;
  208. return 0;
  209. }
  210. int SerialBase::set_dma_usage_rx(DMAUsage usage)
  211. {
  212. if (serial_tx_active(&_serial)) {
  213. return -1;
  214. }
  215. _rx_usage = usage;
  216. return 0;
  217. }
  218. int SerialBase::read(uint8_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match)
  219. {
  220. if (serial_rx_active(&_serial)) {
  221. return -1; // transaction ongoing
  222. }
  223. start_read((void *)buffer, length, 8, callback, event, char_match);
  224. return 0;
  225. }
  226. int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match)
  227. {
  228. if (serial_rx_active(&_serial)) {
  229. return -1; // transaction ongoing
  230. }
  231. start_read((void *)buffer, length, 16, callback, event, char_match);
  232. return 0;
  233. }
  234. void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match)
  235. {
  236. _rx_callback = callback;
  237. _thunk_irq.callback(&SerialBase::interrupt_handler_asynch);
  238. sleep_manager_lock_deep_sleep();
  239. serial_rx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage);
  240. }
  241. void SerialBase::interrupt_handler_asynch(void)
  242. {
  243. int event = serial_irq_handler_asynch(&_serial);
  244. int rx_event = event & SERIAL_EVENT_RX_MASK;
  245. bool unlock_deepsleep = false;
  246. if (_rx_callback && rx_event) {
  247. unlock_deepsleep = true;
  248. _rx_callback.call(rx_event);
  249. }
  250. int tx_event = event & SERIAL_EVENT_TX_MASK;
  251. if (_tx_callback && tx_event) {
  252. unlock_deepsleep = true;
  253. _tx_callback.call(tx_event);
  254. }
  255. // unlock if tx or rx events are generated
  256. if (unlock_deepsleep) {
  257. sleep_manager_unlock_deep_sleep();
  258. }
  259. }
  260. #endif
  261. } // namespace mbed
  262. #endif