Advertisement
RobMeades

stm32f4 UART init()/deinit() v2

Apr 29th, 2020
1,658
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 38.85 KB | None | 0 0
  1. /*
  2.  * Copyright 2020 u-blox Cambourne Ltd
  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.  
  17. #ifdef CELLULAR_CFG_OVERRIDE
  18. # include "cellular_cfg_override.h" // For a customer's configuration override
  19. #endif
  20. #include "cellular_cfg_sw.h"
  21. #include "cellular_port_debug.h"
  22. #include "cellular_port_clib.h"
  23. #include "cellular_port.h"
  24. #include "cellular_port_os.h"
  25. #include "cellular_port_uart.h"
  26. #include "cellular_port_private.h"
  27.  
  28. #include "FreeRTOS.h"
  29. #include "queue.h"
  30. #include "task.h"
  31.  
  32. #include "nrf.h"
  33. #include "nrf_uarte.h"
  34. #include "nrf_gpio.h"
  35.  
  36. /* Note: in order to implement the API we require, where receipt
  37.  * of data is signalled by an event queue and other things can
  38.  * send to that same event queue, this code is implemented on top of
  39.  * the nrf_uarte.h HAL and replaces the nrfx_uarte.h default driver
  40.  * from Nordic.  It steals from the code in nrfx_uarte.c, Nordic's
  41.  * implementation.
  42.  *
  43.  * So that users can continue to use the Nordic UARTE driver this
  44.  * code uses only the UART port that the Nordic UARTE driver is NOT
  45.  * using: for instance, to use UARTE1 in this driver then
  46.  * NRFX_UARTE1_ENABLED should be set to 0 in sdk_config to free it
  47.  * up.
  48.  *
  49.  * Design note: at first this code used DMA plus a per-character
  50.  * interrupt to count the characters and send an event when the
  51.  * number unread transitioned from 0 to 1 but the load of sending the
  52.  * event was too high and interrupts were missed, leading to losing
  53.  * count. So the timer already in use for cellularPortGetTickTimeMs()
  54.  * was modified to generate interrupts more quickly (130 ms interval)
  55.  * when the UART is operating and take a callback which could be
  56.  * used to stop the free-running DMA and query it for the number
  57.  * of characters received.  This worked well except that it was
  58.  * still pouring characters directly into the destination buffer
  59.  * and this caused a problem towards the end of the buffer where
  60.  * the space for DMA would be getting close to zero and the load of
  61.  * setup etc. for the next DMA became too much.  So instead the
  62.  * buffer space was split into separately managed sub-buffers, at
  63.  * least two in number, and then advantage could be taken of the
  64.  * hardware's ability to set up a second buffer in advance
  65.  * of the first completing ('cos the buffer pointer register is
  66.  * itself buffered).  Finally, no character loss, though some buffer
  67.  * management is required at setup and when reading the data out again.
  68.  */
  69.  
  70. /* ----------------------------------------------------------------
  71.  * COMPILE-TIME MACROS
  72.  * -------------------------------------------------------------- */
  73.  
  74. // The maximum number of UARTs supported, which is the range of the
  75. // "uart" parameter on this platform
  76. #ifndef NRFX_UARTE_ENABLED
  77. // NRFX_UARTE is not enabled, we can have both
  78. # define CELLULAR_PORT_UART_MAX_NUM 2
  79. #else
  80. # if !NRFX_UARTE0_ENABLED && !NRFX_UARTE1_ENABLED
  81. // NRFX_UARTE is enabled but neither UARTEx is enabled so we can
  82. // have both
  83. #  define CELLULAR_PORT_UART_MAX_NUM 2
  84. # else
  85. #  if !NRFX_UARTE0_ENABLED || !NRFX_UARTE1_ENABLED
  86. #    define CELLULAR_PORT_UART_MAX_NUM 1
  87. #  else
  88. #    error No UARTs available, both are being used by the Nordic NRFX_UARTE driver; to use this code at least one of NRFX_UARTE0_ENABLED or NRFX_UARTE1_ENABLED must be set to 0.
  89. #  endif
  90. # endif
  91. #endif
  92.  
  93. // Length of DMA on NRF52840 HW.
  94. // Note that the maximum length is 256 however
  95. // the cost of starting a new DMA buffer is
  96. // neglibile (since the pointer is double-buffered
  97. // buffered in HW) and there's a load of buggering
  98. // around one needs to do to make the flow of data
  99. // responsive so it's actually better to have
  100. // more smaller buffers
  101. #ifndef CELLULAR_PORT_UART_SUB_BUFFER_SIZE
  102. # define CELLULAR_PORT_UART_SUB_BUFFER_SIZE 128
  103. #endif
  104.  
  105. // The number of sub-buffers.
  106. // We want at least two buffers and beyond that a number of buffers
  107. // that brings the size of each under the maximum DMA length.
  108. // IMPORTANT: this means that for this platform it is best if
  109. // CELLULAR_PORT_UART_RX_BUFFER_SIZE is a multiple of
  110. // CELLULAR_PORT_UART_SUB_BUFFER_SIZE, which it is with the
  111. // default of 1024.
  112. #define CELLULAR_PORT_UART_NUM_SUB_BUFFERS (CELLULAR_PORT_UART_RX_BUFFER_SIZE / CELLULAR_PORT_UART_SUB_BUFFER_SIZE)
  113.  
  114. #if CELLULAR_PORT_UART_NUM_SUB_BUFFERS < 4
  115. # error Cannot accommodate four sub-buffers, either increase CELLULAR_PORT_UART_RX_BUFFER_SIZE to a larger multiple of CELLULAR_PORT_UART_SUB_BUFFER_SIZE or reduce CELLULAR_PORT_UART_SUB_BUFFER_SIZE.
  116. #endif
  117.  
  118. /* ----------------------------------------------------------------
  119.  * TYPES
  120.  * -------------------------------------------------------------- */
  121.  
  122. /** State enum to keep track of what's happening during
  123.  * a STOPRX/FLUSH */
  124.  typedef enum {
  125.      CELLULAR_PORT_UART_STATE_RECEIVING,
  126.      CELLULAR_PORT_UART_STATE_STOPPING,
  127.      CELLULAR_PORT_UART_STATE_FLUSHING
  128.  } CellularPortUartState_t;
  129.  
  130. /** Structure to hold a UART event.
  131.  */
  132. typedef struct {
  133.     int32_t type;
  134.     size_t size;
  135. } CellularPortUartEventData_t;
  136.  
  137. /** UART buffer structure, which can be used as a list.
  138.  */
  139. typedef struct CellularPortUartBuffer_t {
  140.     char *pStart;
  141.     char *pRead;
  142.     volatile size_t toRead;
  143.     struct CellularPortUartBuffer_t *pNext;
  144. } CellularPortUartBuffer_t;
  145.  
  146. /** Structure of the things we need to keep track of per UART.
  147.  */
  148. typedef struct {
  149.     NRF_UARTE_Type *pReg;
  150.     CellularPortMutexHandle_t mutex;
  151.     CellularPortQueueHandle_t queue;
  152.     CellularPortUartBuffer_t *pRxBufferRead;
  153.     volatile CellularPortUartBuffer_t *pRxBufferWrite;
  154.     volatile CellularPortUartBuffer_t *pRxBufferWriteNext;
  155.     CellularPortUartState_t state;
  156.     bool userNeedsNotify; //!< set this if toRead has hit zero and
  157.                           // hence the user would like a notification
  158.                           // when new data arrives.
  159.     CellularPortUartBuffer_t rxBufferList[CELLULAR_PORT_UART_NUM_SUB_BUFFERS];
  160. } CellularPortUartData_t;
  161.  
  162. /* ----------------------------------------------------------------
  163.  * VARIABLES
  164.  * -------------------------------------------------------------- */
  165.  
  166. // UART data, where the UARTE register is the only one initialised here.
  167. #if !NRFX_UARTE0_ENABLED && !NRFX_UARTE1_ENABLED
  168. static CellularPortUartData_t gUartData[] = {{NRF_UARTE0, },
  169.                                              {NRF_UARTE1, }};
  170. # else
  171. #  if !NRFX_UARTE0_ENABLED
  172. static CellularPortUartData_t gUartData[] = {NRF_UARTE0, };
  173. #  else
  174. static CellularPortUartData_t gUartData[] = {NRF_UARTE1, };
  175. #  endif
  176. #endif
  177.  
  178. /* ----------------------------------------------------------------
  179.  * STATIC FUNCTIONS
  180.  * -------------------------------------------------------------- */
  181.  
  182. // Figure 4 in the UARTE Reception section
  183. // of the nRF52840 Product Specification is critical
  184. // here!  So that you can follow, here is a
  185. // version of it in ASCII.
  186. //
  187. // Ref.  Timeline                                    UART RX bytes    DMA destination   DMA bytes
  188. // 1:  we set SHORT_ENDRX_STARTRX = true
  189. // 2:  we set RXD.PTR = a
  190. // 3:  we set RXD.MAXCOUNT = 10
  191. // 4:  we trigger TASK_STARTRX
  192. // 5:                                                      1
  193. // 6:  event EVENT_RXSTARTED                               2                  a             1
  194. // 7:  we set RXD.PTR = b                                  3                  a             2
  195. // 8:                                                      4                  a             3
  196. // 9:                                                      5                  a             4
  197. // 10:                                                     6                  a             5
  198. // 11:                                                     7                  a             6
  199. // 12:                                                     8                  a             7
  200. // 13:                                                     9                  a             8
  201. // 14:                                                     10                 a             9
  202. // 15:                                                     11                 a             10
  203. // 16: events EVENT_ENDRX ('cos DMA hit 10) and STARTRX    12                 b             11
  204. // 17: event EVENT_RXSTARTED                               13                 b             12
  205. // 18: we set RXD.PTR = c                                  14                 b             13
  206. // 19:                                                     15                 b             14
  207. // 20: our timer goes off                                  16                 b             15
  208. // 21: we set SHORT_ENDRX_STARTRX = false                  17                 b             16
  209. // 22: we trigger TASK_STOPRX                              18                 b             17
  210. // 23: event EVENT_ENDRX ('cos DMA has stopped)            19
  211. // 24:    ...                                              20
  212. // 25:    ...                                              21
  213. // 26: event EVENT_RXTO
  214. // 27: we trigger TASK_FLUSHRX to get bytes 18 to 21                          c             18
  215. // 28:                                                                        c             19
  216. // 29:                                                                        c             20
  217. // 30:                                                                        c             21
  218. // 31: event EVENT_ENDRX ('cos DMA has finished flushing)
  219. // 32: to continue:
  220. // 33:   we set SHORT_ENDRX_STARTRX = true
  221. // 34:   we set RXD.PTR = d
  222. // 35:   we set RXD.MAXCOUNT = 10
  223. // 36:   we trigger TASK_STARTRX
  224. // 37:                                                     22
  225. // 38: event EVENT_RXSTARTED                               23                 d             22
  226. // 39: we set RXD.PTR = e                                  34                 d             23
  227. // etc.
  228.  
  229. // Callback to be called when the receive check timer has expired.
  230. // pParameter must be a pointer to CellularPortUartData_t.
  231. static void rxCb(void *pParameter)
  232. {
  233.     CellularPortUartData_t *pUartData = (CellularPortUartData_t *) pParameter;
  234.     NRF_UARTE_Type *pReg = pUartData->pReg;
  235.  
  236.     // We are now at reference line 20 in the diagram.
  237.     // We will get an ENDRX event as a result of this
  238.     // STOPRX task, then an RXTO event in which time
  239.     // a few more characters may have trickled in.
  240.     // At that point we must do a FLUSHRX and get another
  241.     // ENDRX before continuing; the short needs to be
  242.     // disabled to prevent the start of a new receive
  243.     // as a result of the first ENDRX event.
  244.     nrf_uarte_shorts_disable(pReg, NRF_UARTE_SHORT_ENDRX_STARTRX);
  245.     // Remember that we're stopping
  246.     pUartData->state = CELLULAR_PORT_UART_STATE_STOPPING;
  247.     nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STOPRX);
  248. }
  249.  
  250. // The interrupt handler: only handles Rx events as Tx is blocking.
  251. static void rxIrqHandler(CellularPortUartData_t *pUartData)
  252. {
  253.     NRF_UARTE_Type *pReg = pUartData->pReg;
  254.     BaseType_t yield = false;
  255.  
  256.     if (nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_ENDRX)) {
  257.         volatile CellularPortUartBuffer_t *pRxBuffer;
  258.         size_t x;
  259.         // Clear the event
  260.         nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_ENDRX);
  261.         // Grab the count of the number of bytes DMAed
  262.         x = nrf_uarte_rx_amount_get(pReg);
  263.         if (pUartData->state == CELLULAR_PORT_UART_STATE_FLUSHING) {
  264.             // We are now at reference line 31 in the diagram.
  265.             // If we have just dealt with the flush we must
  266.             // now manually set off the next RX and re-enable
  267.             // the short.  A flush doesn't result in an
  268.             // RXSTARTED event so the buffer pointer won't
  269.             // have been moved on, hence we need to do that here.
  270.             nrf_uarte_rx_buffer_set(pReg,
  271.                                     (uint8_t *) (pUartData->pRxBufferWriteNext->pStart),
  272.                                     CELLULAR_PORT_UART_SUB_BUFFER_SIZE);
  273.             pUartData->pRxBufferWriteNext = pUartData->pRxBufferWriteNext->pNext;
  274.             // Now we can start again
  275.             nrf_uarte_shorts_enable(pReg, NRF_UARTE_SHORT_ENDRX_STARTRX);
  276.             nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STARTRX);
  277.             pUartData->state = CELLULAR_PORT_UART_STATE_RECEIVING;
  278.         }
  279.         // Remember where we are and move the current receive
  280.         // write buffer on.
  281.         pRxBuffer = pUartData->pRxBufferWrite;
  282.         pUartData->pRxBufferWrite = pUartData->pRxBufferWrite->pNext;
  283.         // Now update the read count
  284.         pRxBuffer->toRead = x;
  285.         // If there is at least some data and the user needs to
  286.         // be notified, let them know
  287.         if ((pRxBuffer->toRead > 0) && pUartData->userNeedsNotify) {
  288.             CellularPortUartEventData_t uartEvent;
  289.             uartEvent.type = 0;
  290.             uartEvent.size = pRxBuffer->toRead;
  291.             xQueueSendFromISR((QueueHandle_t *) (pUartData->queue),
  292.                               &uartEvent, &yield);
  293.             pUartData->userNeedsNotify = false;
  294.         }
  295.     } else if (nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_RXSTARTED)) {
  296.         // An RX has started so it's OK to update the buffer
  297.         // pointer registers in the hardware for the one that
  298.         // will follow after this one has ended as the
  299.         // Rx buffer register is double-buffered in HW.
  300.         nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_RXSTARTED);
  301.         nrf_uarte_rx_buffer_set(pReg,
  302.                                 (uint8_t *) (pUartData->pRxBufferWriteNext->pStart),
  303.                                 CELLULAR_PORT_UART_SUB_BUFFER_SIZE);
  304.         pUartData->pRxBufferWriteNext = pUartData->pRxBufferWriteNext->pNext;
  305.     } else if (nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_RXTO)) {
  306.         // We are now at reference line 26 in the diagram.
  307.         // We've been stopped, must have been a timeout.
  308.         // There may be stuff still in the FIFO that
  309.         // has not been DMA'ed.  To get that out, trigger
  310.         // a flush RX event.
  311.         nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_RXTO);
  312.         // The flush operation will write to the beginning
  313.         // of the receive buffer again, however will already
  314.         // have set up the new buffer pointer due to the
  315.         // previous RXSTARTED event so that shouldn't be a
  316.         // problem.
  317.         // Remember that we're flushing
  318.         pUartData->state = CELLULAR_PORT_UART_STATE_FLUSHING;
  319.         nrf_uarte_task_trigger(pUartData->pReg,
  320.                                NRF_UARTE_TASK_FLUSHRX);
  321.     } else if (nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_ERROR)) {
  322.         // Clear any errors: no need to do anything, they
  323.         // have no effect upon reception
  324.         nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_ERROR);
  325.         nrf_uarte_errorsrc_get_and_clear(pReg);
  326.     }
  327.  
  328.     // Required for FreeRTOS task scheduling to work
  329.     if (yield) {
  330.         taskYIELD();
  331.     }
  332. }
  333.  
  334. // Convert a baud rate into an NRF52840 baud rate.
  335. static int32_t baudRateToNrfBaudRate(int32_t baudRate)
  336. {
  337.     int32_t baudRateNrf = -1;
  338.  
  339.     switch (baudRate) {
  340.         case 1200:
  341.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud1200;
  342.         break;
  343.         case 2400:
  344.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud2400;
  345.         break;
  346.         case 9600:
  347.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud9600;
  348.         break;
  349.         case 14400:
  350.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud14400;
  351.         break;
  352.         case 19200:
  353.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud19200;
  354.         break;
  355.         case 28800:
  356.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud28800;
  357.         break;
  358.         case 31250:
  359.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud31250;
  360.         break;
  361.         case 38400:
  362.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud38400;
  363.         break;
  364.         case 56000:
  365.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud56000;
  366.         break;
  367.         case 57600:
  368.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud57600;
  369.         break;
  370.         case 76800:
  371.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud76800;
  372.         break;
  373.         case 115200:
  374.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud115200;
  375.         break;
  376.         case 230400:
  377.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud230400;
  378.         break;
  379.         case 250000:
  380.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud250000;
  381.         break;
  382.         case 460800:
  383.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud460800;
  384.         break;
  385.         case 921600:
  386.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud921600;
  387.         break;
  388.         case 1000000:
  389.             baudRateNrf = UARTE_BAUDRATE_BAUDRATE_Baud1M;
  390.         break;
  391.         default:
  392.         break;
  393.     }
  394.  
  395.     return baudRateNrf;
  396. }
  397.  
  398. // Derived from the NRFX functions nrfx_is_in_ram() and
  399. // nrfx_is_word_aligned(), check if a buffer pointer is good
  400. // for DMA
  401. __STATIC_INLINE bool isGoodForDma(void const *pBuffer)
  402. {
  403.     return (((((uint32_t) pBuffer) & 0x3u) == 0u) &&
  404.             ((((uint32_t) pBuffer) & 0xE0000000u) == 0x20000000u));
  405. }
  406.  
  407. // Derived from the NRFX function nrfx_get_irq_number()
  408. __STATIC_INLINE IRQn_Type getIrqNumber(void const *pReg)
  409. {
  410.     return (IRQn_Type) (uint8_t)((uint32_t)(pReg) >> 12);
  411. }
  412.  
  413. /* ----------------------------------------------------------------
  414.  * PUBLIC FUNCTIONS: INTERRUPT HANDLERS
  415.  * -------------------------------------------------------------- */
  416.  
  417. #if !NRFX_UARTE0_ENABLED
  418. void nrfx_uarte_0_irq_handler(void)
  419. {
  420.     rxIrqHandler(&(gUartData[0]));
  421. }
  422. #endif
  423.  
  424. #if !NRFX_UARTE1_ENABLED
  425. void nrfx_uarte_1_irq_handler(void)
  426. {
  427.     rxIrqHandler(&(gUartData[1]));
  428. }
  429. #endif
  430.  
  431. /* ----------------------------------------------------------------
  432.  * PUBLIC FUNCTIONS
  433.  * -------------------------------------------------------------- */
  434.  
  435. // Initialise a UARTE.
  436. int32_t cellularPortUartInit(int32_t pinTx, int32_t pinRx,
  437.                              int32_t pinCts, int32_t pinRts,
  438.                              int32_t baudRate,
  439.                              size_t rtsThreshold,
  440.                              int32_t uart,
  441.                              CellularPortQueueHandle_t *pUartQueue)
  442. {
  443.     CellularPortErrorCode_t errorCode = CELLULAR_PORT_INVALID_PARAMETER;
  444.     int32_t baudRateNrf = baudRateToNrfBaudRate(baudRate);
  445.     uint32_t pinCtsNrf = NRF_UARTE_PSEL_DISCONNECTED;
  446.     uint32_t pinRtsNrf = NRF_UARTE_PSEL_DISCONNECTED;
  447.     nrf_uarte_hwfc_t hwfc = NRF_UARTE_HWFC_DISABLED;
  448.     NRF_UARTE_Type *pReg;
  449.     char *pRxBuffer = NULL;
  450.  
  451.     // The RTS threshold is not adjustable on this platform,
  452.     // From the nRF52840 Product Specification, UARTE section:
  453.     // "The RTS signal will be deactivated when the receiver
  454.     // is stopped via the STOPRX task or when the UARTE is
  455.     // only able to receive four more bytes in its internal
  456.     // RX FIFO."
  457.     (void) rtsThreshold;
  458.  
  459.     if ((pUartQueue != NULL) && (pinRx >= 0) && (pinTx >= 0) &&
  460.         (uart < sizeof(gUartData) / sizeof(gUartData[0])) &&
  461.         (baudRateNrf >= 0)) {
  462.         errorCode = CELLULAR_PORT_SUCCESS;
  463.         if (gUartData[uart].mutex == NULL) {
  464.             pReg = gUartData[uart].pReg;
  465.  
  466. #if NRFX_PRS_ENABLED
  467.             static nrfx_irq_handler_t const irq_handlers[NRFX_UARTE_ENABLED_COUNT] = {
  468. # if !NRFX_UARTE0_ENABLED
  469.                 nrfx_uarte_0_irq_handler,
  470. # endif
  471. # if !NRFX_UARTE1_ENABLED
  472.                 nrfx_uarte_1_irq_handler,
  473. # endif
  474.             };
  475.             if (nrfx_prs_acquire(pReg, irq_handlers[pReg) != NRFX_SUCCESS) {
  476.                 errorCode = CELLULAR_PORT_PLATFORM_ERROR;
  477.             }
  478. #endif
  479.             if (errorCode == 0) {
  480.                 // Create the mutex
  481.                 errorCode = cellularPortMutexCreate(&(gUartData[uart].mutex));
  482.                 if (errorCode == 0) {
  483.  
  484.                     CELLULAR_PORT_MUTEX_LOCK(gUartData[uart].mutex);
  485.  
  486.                     errorCode = CELLULAR_PORT_OUT_OF_MEMORY;
  487.  
  488.                     // Malloc memory for the read buffer
  489.                     pRxBuffer = pCellularPort_malloc(CELLULAR_PORT_UART_RX_BUFFER_SIZE);
  490.                     if (pRxBuffer != NULL) {
  491.                         // Set up the buffer list
  492.                         for (size_t x = 0; x < sizeof(gUartData[uart].rxBufferList) /
  493.                                                sizeof(gUartData[uart].rxBufferList[0]); x++) {
  494.                             gUartData[uart].rxBufferList[x].pStart = pRxBuffer;
  495.                             gUartData[uart].rxBufferList[x].pRead = pRxBuffer;
  496.                             gUartData[uart].rxBufferList[x].toRead = 0;
  497.                             // Set up the next pointers in a ring
  498.                             if (x < sizeof(gUartData[uart].rxBufferList) /
  499.                                     sizeof(gUartData[uart].rxBufferList[0]) - 1) {
  500.                                 gUartData[uart].rxBufferList[x].pNext = &(gUartData[uart].rxBufferList[x + 1]);
  501.                             } else {
  502.                                 gUartData[uart].rxBufferList[x].pNext = &(gUartData[uart].rxBufferList[0]);
  503.                             }
  504.                             pRxBuffer += CELLULAR_PORT_UART_SUB_BUFFER_SIZE;
  505.                         }
  506.                         gUartData[uart].pRxBufferRead = &(gUartData[uart].rxBufferList[0]);
  507.                         gUartData[uart].pRxBufferWrite = &(gUartData[uart].rxBufferList[0]);
  508.                         gUartData[uart].pRxBufferWriteNext = gUartData[uart].pRxBufferWrite->pNext;
  509.                         gUartData[uart].userNeedsNotify = true;
  510.                         gUartData[uart].state = CELLULAR_PORT_UART_STATE_RECEIVING;
  511.  
  512.                         // Create the queue
  513.                         errorCode = cellularPortQueueCreate(CELLULAR_PORT_UART_EVENT_QUEUE_SIZE,
  514.                                                             sizeof(CellularPortUartEventData_t),
  515.                                                             pUartQueue);
  516.                         if (errorCode == 0) {
  517.                             gUartData[uart].queue = *pUartQueue;
  518.  
  519.                             // Set baud rate
  520.                             nrf_uarte_baudrate_set(pReg, baudRateNrf);
  521.  
  522.                             // Set Tx/Rx pins
  523.                             nrf_gpio_pin_set(pinTx);
  524.                             nrf_gpio_cfg_output(pinTx);
  525.                             // You might expect this to be "no pull" since
  526.                             // the line is pulled up by the module already but
  527.                             // the problem is that when the module is powered
  528.                             // off the pin floats low which the NRF52840 UART
  529.                             // reads as "break" which floods the input buffers
  530.                             // with a constant 0 that its impossible to switch
  531.                             // off.
  532.                             nrf_gpio_cfg_input(pinRx, NRF_GPIO_PIN_PULLUP);
  533.                             nrf_uarte_txrx_pins_set(pReg, pinTx, pinRx);
  534.  
  535.                             // Set flow control
  536.                             if (pinCts >= 0) {
  537.                                 pinCtsNrf = pinCts;
  538.                                 nrf_gpio_cfg_input(pinCtsNrf,
  539.                                                    NRF_GPIO_PIN_NOPULL);
  540.                                 hwfc = NRF_UARTE_HWFC_ENABLED;
  541.                             }
  542.                             if (pinRts >= 0) {
  543.                                 pinRtsNrf = pinRts;
  544.                                 nrf_gpio_pin_set(pinRtsNrf);
  545.                                 nrf_gpio_cfg_output(pinRtsNrf);
  546.                                 hwfc = NRF_UARTE_HWFC_ENABLED;
  547.                             }
  548.  
  549.                             if (hwfc == NRF_UARTE_HWFC_ENABLED) {
  550.                                 nrf_uarte_hwfc_pins_set(pReg, pinRtsNrf, pinCtsNrf);
  551.                             }
  552.  
  553.                             // Configure the UART
  554.                             nrf_uarte_configure(pReg, NRF_UARTE_PARITY_EXCLUDED, hwfc);
  555.  
  556.                            // Enable the UART
  557.                             nrf_uarte_enable(pReg);
  558.  
  559.                             // Clear flags, set Rx interrupt and buffer and let it go
  560.                             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_ENDRX);
  561.                             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_ENDTX);
  562.                             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_ERROR);
  563.                             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_RXTO);
  564.                             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_RXSTARTED);
  565.                             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_TXSTOPPED);
  566.  
  567.                             // Let the end of one RX trigger the next immediately
  568.                             nrf_uarte_shorts_enable(pReg, NRF_UARTE_SHORT_ENDRX_STARTRX);
  569.  
  570.                             nrf_uarte_rx_buffer_set(pReg,
  571.                                                     (uint8_t *) (gUartData[uart].pRxBufferWrite->pStart),
  572.                                                     CELLULAR_PORT_UART_SUB_BUFFER_SIZE);
  573.                             nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STARTRX);
  574.                             nrf_uarte_int_enable(pReg, NRF_UARTE_INT_ENDRX_MASK     |
  575.                                                        NRF_UARTE_INT_ERROR_MASK     |
  576.                                                        NRF_UARTE_INT_RXTO_MASK      |
  577.                                                        NRF_UARTE_INT_RXSTARTED_MASK);
  578.                             NRFX_IRQ_PRIORITY_SET(getIrqNumber((void *) pReg),
  579.                                                   NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY);
  580.                             NRFX_IRQ_ENABLE(getIrqNumber((void *) (pReg)));
  581.  
  582.                             // Put the tick timer into UART mode and
  583.                             // register the receive timout callback
  584.                             cellularPortPrivateTickTimeUartMode();
  585.                             cellularPortPrivateTickTimeSetInterruptCb(rxCb,
  586.                                                                       &(gUartData[uart]));
  587.                         }
  588.                     }
  589.  
  590.                     CELLULAR_PORT_MUTEX_UNLOCK(gUartData[uart].mutex);
  591.  
  592.                     // If we failed to create the queue or get memory for the buffer,
  593.                     // delete the mutex, free memory and put the uart's
  594.                     // mutex back to NULL
  595.                     if ((errorCode != 0) ||
  596.                         (pRxBuffer == NULL)) {
  597.                         cellularPortMutexDelete(gUartData[uart].mutex);
  598.                         gUartData[uart].mutex = NULL;
  599.                         cellularPort_free(pRxBuffer);
  600.                     }
  601.                 }
  602.             }
  603.         }
  604.     }
  605.  
  606.     return (int32_t) errorCode;
  607. }
  608.  
  609. // Shutdown a UART.
  610. int32_t cellularPortUartDeinit(int32_t uart)
  611. {
  612.     CellularPortErrorCode_t errorCode = CELLULAR_PORT_INVALID_PARAMETER;
  613.     uint32_t pinRtsNrf;
  614.     uint32_t pinCtsNrf;
  615.     NRF_UARTE_Type *pReg;
  616.  
  617.     if (uart < sizeof(gUartData) / sizeof(gUartData[0])) {
  618.         errorCode = CELLULAR_PORT_SUCCESS;
  619.         if (gUartData[uart].mutex != NULL) {
  620.             errorCode = CELLULAR_PORT_PLATFORM_ERROR;
  621.             pReg = gUartData[uart].pReg;
  622.  
  623.             // This function should not be called if another task
  624.             // already has the mutex, do a quick check here
  625.             cellularPort_assert(cellularPortMutexGetLocker(gUartData[uart].mutex) == NULL);
  626.  
  627.             // No need to lock the mutex, we need to delete it
  628.             // and we're not allowed to delete a locked mutex.
  629.             // The caller needs to make sure that no read/write
  630.             // is in progress when this function is called.
  631.  
  632.             // Disable Rx interrupts
  633.             nrf_uarte_int_disable(pReg, NRF_UARTE_INT_ENDRX_MASK     |
  634.                                         NRF_UARTE_INT_ERROR_MASK     |
  635.                                         NRF_UARTE_INT_RXTO_MASK      |
  636.                                         NRF_UARTE_INT_RXSTARTED_MASK);
  637.             NRFX_IRQ_DISABLE(nrfx_get_irq_number((void *) (pReg)));
  638.  
  639.             // Deregister the timer callback and
  640.             // return the tick timer to normal mode
  641.             cellularPortPrivateTickTimeSetInterruptCb(NULL, NULL);
  642.             cellularPortPrivateTickTimeNormalMode();
  643.  
  644.             // Make sure all transfers are finished before UARTE is
  645.             // disabled to achieve the lowest power consumption
  646.             nrf_uarte_shorts_disable(pReg, NRF_UARTE_SHORT_ENDRX_STARTRX);
  647.             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_RXTO);
  648.             nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STOPRX);
  649.             nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_TXSTOPPED);
  650.             nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STOPTX);
  651.             while (!nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_TXSTOPPED) ||
  652.                    !nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_RXTO)) {}
  653.  
  654.             // Disable the UARTE
  655.             nrf_uarte_disable(pReg);
  656.  
  657.             // Put the pins back
  658.             nrf_gpio_cfg_default(nrf_uarte_tx_pin_get(pReg));
  659.             nrf_gpio_cfg_default(nrf_uarte_rx_pin_get(pReg));
  660.             nrf_uarte_txrx_pins_disconnect(pReg);
  661.             pinRtsNrf = nrf_uarte_rts_pin_get(pReg);
  662.             pinCtsNrf = nrf_uarte_cts_pin_get(pReg);
  663.             nrf_uarte_hwfc_pins_disconnect(pReg);
  664.             if (pinCtsNrf != NRF_UARTE_PSEL_DISCONNECTED) {
  665.                 nrf_gpio_cfg_default(pinCtsNrf);
  666.             }
  667.             if (pinRtsNrf != NRF_UARTE_PSEL_DISCONNECTED) {
  668.                 nrf_gpio_cfg_default(pinRtsNrf);
  669.             }
  670.  
  671.             // Delete the queue
  672.             cellularPortQueueDelete(gUartData[uart].queue);
  673.             gUartData[uart].queue = NULL;
  674.             // Free the buffer
  675.             cellularPort_free(gUartData[uart].rxBufferList[0].pStart);
  676.             // Delete the mutex
  677.             cellularPortMutexDelete(gUartData[uart].mutex);
  678.             gUartData[uart].mutex = NULL;
  679.             errorCode = CELLULAR_PORT_SUCCESS;
  680.         }
  681.     }
  682.  
  683.     return (int32_t) errorCode;
  684. }
  685.  
  686. // Push a UART event onto the UART event queue.
  687. int32_t cellularPortUartEventSend(const CellularPortQueueHandle_t queueHandle,
  688.                                   int32_t sizeBytes)
  689. {
  690.     int32_t errorCode = CELLULAR_PORT_INVALID_PARAMETER;
  691.     CellularPortUartEventData_t uartEvent;
  692.  
  693.     if (queueHandle != NULL) {
  694.         uartEvent.type = -1;
  695.         uartEvent.size = 0;
  696.         if (sizeBytes >= 0) {
  697.             uartEvent.type = 0;
  698.             uartEvent.size = sizeBytes;
  699.         }
  700.         errorCode = cellularPortQueueSend(queueHandle, (void *) &uartEvent);
  701.     }
  702.  
  703.     return errorCode;
  704. }
  705.  
  706. // Receive a UART event, blocking until one turns up.
  707. int32_t cellularPortUartEventReceive(const CellularPortQueueHandle_t queueHandle)
  708. {
  709.     int32_t sizeOrErrorCode = CELLULAR_PORT_INVALID_PARAMETER;
  710.     CellularPortUartEventData_t uartEvent;
  711.  
  712.     if (queueHandle != NULL) {
  713.         sizeOrErrorCode = CELLULAR_PORT_PLATFORM_ERROR;
  714.         if (cellularPortQueueReceive(queueHandle, &uartEvent) == 0) {
  715.             sizeOrErrorCode = CELLULAR_PORT_UNKNOWN_ERROR;
  716.             if (uartEvent.type >= 0) {
  717.                 sizeOrErrorCode = uartEvent.size;
  718.             }
  719.         }
  720.     }
  721.  
  722.     return sizeOrErrorCode;
  723. }
  724.  
  725. // Get the number of bytes waiting in the receive buffer.
  726. int32_t cellularPortUartGetReceiveSize(int32_t uart)
  727. {
  728.     CellularPortErrorCode_t sizeOrErrorCode = CELLULAR_PORT_INVALID_PARAMETER;
  729.     CellularPortUartBuffer_t *pRxBuffer;
  730.  
  731.     if (uart < sizeof(gUartData) / sizeof(gUartData[0])) {
  732.         sizeOrErrorCode = CELLULAR_PORT_NOT_INITIALISED;
  733.         if (gUartData[uart].mutex != NULL) {
  734.  
  735.             CELLULAR_PORT_MUTEX_LOCK(gUartData[uart].mutex);
  736.  
  737.             // Count up the lot
  738.             pRxBuffer = gUartData[uart].pRxBufferRead;
  739.             sizeOrErrorCode = 0;
  740.             for (size_t x = 0; x < sizeof(gUartData[uart].rxBufferList) /
  741.                                    sizeof(gUartData[uart].rxBufferList[0]); x++) {
  742.                 sizeOrErrorCode += pRxBuffer->toRead;
  743.                 pRxBuffer = pRxBuffer->pNext;
  744.             }
  745.  
  746.             CELLULAR_PORT_MUTEX_UNLOCK(gUartData[uart].mutex);
  747.  
  748.         }
  749.     }
  750.  
  751.     return (int32_t) sizeOrErrorCode;
  752. }
  753.  
  754. // Read from the given UART interface.
  755. int32_t cellularPortUartRead(int32_t uart, char *pBuffer,
  756.                              size_t sizeBytes)
  757. {
  758.     CellularPortErrorCode_t sizeOrErrorCode = CELLULAR_PORT_INVALID_PARAMETER;
  759.     CellularPortUartBuffer_t *pRxBuffer;
  760.     size_t thisRead;
  761.  
  762.     if ((pBuffer != NULL) && (sizeBytes > 0) &&
  763.         (uart < sizeof(gUartData) / sizeof(gUartData[0]))) {
  764.         sizeOrErrorCode = CELLULAR_PORT_NOT_INITIALISED;
  765.         if (gUartData[uart].mutex != NULL) {
  766.  
  767.             CELLULAR_PORT_MUTEX_LOCK(gUartData[uart].mutex);
  768.  
  769.             // Move along the buffers copying out
  770.             // everything we can from each one
  771.             sizeOrErrorCode = 0;
  772.             pRxBuffer = gUartData[uart].pRxBufferRead;
  773.             for (size_t x = 0; (sizeBytes > 0) &&
  774.                                (x < sizeof(gUartData[uart].rxBufferList) /
  775.                                     sizeof(gUartData[uart].rxBufferList[0])); x++) {
  776.                 // Read what we can from the current
  777.                 // receive read buffer
  778.                 thisRead = pRxBuffer->toRead;
  779.                 if (thisRead > sizeBytes) {
  780.                     thisRead = sizeBytes;
  781.                 }
  782.                 pCellularPort_memcpy(pBuffer,
  783.                                      pRxBuffer->pRead,
  784.                                      thisRead);
  785.                 // Move buffer pointer and reduce read count
  786.                 // by what we've read
  787.                 pBuffer += thisRead;
  788.                 pRxBuffer->toRead -= thisRead;
  789.                 if (pRxBuffer->toRead <= 0) {
  790.                     // If we've read everything from this
  791.                     // receive read buffer, move
  792.                     // its read pointer back to the start
  793.                     // and move on
  794.                     pRxBuffer->pRead = pRxBuffer->pStart;
  795.                     pRxBuffer = pRxBuffer->pNext;
  796.                 } else {
  797.                     // Otherwise just move the read pointer
  798.                     // on within the current receive read buffer
  799.                     pRxBuffer->pRead += thisRead;
  800.                 }
  801.                 // Update the totals
  802.                 sizeOrErrorCode += thisRead;
  803.                 sizeBytes -= thisRead;
  804.             }
  805.  
  806.             // Set the receive read buffer to where we've got to
  807.             gUartData[uart].pRxBufferRead = pRxBuffer;
  808.  
  809.             // Set the notify flag if we've read everything
  810.             gUartData[uart].userNeedsNotify = false;
  811.             if (pRxBuffer->toRead == 0) {
  812.                 gUartData[uart].userNeedsNotify = true;
  813.             }
  814.  
  815.             CELLULAR_PORT_MUTEX_UNLOCK(gUartData[uart].mutex);
  816.         }
  817.     }
  818.  
  819.     return (int32_t) sizeOrErrorCode;
  820. }
  821.  
  822. // Write to the given UART interface.
  823. int32_t cellularPortUartWrite(int32_t uart,
  824.                               const char *pBuffer,
  825.                               size_t sizeBytes)
  826. {
  827.     CellularPortErrorCode_t sizeOrErrorCode = CELLULAR_PORT_INVALID_PARAMETER;
  828.     const char *pTxBuffer = NULL;
  829.     char *pTmpBuffer = NULL;
  830.     NRF_UARTE_Type *pReg;
  831.  
  832.     if ((pBuffer != NULL) &&
  833.         (uart < sizeof(gUartData) / sizeof(gUartData[0]))) {
  834.         sizeOrErrorCode = CELLULAR_PORT_NOT_INITIALISED;
  835.         if (gUartData[uart].mutex != NULL) {
  836.  
  837.             CELLULAR_PORT_MUTEX_LOCK(gUartData[uart].mutex);
  838.  
  839.             sizeOrErrorCode = CELLULAR_PORT_OUT_OF_MEMORY;
  840.             pReg = gUartData[uart].pReg;
  841.  
  842.             // If the provided buffer is not good for
  843.             // DMA (e.g. if it's in flash) then copy
  844.             // it to somewhere that is
  845.             if (!isGoodForDma(pBuffer)) {
  846.                 pTmpBuffer = pCellularPort_malloc(sizeBytes);
  847.                 if (pTmpBuffer != NULL) {
  848.                     pCellularPort_memcpy(pTmpBuffer, pBuffer, sizeBytes);
  849.                     pTxBuffer = pTmpBuffer;
  850.                 }
  851.             } else {
  852.                 pTxBuffer = pBuffer;
  853.             }
  854.  
  855.             if (pTxBuffer != NULL) {
  856.                 // Set up the flags
  857.                 nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_ENDTX);
  858.                 nrf_uarte_event_clear(pReg, NRF_UARTE_EVENT_TXSTOPPED);
  859.                 nrf_uarte_tx_buffer_set(pReg, (uint8_t const *) pTxBuffer, sizeBytes);
  860.                 nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STARTTX);
  861.  
  862.                 // Wait for the transmission to complete
  863.                 while (!nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_ENDTX)) {}
  864.  
  865.                 // Put UARTE into lowest power state.
  866.                 nrf_uarte_task_trigger(pReg, NRF_UARTE_TASK_STOPTX);
  867.                 while (!nrf_uarte_event_check(pReg, NRF_UARTE_EVENT_TXSTOPPED)) {}
  868.  
  869.                 sizeOrErrorCode = sizeBytes;
  870.             }
  871.  
  872.             // Free memory (it is valid C to free a NULL buffer)
  873.             cellularPort_free(pTmpBuffer);
  874.  
  875.             CELLULAR_PORT_MUTEX_UNLOCK(gUartData[uart].mutex);
  876.         }
  877.     }
  878.  
  879.     return (int32_t) sizeOrErrorCode;
  880. }
  881.  
  882. // Determine if RTS flow control is enabled.
  883. bool cellularPortIsRtsFlowControlEnabled(int32_t uart)
  884. {
  885.     bool rtsFlowControlIsEnabled = false;
  886.     NRF_UARTE_Type *pReg;
  887.  
  888.     if ((uart < sizeof(gUartData) / sizeof(gUartData[0])) &&
  889.         (gUartData[uart].mutex != NULL)) {
  890.  
  891.         CELLULAR_PORT_MUTEX_LOCK(gUartData[uart].mutex);
  892.  
  893.         pReg = gUartData[uart].pReg;
  894.  
  895.         if (nrf_uarte_rts_pin_get(pReg) != NRF_UARTE_PSEL_DISCONNECTED) {
  896.             rtsFlowControlIsEnabled = true;
  897.         }
  898.  
  899.         CELLULAR_PORT_MUTEX_UNLOCK(gUartData[uart].mutex);
  900.     }
  901.  
  902.     return rtsFlowControlIsEnabled;
  903. }
  904.  
  905. // Determine if CTS flow control is enabled.
  906. bool cellularPortIsCtsFlowControlEnabled(int32_t uart)
  907. {
  908.     bool ctsFlowControlIsEnabled = false;
  909.     NRF_UARTE_Type *pReg;
  910.  
  911.     if ((uart < sizeof(gUartData) / sizeof(gUartData[0])) &&
  912.         (gUartData[uart].mutex != NULL)) {
  913.  
  914.         CELLULAR_PORT_MUTEX_LOCK(gUartData[uart].mutex);
  915.  
  916.         pReg = gUartData[uart].pReg;
  917.  
  918.         if (nrf_uarte_cts_pin_get(pReg) != NRF_UARTE_PSEL_DISCONNECTED) {
  919.             ctsFlowControlIsEnabled = true;
  920.         }
  921.  
  922.         CELLULAR_PORT_MUTEX_UNLOCK(gUartData[uart].mutex);
  923.     }
  924.  
  925.     return ctsFlowControlIsEnabled;
  926. }
  927.  
  928. // End of file
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement