dtm_uart.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. /**
  13. @defgroup dtm_standalone main.c
  14. @{
  15. @ingroup ble_sdk_app_dtm_serial
  16. @brief Stand-alone DTM application for UART interface.
  17. */
  18. #include <stdint.h>
  19. #include <stdbool.h>
  20. #include "nrf.h"
  21. #include "ble_dtm.h"
  22. #include "nrf_gpio.h"
  23. #include "dtm_uart.h"
  24. #include "nrf_error.h"
  25. #include "app_util.h"
  26. #include "nrf_drv_uart.h"
  27. #include "app_util_platform.h"
  28. //Configuration parameters.
  29. #define BITRATE UART_BAUDRATE_BAUDRATE_Baud57600 /**< Serial bitrate on the UART */
  30. //@note: The BLE DTM 2-wire UART standard specifies 8 data bits, 1 stop bit, no flow control.
  31. //These parameters are not configurable in the BLE standard.
  32. /**@details Maximum iterations needed in the main loop between stop bit 1st byte and start bit 2nd
  33. * byte. DTM standard allows 5000us delay between stop bit 1st byte and start bit 2nd byte.
  34. * As the time is only known when a byte is received, then the time between between stop bit 1st
  35. * byte and stop bit 2nd byte becomes:
  36. * 5000us + transmission time of 2nd byte.
  37. *
  38. * Byte transmission time is (Baud rate of 19200):
  39. * 10bits * 1/19200 = approx. 520 us/byte (8 data bits + start & stop bit).
  40. *
  41. * Loop time on polling UART register for received byte is defined in ble_dtm.c as:
  42. * UART_POLL_CYCLE = 260 us
  43. *
  44. * The max time between two bytes thus becomes (loop time: 260us / iteration):
  45. * (5000us + 520us) / 260us / iteration = 21.2 iterations.
  46. *
  47. * This is rounded down to 21.
  48. *
  49. * @note If UART bit rate is changed, this value should be recalculated as well.
  50. */
  51. static uint32_t m_baud_rates[] = {[UART_BAUD_RATE_1200] = UART_BAUDRATE_BAUDRATE_Baud1200,
  52. [UART_BAUD_RATE_2400] = UART_BAUDRATE_BAUDRATE_Baud2400,
  53. [UART_BAUD_RATE_4800] = UART_BAUDRATE_BAUDRATE_Baud4800,
  54. [UART_BAUD_RATE_9600] = UART_BAUDRATE_BAUDRATE_Baud9600,
  55. [UART_BAUD_RATE_14400] = UART_BAUDRATE_BAUDRATE_Baud14400,
  56. [UART_BAUD_RATE_19200] = UART_BAUDRATE_BAUDRATE_Baud19200,
  57. [UART_BAUD_RATE_28800] = UART_BAUDRATE_BAUDRATE_Baud28800,
  58. [UART_BAUD_RATE_38400] = UART_BAUDRATE_BAUDRATE_Baud38400,
  59. [UART_BAUD_RATE_57600] = UART_BAUDRATE_BAUDRATE_Baud57600,
  60. [UART_BAUD_RATE_76800] = UART_BAUDRATE_BAUDRATE_Baud76800,
  61. [UART_BAUD_RATE_115200] = UART_BAUDRATE_BAUDRATE_Baud115200, };
  62. static uint32_t m_iteration[] = {[UART_BAUD_RATE_1200] = 51,
  63. [UART_BAUD_RATE_2400] = 35,
  64. [UART_BAUD_RATE_4800] = 27,
  65. [UART_BAUD_RATE_9600] = 23,
  66. [UART_BAUD_RATE_14400] = 21,
  67. [UART_BAUD_RATE_19200] = 21,
  68. [UART_BAUD_RATE_28800] = 20,
  69. [UART_BAUD_RATE_38400] = 20,
  70. [UART_BAUD_RATE_57600] = 19,
  71. [UART_BAUD_RATE_76800] = 19,
  72. [UART_BAUD_RATE_115200] = 19, };
  73. static uint32_t m_iterations_next_byte_max = 51;
  74. /**@brief Function for UART initialization.
  75. */
  76. static uint32_t uart_init(app_uart_stream_comm_params_t * p_comm_params)
  77. {
  78. if (p_comm_params->baud_rate > UART_BAUD_RATE_115200)
  79. {
  80. return NRF_ERROR_INVALID_PARAM;
  81. }
  82. nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
  83. config.pselrxd = p_comm_params->rx_pin_no;
  84. config.pseltxd = p_comm_params->tx_pin_no;
  85. config.baudrate = (nrf_uart_baudrate_t) m_baud_rates[p_comm_params->baud_rate];
  86. config.hwfc = NRF_UART_HWFC_DISABLED;
  87. config.parity = NRF_UART_PARITY_EXCLUDED;
  88. nrf_drv_uart_uninit();
  89. uint32_t err_code = nrf_drv_uart_init(&config, NULL);
  90. if (err_code != NRF_SUCCESS)
  91. {
  92. return err_code;
  93. }
  94. nrf_drv_uart_rx_enable();
  95. m_iterations_next_byte_max = m_iteration[p_comm_params->baud_rate];
  96. return NRF_SUCCESS;
  97. }
  98. /**@brief Function for splitting UART command bit fields into separate command parameters for the DTM library.
  99. *
  100. * @param[in] command The packed UART command.
  101. * @return result status from dtmlib.
  102. */
  103. static uint32_t dtm_cmd_put(uint16_t command)
  104. {
  105. dtm_cmd_t command_code = (command >> 14) & 0x03;
  106. dtm_freq_t freq = (command >> 8) & 0x3F;
  107. uint32_t length = (command >> 2) & 0x3F;
  108. dtm_pkt_type_t payload = command & 0x03;
  109. //Check for Vendor Specific payload.
  110. if (payload == 0x03)
  111. {
  112. /* Note that in a HCI adaption layer, as well as in the DTM PDU format,
  113. the value 0x03 is a distinct bit pattern (PRBS15). Even though BLE does not
  114. support PRBS15, this implementation re-maps 0x03 to DTM_PKT_VENDORSPECIFIC,
  115. to avoid the risk of confusion, should the code be extended to greater coverage.
  116. */
  117. payload = DTM_PKT_VENDORSPECIFIC;
  118. }
  119. return dtm_cmd(command_code, freq, length, payload);
  120. }
  121. /**@brief Function for application main entry.
  122. *
  123. * @details This function serves as an adaptation layer between a 2-wire UART interface and the
  124. * dtmlib. After initialization, DTM commands submitted through the UART are forwarded to
  125. * dtmlib and events (i.e. results from the command) is reported back through the UART.
  126. */
  127. uint32_t dtm_start(app_uart_stream_comm_params_t uart_comm_params)
  128. {
  129. uint32_t current_time;
  130. uint32_t dtm_error_code;
  131. uint32_t msb_time = 0; //Time when MSB of the DTM command was read. Used to catch stray bytes from "misbehaving" testers.
  132. bool is_msb_read = false; //True when MSB of the DTM command has been read and the application is waiting for LSB.
  133. uint16_t dtm_cmd_from_uart = 0; //Packed command containing command_code:freqency:length:payload in 2:6:6:2 bits.
  134. uint8_t rx_byte; //Last byte read from UART.
  135. dtm_event_t result; //Result of a DTM operation.
  136. uint32_t err_code;
  137. err_code = uart_init(&uart_comm_params);
  138. if (err_code != NRF_SUCCESS)
  139. {
  140. return err_code;
  141. }
  142. dtm_error_code = dtm_init();
  143. if (dtm_error_code != DTM_SUCCESS)
  144. {
  145. //If DTM cannot be correctly initialized, then we just return.
  146. return NRF_ERROR_INTERNAL;
  147. }
  148. for (;; )
  149. {
  150. //Will return every timeout, 625 us.
  151. current_time = dtm_wait();
  152. if (NRF_SUCCESS != nrf_drv_uart_rx(&rx_byte,1))
  153. {
  154. return NRF_ERROR_INTERNAL;
  155. }
  156. if (!is_msb_read)
  157. {
  158. //This is first byte of two-byte command.
  159. is_msb_read = true;
  160. dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
  161. msb_time = current_time;
  162. //Go back and wait for 2nd byte of command word.
  163. continue;
  164. }
  165. //This is the second byte read; combine it with the first and process command
  166. if (current_time > (msb_time + m_iterations_next_byte_max))
  167. {
  168. //More than ~5mS after msb: Drop old byte, take the new byte as MSB.
  169. //The variable is_msb_read will remains true.
  170. //Go back and wait for 2nd byte of the command word.
  171. dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
  172. msb_time = current_time;
  173. continue;
  174. }
  175. //2-byte UART command received.
  176. is_msb_read = false;
  177. dtm_cmd_from_uart |= (dtm_cmd_t)rx_byte;
  178. if (dtm_cmd_put(dtm_cmd_from_uart) != DTM_SUCCESS)
  179. {
  180. //Extended error handling may be put here.
  181. //Default behavior is to return the event on the UART (see below);
  182. //the event report will reflect any lack of success.
  183. }
  184. //Retrieve result of the operation. This implementation will busy-loop
  185. //for the duration of the byte transmissions on the UART.
  186. if (dtm_event_get(&result))
  187. {
  188. //Report command status on the UART.
  189. uint8_t tx_byte = (result >> 8) & 0xFF;
  190. //Transmit MSB of the result.
  191. (void)nrf_drv_uart_tx(&tx_byte, 1);
  192. //Transmit LSB of the result.
  193. tx_byte = result & 0xFF;
  194. (void)nrf_drv_uart_tx(&tx_byte, 1);
  195. }
  196. }
  197. }
  198. /// @}