Example #1
0
/*****************************************************************************
 * @fn      HalUARTReadDMA
 *
 * @brief   Read a buffer from the UART
 *
 * @param   buf  - valid data buffer at least 'len' bytes in size
 *          len  - max length number of bytes to copy to 'buf'
 *
 * @return  length of buffer that was read
 *****************************************************************************/
static uint16 HalUARTReadDMA(uint8 *buf, uint16 len)
{
  uint16 cnt;

  for (cnt = 0; cnt < len; cnt++)
  {
    if (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
    {
      break;
    }
    *buf++ = HAL_UART_DMA_GET_RX_BYTE(dmaCfg.rxHead);
    HAL_UART_DMA_CLR_RX_BYTE(dmaCfg.rxHead);
    HAL_UART_RX_IDX_T_INCR(dmaCfg.rxHead);
  }

  /* Update pointers after reading the bytes */
  dmaCfg.rxTail = dmaCfg.rxHead;

  if (!DMA_PM && (UxUCR & UCR_FLOW))
  {
    HAL_UART_DMA_SET_RDY_OUT();  // Re-enable the flow asap (i.e. not wait until next uart poll).    
  }

  return cnt;
}
Example #2
0
/*****************************************************************************
 * @fn      HalUARTReadDMA
 *
 * @brief   Read a buffer from the UART
 *
 * @param   buf  - valid data buffer at least 'len' bytes in size
 *          len  - max length number of bytes to copy to 'buf'
 *
 * @return  length of buffer that was read
 *****************************************************************************/
static uint16 HalUARTReadDMA(uint8 *buf, uint16 len)
{
  uint16 cnt;

  for (cnt = 0; cnt < len; cnt++)
  {
    if (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
    {
      break;
    }
    *buf++ = HAL_UART_DMA_GET_RX_BYTE(dmaCfg.rxHead);
    HAL_UART_DMA_CLR_RX_BYTE(dmaCfg.rxHead);
    HAL_UART_RX_IDX_T_INCR(dmaCfg.rxHead);
  }

  if (!DMA_PM && (UxUCR & UCR_FLOW))
  {
    if (HalUARTRxAvailDMA() < HAL_UART_DMA_HIGH)
    {
      HAL_UART_DMA_SET_RDY_OUT();  // Re-enable the flow asap (i.e. not wait until next uart poll).
    }
  }

  return cnt;
}
Example #3
0
/******************************************************************************
 * @fn      HalUARTArmTxDMA
 *
 * @brief   Arm the Tx DMA channel.
 *
 * @param   None
 *
 * @return  None
 *****************************************************************************/
static void HalUARTArmTxDMA(void)
{
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX);
  HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]);
  HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]);

  dmaCfg.txSel ^= 1;
  dmaCfg.txTrig = 1;
  HAL_DMA_ARM_CH(HAL_DMA_CH_TX);

  HalUARTPollTxTrigDMA();

  if (DMA_PM)
  {
    HAL_UART_DMA_SET_RDY_OUT();
  }
}
Example #4
0
/******************************************************************************
 * @fn      HalUARTArmTxDMA
 *
 * @brief   Arm the Tx DMA channel.
 *
 * @param   None
 *
 * @return  None
 *****************************************************************************/
