Ejemplo n.º 1
0
/******************************************************************************
 * @fn      HalUARTPollTxTrigDMA
 *
 * @brief   Ascertain whether a manual trigger is required for the DMA Tx channel.
 *
 * @param   None
 *
 * @return  None
 *****************************************************************************/
static void HalUARTPollTxTrigDMA(void)
{
  if ((UxCSR & CSR_TX_BYTE) == 0)  // If no TXBUF to shift register transfer, then TXBUF may be MT.
  {
    if ((dmaCfg.txTick == 0) || ((uint8)(ST0 - dmaCfg.txTick) > HAL_UART_TX_TICK_MIN))
    {
      dmaCfg.txTick = 0;

      if (dmaCfg.txTrig && HAL_DMA_CH_ARMED(HAL_DMA_CH_TX))
      {
        HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX);
      }
      dmaCfg.txTrig = 0;
    }
  }
  else
  {
    UxCSR = (CSR_MODE | CSR_RE);  // Clear the CSR_TX_BYTE flag.
    dmaCfg.txTick = ST0;

    if (dmaCfg.txTick == 0)  // Reserve zero to signify that the minimum delay has been met.
    {
      dmaCfg.txTick = 0xFF;
    }
  }
}
Ejemplo n.º 2
0
/**************************************************************************************************
 * @fn          HalUARTWriteSPI
 *
 * @brief       Transmit data bytes as a SPI packet.
 *
 * input parameters
 *
 * @param       buf - pointer to the memory of the data bytes to send.
 * @param       len - the length of the data bytes to send.
 *
 * output parameters
 *
 * None.
 *
 * @return      Zero for any error; otherwise, 'len'.
 */
static spiLen_t HalUARTWriteSPI(uint8 *buf, spiLen_t len)
{  
  // Already in Tx or Rx transaction
#ifdef RBA_UART_TO_SPI
  // The RBA Bridge is not written to handle re-writes so we must 
  // just let it write
  if (spiTxLen != 0)
#else //!RBA_UART_TO_SPI
  if (spiTxLen != 0 || SPI_RDY_OUT())
#endif
  {
    return 0;
  }
  
  if (len > SPI_MAX_DAT_LEN)
  {
    len = SPI_MAX_DAT_LEN;
  }
        
  spiTxLen = len;
  writeActive = 1;

#if defined HAL_SPI_MASTER
  
  spiTxPkt[SPI_LEN_IDX] = len;
  (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len);
  
  spiCalcFcs(spiTxPkt);
  spiTxPkt[SPI_SOF_IDX] = SPI_SOF;
  
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX);
  HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt)); /* DMA TX might need padding */
 
  /* Abort any pending DMA operations */
  HAL_DMA_ABORT_CH( HAL_SPI_CH_RX );
  spiRxIdx = 0;
  (void)memset(spiRxBuf, (DMA_PAD ^ 0xFF), SPI_MAX_PKT_LEN * sizeof(uint16));

  HAL_DMA_ARM_CH(HAL_SPI_CH_RX);
  
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  /* Abort any pending DMA operations */
  HAL_DMA_ABORT_CH( HAL_SPI_CH_TX );
  HAL_DMA_ARM_CH(HAL_SPI_CH_TX);

  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  SPI_SET_CSn_OUT();

  while((!SPI_RDY_IN()) && (!spiRdyIsr) );

  HAL_DMA_MAN_TRIGGER(HAL_SPI_CH_TX);

#elif !defined HAL_SPI_MASTER

#ifdef POWER_SAVING
  /* Disable POWER SAVING when transmission is initiated */
  CLEAR_SLEEP_MODE();
#endif

  HAL_DMA_ARM_CH(HAL_SPI_CH_RX);

  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  
  spiTxPkt[SPI_LEN_IDX] = len;
  (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len);

  spiCalcFcs(spiTxPkt);
  spiTxPkt[SPI_SOF_IDX] = SPI_SOF;

  halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX);
  HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt) + 1); /* slave DMA TX might drop the last byte */
  HAL_DMA_ARM_CH(HAL_SPI_CH_TX);
  
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  SPI_SET_RDY_OUT();

#endif
  return len;
}
Ejemplo n.º 3
0
/**************************************************************************************************
 * @fn          HalUARTWriteSPI
 *
 * @brief       Transmit data bytes as a SPI packet.
 *
 * input parameters
 *
 * @param       buf - pointer to the memory of the data bytes to send.
 * @param       len - the length of the data bytes to send.
 *
 * output parameters
 *
 * None.
 *
 * @return      Zero for any error; otherwise, 'len'.
 */
static spiLen_t HalUARTWriteSPI(uint8 *buf, spiLen_t len)
{  
  if (spiTxLen != 0)
  {
    return 0;
  }
  
  if (len > SPI_MAX_DAT_LEN)
  {
    len = SPI_MAX_DAT_LEN;
  }

  spiTxLen = len;

#if defined HAL_SPI_MASTER

  spiRdyIsr = 0;
  spiTxPkt[SPI_LEN_IDX] = len;
  (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len);
  
  spiCalcFcs(spiTxPkt);
  spiTxPkt[SPI_SOF_IDX] = SPI_SOF;
  
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX);
  HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt)); /* DMA TX might need padding */
 
  /* Abort any pending DMA operations */
  HAL_DMA_ABORT_CH( HAL_SPI_CH_RX );
  spiRxIdx = 0;
  (void)memset(spiRxBuf, (DMA_PAD ^ 0xFF), SPI_MAX_PKT_LEN * sizeof(uint16));

  HAL_DMA_ARM_CH(HAL_SPI_CH_RX);
  
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  /* Abort any pending DMA operations */
  HAL_DMA_ABORT_CH( HAL_SPI_CH_TX );
  HAL_DMA_ARM_CH(HAL_SPI_CH_TX);

  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  SPI_SET_CSn_OUT();

  while((!SPI_RDY_IN()) && (!spiRdyIsr) );

  HAL_DMA_MAN_TRIGGER(HAL_SPI_CH_TX);

#elif !defined HAL_SPI_MASTER

#ifdef POWER_SAVING
  /* Disable POWER SAVING when transmission is initiated */
  CLEAR_SLEEP_MODE();
#endif

  SPI_CLR_RDY_OUT();

  HAL_DMA_ARM_CH(HAL_SPI_CH_RX);

  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  if ( SPI_RDY_IN() )
  {
    SPI_SET_RDY_OUT();
  }
  
  spiTxPkt[SPI_LEN_IDX] = len;
  (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len);

  spiCalcFcs(spiTxPkt);
  spiTxPkt[SPI_SOF_IDX] = SPI_SOF;

  halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX);
  HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt) + 1); /* slave DMA TX might drop the last byte */
  HAL_DMA_ARM_CH(HAL_SPI_CH_TX);
  
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
  asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

  SPI_SET_RDY_OUT();

#endif
  return len;
}
Ejemplo n.º 4
0
/**************************************************************************************************
 * @fn          DMAExecCrc
 *
 * @brief       This function assumes CRC has been initialized and sets up and
 *              starts a dma tranfer from a flash page to the CRC HW module.
 *
 * @note        This function assumes DMA channel 0 is available for use.
 *
 * input parameters
 *
 * @param       page - A valid flash page number.
 * @param       offset - A valid offset into the page.
 * @param       len - A valid number of bytes to calculate crc of.
 *
 * @return      None.
 **************************************************************************************************
 */
void DMAExecCrc(uint8 page, uint16 offset, uint16 len) {

  uint8 memctr = MEMCTR;  // Save to restore.
  
  // Calculate the offset into the containing flash bank as it gets mapped into XDATA.
  uint16 address = (offset + HAL_FLASH_PAGE_MAP) +
                   ((page % HAL_FLASH_PAGE_PER_BANK) * HAL_FLASH_PAGE_SIZE);

  // Pointer to DMA config structure
  halDMADesc_t *dmaCh0_p = &dmaCh0;
  
#if !defined HAL_OAD_BOOT_CODE
  halIntState_t is;
#endif

  page /= HAL_FLASH_PAGE_PER_BANK;  // Calculate the flash bank from the flash page.

#if !defined HAL_OAD_BOOT_CODE
  HAL_ENTER_CRITICAL_SECTION(is);
#endif
  
  // Calculate and map the containing flash bank into XDATA.
  MEMCTR = (MEMCTR & 0xF8) | page;  // page is actually bank
  
  // Start address for CRC calculation in the XDATA mapped flash bank
  HAL_DMA_SET_SOURCE(dmaCh0_p, address);
  
  // Destination for data transfer, RNDH mapped to XDATA
  HAL_DMA_SET_DEST(dmaCh0_p, 0x70BD);
  
  // One whole page (or len) at a time
  HAL_DMA_SET_LEN(dmaCh0_p, len);
  
  // 8-bit, block, no trigger
  HAL_DMA_SET_WORD_SIZE(dmaCh0_p, HAL_DMA_WORDSIZE_BYTE);
  HAL_DMA_SET_TRIG_MODE(dmaCh0_p, HAL_DMA_TMODE_BLOCK);
  HAL_DMA_SET_TRIG_SRC(dmaCh0_p, HAL_DMA_TRIG_NONE);
  
  // SRC += 1, DST = constant, no IRQ, all 8 bits, high priority
  HAL_DMA_SET_SRC_INC(dmaCh0_p, HAL_DMA_SRCINC_1);
  HAL_DMA_SET_DST_INC(dmaCh0_p, HAL_DMA_DSTINC_0);
  HAL_DMA_SET_IRQ(dmaCh0_p, HAL_DMA_IRQMASK_DISABLE);
  HAL_DMA_SET_M8(dmaCh0_p, HAL_DMA_M8_USE_8_BITS);
  HAL_DMA_SET_PRIORITY(dmaCh0_p, HAL_DMA_PRI_HIGH);
  
  // Tell DMA Controller where above configuration can be found
  HAL_DMA_SET_ADDR_DESC0(&dmaCh0);
  
  // Arm the DMA channel (0)
  HAL_DMA_ARM_CH(0);
  
  // 9 cycles wait
  asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
  asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
  
  // Start DMA tranfer
  HAL_DMA_MAN_TRIGGER(0);
  
  // Wait for dma to finish.
  while(DMAREQ & 0x1);
  
  // Restore bank mapping
  MEMCTR = memctr;

#if !defined HAL_OAD_BOOT_CODE
  HAL_EXIT_CRITICAL_SECTION(is);
#endif
}
Ejemplo n.º 5
0
/******************************************************************************
 * @fn      HalUARTPollDMA
 *
 * @brief   Poll a USART module implemented by DMA.
 *
 * @param   none
 *
 * @return  none
 *****************************************************************************/
static void HalUARTPollDMA(void)
{
  uint16 cnt = 0;
  uint8 evt = 0;

  if (HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
  {
    rxIdx_t tail = findTail();

    // If the DMA has transferred in more Rx bytes, reset the Rx idle timer.
    if (dmaCfg.rxTail != tail)
    {
      dmaCfg.rxTail = tail;

      // Re-sync the shadow on any 1st byte(s) received.
      if (dmaCfg.rxTick == 0)
      {
        dmaCfg.rxShdw = ST0;
      }
      dmaCfg.rxTick = HAL_UART_DMA_IDLE;
    }
    else if (dmaCfg.rxTick)
    {
      // Use the LSB of the sleep timer (ST0 must be read first anyway).
      uint8 decr = ST0 - dmaCfg.rxShdw;

      if (dmaCfg.rxTick > decr)
      {
        dmaCfg.rxTick -= decr;
        dmaCfg.rxShdw = ST0;
      }
      else
      {
        dmaCfg.rxTick = 0;
      }
    }
    cnt = HalUARTRxAvailDMA();
  }
  else
  {
    dmaCfg.rxTick = 0;
  }

  if (cnt >= HAL_UART_DMA_FULL)
  {
    evt = HAL_UART_RX_FULL;
  }
  else if (cnt >= HAL_UART_DMA_HIGH)
  {
    evt = HAL_UART_RX_ABOUT_FULL;
    PxOUT |= HAL_UART_Px_RTS;  // Disable Rx flow.
  }
  else if (cnt && !dmaCfg.rxTick)
  {
    evt = HAL_UART_RX_TIMEOUT;
  }

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

  if (dmaCfg.txShdwValid)
  {
    uint8 decr = ST0;
    decr -= dmaCfg.txShdw;
    if (decr > dmaCfg.txTick)
    {
      // No protection for txShdwValid is required
      // because while the shadow was valid, DMA ISR cannot be triggered
      // to cause concurrent access to this variable.
      dmaCfg.txShdwValid = FALSE;
    }
  }
  
  if (dmaCfg.txDMAPending && !dmaCfg.txShdwValid)
  {
    // UART TX DMA is expected to be fired and enough time has lapsed since last DMA ISR
    // to know that DBUF can be overwritten
    halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX);
    halIntState_t intState;

    // Clear the DMA pending flag
    dmaCfg.txDMAPending = FALSE;
    
    HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]);
    HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]);
    dmaCfg.txSel ^= 1;
    HAL_ENTER_CRITICAL_SECTION(intState);
    HAL_DMA_ARM_CH(HAL_DMA_CH_TX);
    do
    {
      asm("NOP");
    } while (!HAL_DMA_CH_ARMED(HAL_DMA_CH_TX));
    HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX);
    HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX);
    HAL_EXIT_CRITICAL_SECTION(intState);
  }
  else
  {
    halIntState_t his;

    HAL_ENTER_CRITICAL_SECTION(his);
    if ((dmaCfg.txIdx[dmaCfg.txSel] != 0) && !HAL_DMA_CH_ARMED(HAL_DMA_CH_TX)
                                          && !HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX))
    {
      HAL_EXIT_CRITICAL_SECTION(his);
      HalUARTIsrDMA();
    }
    else
    {
      HAL_EXIT_CRITICAL_SECTION(his);
    }
  }

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