static void HalUARTArmTxDMA(void)
{
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX);
  HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]);
  HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]);

  dmaCfg.txSel ^= 1;
  dmaCfg.txTrig = 1;
  HAL_DMA_ARM_CH(HAL_DMA_CH_TX);
 
  /* Time to arm each DMA channel is 9 cycles as per the user's guide */
  asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
  asm("nop"); asm("nop"); asm("nop"); asm("nop"); 

  HalUARTPollTxTrigDMA();

  if (DMA_PM)
  {
    HAL_UART_DMA_SET_RDY_OUT();
  }
}
Example #5
0
static uint16 HalUARTRxAvailDMA(void)
{
  uint16 cnt = 0;
#ifndef POWER_SAVING  
  bool detectOverflow = FALSE;
#endif
  // First, synchronize the Rx tail marker with where the DMA Rx engine is working.
  rxIdx_t tail = dmaCfg.rxTail;

#ifndef POWER_SAVING
  if (!DMA_PM && (UxUCR & UCR_FLOW))
  {
    HAL_UART_DMA_CLR_RDY_OUT();  // Stop the inflow for counting the bytes
  }
#endif

  do
  {
    if (!HAL_UART_DMA_NEW_RX_BYTE(tail))
    {
      break;
    }
    else
    {
      cnt++;
    }

    HAL_UART_RX_IDX_T_INCR(tail);
  } while (cnt  < HAL_UART_DMA_RX_MAX);

  if(!cnt)
  {
    while(sweepIdx < HAL_UART_DMA_RX_MAX)
    {
      if (HAL_UART_DMA_NEW_RX_BYTE(sweepIdx))
      {
        dmaCfg.rxTail = sweepIdx;
        dmaCfg.rxHead = sweepIdx;
        cnt = 0;
#ifndef POWER_SAVING
        detectOverflow = TRUE;
#endif
        break;
      }

      sweepIdx++;
    }

    if ( sweepIdx == HAL_UART_DMA_RX_MAX )
    {
      sweepIdx = 0;
    }
  }

#ifndef POWER_SAVING
  if ( (!DMA_PM && (UxUCR & UCR_FLOW)) && (!detectOverflow ) )
  {
    HAL_UART_DMA_SET_RDY_OUT();  // Re-enable the flow asap
  }
#endif
  return cnt;
}
Example #6
0
/******************************************************************************
 * @fn      HalUARTPollDMA
 *
 * @brief   Poll a USART module implemented by DMA, including the hybrid solution in which the Rx
 *          is driven by DMA but the Tx is driven by ISR.
 *
 * @param   none
 *
 * @return  none
 *****************************************************************************/
static void HalUARTPollDMA(void)
{
  uint8 evt = 0;
  uint16 cnt;

#if DMA_PM
  PxIEN &= ~DMA_RDYIn_BIT;  // Clear to not race with DMA_RDY_IN ISR.
  {
    if (dmaRdyIsr || HAL_UART_DMA_RDY_IN() || HalUARTBusyDMA())
    {
      // Master may have timed-out the SRDY asserted state & may need a new edge.
#if HAL_UART_TX_BY_ISR
      if (!HAL_UART_DMA_RDY_IN() && (dmaCfg.txHead != dmaCfg.txTail))
#else
      if (!HAL_UART_DMA_RDY_IN() && ((dmaCfg.txIdx[0] != 0) || (dmaCfg.txIdx[1] != 0)))
#endif
      {
        HAL_UART_DMA_CLR_RDY_OUT();
      }
      dmaRdyIsr = 0;

      if (dmaRdyDly == 0)
      {
        (void)osal_set_event(Hal_TaskID, HAL_PWRMGR_HOLD_EVENT);
      }

      if ((dmaRdyDly = ST0) == 0)  // Reserve zero to signify that the delay expired.
      {
        dmaRdyDly = 0xFF;
      }
      HAL_UART_DMA_SET_RDY_OUT();
    }
    else if ((dmaRdyDly != 0) && (!DMA_PM_DLY || ((uint8)(ST0 - dmaRdyDly) > DMA_PM_DLY)))
    {
      dmaRdyDly = 0;
      (void)osal_set_event(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT);
    }
  }
  PxIEN |= DMA_RDYIn_BIT;
#endif

#if !HAL_UART_TX_BY_ISR
  HalUARTPollTxTrigDMA();
#endif


  cnt = HalUARTRxAvailDMA();  // Wait to call until after the above DMA Rx bug work-around.

#if HAL_UART_DMA_IDLE
  if (dmaCfg.rxTick)
  {
    // Use the LSB of the sleep timer (ST0 must be read first anyway) to measure the Rx timeout.
    if ((ST0 - dmaCfg.rxTick) > HAL_UART_DMA_IDLE)
    {
      dmaCfg.rxTick = 0;
      evt = HAL_UART_RX_TIMEOUT;
    }
  }
  else if (cnt != 0)
  {
    if ((dmaCfg.rxTick = ST0) == 0)  // Zero signifies that the Rx timeout is not running.
    {
      dmaCfg.rxTick = 0xFF;
    }
  }
#else
  if (cnt != 0)
  {
    evt = HAL_UART_RX_TIMEOUT;
  }
#endif

  if (cnt >= HAL_UART_DMA_FULL)
  {
    evt |= HAL_UART_RX_FULL;
  }
  else if (cnt >= HAL_UART_DMA_HIGH)
  {
    evt |= HAL_UART_RX_ABOUT_FULL;

    if (!DMA_PM && (UxUCR & UCR_FLOW))
    {
      HAL_UART_DMA_CLR_RDY_OUT();  // Disable Rx flow.
    }
  }

  if (dmaCfg.txMT)
  {
    dmaCfg.txMT = FALSE;
    evt |= HAL_UART_TX_EMPTY;
  }

  if ((evt != 0) && (dmaCfg.uartCB != NULL))
  {
    dmaCfg.uartCB(HAL_UART_DMA-1, evt);
  }

  if (DMA_PM && (dmaRdyDly == 0) && !HalUARTBusyDMA())
  {
    HAL_UART_DMA_CLR_RDY_OUT();
  }
}
Example #7
0
/******************************************************************************
 * @fn      HalUARTOpenDMA
 *
 * @brief   Open a port according tp the configuration specified by parameter.
 *
 * @param   config - contains configuration information
 *
 * @return  none
 *****************************************************************************/
static void HalUARTOpenDMA(halUARTCfg_t *config)
{
  dmaCfg.uartCB = config->callBackFunc;

  // Only supporting subset of baudrate for code size - other is possible.
  HAL_ASSERT((config->baudRate == HAL_UART_BR_9600) ||
                  (config->baudRate == HAL_UART_BR_19200) ||
                  (config->baudRate == HAL_UART_BR_38400) ||
                  (config->baudRate == HAL_UART_BR_57600) ||
                  (config->baudRate == HAL_UART_BR_115200));

  if (config->baudRate == HAL_UART_BR_57600 ||
      config->baudRate == HAL_UART_BR_115200)
  {
    UxBAUD = 216;
  }
  else
  {
    UxBAUD = 59;
  }

  switch (config->baudRate)
  {
    case HAL_UART_BR_9600:
      UxGCR = 8;
      break;
    case HAL_UART_BR_19200:
      UxGCR = 9;
      break;
    case HAL_UART_BR_38400:
    case HAL_UART_BR_57600:
      UxGCR = 10;
      break;
    default:
      // HAL_UART_BR_115200
      UxGCR = 11;
      break;
  }

  if (DMA_PM || config->flowControl)
  {
    UxUCR = UCR_FLOW | UCR_STOP;      // 8 bits/char; no parity; 1 stop bit; stop bit hi.
    PxSEL |= HAL_UART_Px_CTS;         // Enable Peripheral control of CTS flow control on Px.
  }
  else
  {
    UxUCR = UCR_STOP;                 // 8 bits/char; no parity; 1 stop bit; stop bit hi.
  }

  UxCSR = (CSR_MODE | CSR_RE);

  if (DMA_PM)
  {
    PxIFG = 0;
    PxIF = 0;
    IENx |= IEN_BIT;
  }
  else if (UxUCR & UCR_FLOW)
  {
    // DMA Rx is always on (self-resetting). So flow must be controlled by the S/W polling the
    // circular Rx queue depth. Start by allowing flow.
    HAL_UART_DMA_SET_RDY_OUT();
    PxDIR |= HAL_UART_Px_RTS;
  }

#if HAL_UART_TX_BY_ISR
  UTXxIF = 1;  // Prime the ISR pump.
#endif
}