Exemplo n.º 1
0
/******************************************************************************
 * @fn      AesDmaSetup
 *
 * @brief   Sets up DMA of 16 byte block using CC2540 HW aes encryption engine
 *
 * input parameters
 *
 * @param   Cstate  - Pointer to output data.
 * @param   msg_out_len - message out length
 * @param   msg_in  - pointer to input data.
 * @param   msg_in_len - message in length
 *
 * output parameters
 *
 * @param   Cstate  - Pointer to encrypted data.
 *
 * @return  None
 *
 */
void AesDmaSetup( uint8 *Cstate, uint16 msg_out_len, uint8 *msg_in, uint16 msg_in_len )
{
  halDMADesc_t *ch;

  /* Modify descriptors for channel 1 */
  ch = HAL_DMA_GET_DESC1234( HAL_DMA_AES_IN );
  HAL_DMA_SET_SOURCE( ch, msg_in );
  HAL_DMA_SET_LEN( ch, msg_in_len );

  /* Modify descriptors for channel 2 */
  ch = HAL_DMA_GET_DESC1234( HAL_DMA_AES_OUT );
  HAL_DMA_SET_DEST( ch, Cstate );
  HAL_DMA_SET_LEN( ch, msg_out_len );

  /* Arm DMA channels 1 and 2 */
  HAL_DMA_CLEAR_IRQ( HAL_DMA_AES_IN );
  HAL_DMA_ARM_CH( HAL_DMA_AES_IN );
  do {
    asm("NOP");
  } while (!HAL_DMA_CH_ARMED(HAL_DMA_AES_IN));
  HAL_DMA_CLEAR_IRQ( HAL_DMA_AES_OUT );
  HAL_DMA_ARM_CH( HAL_DMA_AES_OUT );
  do {
    asm("NOP");
  } while (!HAL_DMA_CH_ARMED(HAL_DMA_AES_OUT));
}
Exemplo n.º 2
0
/**************************************************************************************************
 * @fn          HalFlashWrite
 *
 * @brief       This function writes 'cnt' bytes to the internal flash.
 *
 * input parameters
 *
 * @param       addr - Valid HAL flash write address: actual addr / 4 and quad-aligned.
 * @param       buf - Valid buffer space at least as big as 'cnt' X 4.
 * @param       cnt - Number of 4-byte blocks to write.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
void HalFlashWrite(uint16 addr, uint8 *buf, uint16 cnt)
{
  halDMADesc_t *ch = HAL_NV_DMA_GET_DESC();

  HAL_DMA_SET_SOURCE(ch, buf);
  HAL_DMA_SET_DEST(ch, &FWDATA);
  HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN);
  HAL_DMA_SET_LEN(ch, (cnt * HAL_FLASH_WORD_SIZE));
  HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE);
  HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE);
  HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_FLASH);
  HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1);
  HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
  // The DMA is to be polled and shall not issue an IRQ upon completion.
  HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE);
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS);
  HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH);
  HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH);
  HAL_DMA_ARM_CH(HAL_NV_DMA_CH);

  FADDRL = (uint8)addr;
  FADDRH = (uint8)(addr >> 8);
  FCTL |= 0x02;         // Trigger the DMA writes.
  while (FCTL & 0x80);  // Wait until writing is done.
}
Exemplo n.º 3
0
/******************************************************************************
 * @fn      AesLoadKey
 *
 * @brief   Writes the key into the CC2540
 *
 * input parameters
 *
 * @param   AesKey  - Pointer to AES Key.
 *
 * @return  None
 */
void AesLoadKey( uint8 *AesKey )
{
#if (defined HAL_AES_DMA) && (HAL_AES_DMA == TRUE)
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234( HAL_DMA_AES_IN );

  /* Modify descriptors for channel 1 */
  HAL_DMA_SET_SOURCE( ch, AesKey );
  HAL_DMA_SET_LEN( ch, KEY_BLENGTH );

  /* Arm DMA channel 1 */
  HAL_DMA_CLEAR_IRQ( HAL_DMA_AES_IN );
  HAL_DMA_ARM_CH( HAL_DMA_AES_IN );
  do {
    asm("NOP");
  } while (!HAL_DMA_CH_ARMED(HAL_DMA_AES_IN));

  /* Set AES mode */
  AES_SET_ENCR_DECR_KEY_IV( AES_LOAD_KEY );

  /* Kick it off, block until AES is ready */
  AES_START();
  while( !(ENCCS & 0x08) );
#else
  /* Set AES mode */
  AES_SET_ENCR_DECR_KEY_IV( AES_LOAD_KEY );

  /* Load the block */
  AesLoadBlock( AesKey );
#endif
}
/******************************************************************************
 * @fn      startIrGenNec
 *
 * @brief   Generate repeat IR signal corresponding to NEC protocol
 *
 * input parameters
 *
 * @param   IrBufSize - Size of the command containing the IR signal
 *
 * output parameters
 *
 * None.
 *
 * @return  None.
 *
 */
static void startIrGenNec(uint8 IrBufSize)
{
  halIntState_t intState;
  
  //check if IR generation timers are already in use
  if (halIrGenTimerRunning)
  {
    // Timer is already running. Cannot generate the signals.
    return;
  }
  
  halIrGenTimerRunning = TRUE;

 
  // Inlcude stop bit ('1')
  halIrGenCc0Buf[IrBufSize] = HAL_IRGEN_NEC_BIT_1_PER;
  
  // Inlcude dummy value as last entry in buffer to make sure stop bit is generated
  halIrGenCc0Buf[IrBufSize+1] = 0xFFFF;
  
  // Set data length.
  HAL_DMA_SET_LEN(pDmaDescCc0, IrBufSize + 2);
  HAL_DMA_SET_LEN(pDmaDescCc1, IrBufSize + 2);
  
  // ARM both DMA channels
  HAL_DMA_CLEAR_IRQ(HAL_IRGEN_DMA_CH_CC0);
  HAL_DMA_ARM_CH(HAL_IRGEN_DMA_CH_CC0);

  HAL_DMA_CLEAR_IRQ(HAL_IRGEN_DMA_CH_CC1);
  HAL_DMA_ARM_CH(HAL_IRGEN_DMA_CH_CC1);
 
  // program initial state (preamble)
  // duty cycle
  if (IrBufSize)  // command signal generation
  {
    T1CC0L = ((6 * HAL_IRGEN_NEC_BIT_1_PER) & 0xff) - 1;
    T1CC0H = (6 * HAL_IRGEN_NEC_BIT_1_PER) >> 8;
  }
  else  // repeat signal generation
  {
Exemplo n.º 5
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();
  }
}
Exemplo n.º 6
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();
  }
}
Exemplo n.º 7
0
/**************************************************************************************************
 * @fn          HalUARTPollSPI
 *
 * @brief       SPI Transport Polling Manager.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
static void HalUARTPollSPI(void)
{
#ifdef HAL_SPI_MASTER
#else
#if defined POWER_SAVING  
  pktFound = FALSE;
#endif
  if ( ( spiRdyIsr ) || (SPI_RDY_IN()) )
  {
    CLEAR_SLEEP_MODE();

#if defined HAL_SBL_BOOT_CODE
    if(!spiTxLen)
    {   
      UxDBUF = 0x00; /* Zero out garbage from UxDBUF */
      
      HAL_DMA_ARM_CH(HAL_SPI_CH_RX); /* Arm RX DMA */

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

      halIntState_t intState;      
      HAL_ENTER_CRITICAL_SECTION(intState);
      
      SPI_SET_RDY_OUT(); /* SPI_RDYOut = 0 */
      SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */

      HAL_EXIT_CRITICAL_SECTION(intState);
    }
#endif
#if defined POWER_SAVING      
    pktFound = TRUE;
#endif
  }
#endif

#ifdef HAL_SPI_MASTER
  if ( spiRdyIsr && !writeActive) 
  {
    spiParseRx();
  }
#else //SPI Slave
  if ( spiRdyIsr && !writeActive )
  {
     if ( !(UxCSR & CSR_ACTIVE) )
     {
       // MRDY has gone low to set spiRdyIsr
       // and has now gone high if SPI_RDY_IN
       // is false, read RXed bytes
       spiParseRx();
     }
     else
     {
       // MRDY has gone low and is still low
       // Set SRDY low to signal ready to RX
       SPI_SET_RDY_OUT();
     }
  }
#endif //HAL_SPI_MASTER

#if defined HAL_SPI_MASTER
  if( SPI_RX_RDY())
#else
  if (SPI_RX_RDY() && !spiTxLen)
#endif
  {
    if (spiCB != NULL)
    {
      spiCB((HAL_UART_SPI - 1), HAL_UART_RX_TIMEOUT);
    }
  }

#if defined POWER_SAVING
  if  ( SPI_RDY_IN()|| SPI_RX_RDY() || spiRxLen || spiTxLen || spiRdyIsr ||  pktFound || SPI_RDY_OUT() )
  {
    CLEAR_SLEEP_MODE();
  }
  else if ( (!pktFound) && (!SPI_NEW_RX_BYTE(spiRxIdx)) )
  {
    PxIEN |= SPI_RDYIn_BIT; 
    SPI_CLR_RDY_OUT();
  }
#endif
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
/**************************************************************************************************
 * @fn          HalUARTInitSPI
 *
 * @brief       Initialize the SPI UART Transport.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
static void HalUARTInitSPI(void)
{
#if (HAL_UART_SPI == 1)
  PERCFG &= ~HAL_UART_PERCFG_BIT;    /* Set UART0 I/O to Alt. 1 location on P0 */
#else
  PERCFG |= HAL_UART_PERCFG_BIT;     /* Set UART1 I/O to Alt. 2 location on P1 */
#endif
#if defined HAL_SPI_MASTER
  PxSEL |= HAL_UART_Px_SEL_M;        /* SPI-Master peripheral select */
  UxCSR = 0;                         /* Mode is SPI-Master Mode */
  UxGCR =  15;                       /* Cfg for the max Rx/Tx baud of 2-MHz */
  UxBAUD = 255;
#elif !defined HAL_SPI_MASTER
  PxSEL |= HAL_UART_Px_SEL_S;        /* SPI-Slave peripheral select */
  UxCSR = CSR_SLAVE;                 /* Mode is SPI-Slave Mode */
#endif
  UxUCR = UCR_FLUSH;                 /* Flush it */
  UxGCR |= BV(5);                    /* Set bit order to MSB */

  P2DIR &= ~P2DIR_PRIPO;
  P2DIR |= HAL_UART_PRIPO;

  /* Setup GPIO for interrupts by falling edge on SPI_RDY_IN */
  PxIEN |= SPI_RDYIn_BIT;
  PICTL |= PICTL_BIT;

  SPI_CLR_RDY_OUT();
  PxDIR |= SPI_RDYOut_BIT;

  /* Setup Tx by DMA */
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234( HAL_SPI_CH_TX );
  
  /* Abort any pending DMA operations (in case of a soft reset) */
  HAL_DMA_ABORT_CH( HAL_SPI_CH_TX );

  /* The start address of the destination */
  HAL_DMA_SET_DEST( ch, DMA_UxDBUF );

  /* Using the length field to determine how many bytes to transfer */
  HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

  /* One byte is transferred each time */
  HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE );

  /* The bytes are transferred 1-by-1 on Tx Complete trigger */
  HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
  HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX );

  /* The source address is incremented by 1 byte after each transfer */
  HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 );
  HAL_DMA_SET_SOURCE( ch, spiTxPkt );

  /* The destination address is constant - the Tx Data Buffer */
  HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 );

  /* The DMA Tx done is serviced by ISR */
  HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE );

  /* Xfer all 8 bits of a byte xfer */
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

  /* DMA has highest priority for memory access */
  HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );

  /* Setup Rx by DMA */
  ch = HAL_DMA_GET_DESC1234( HAL_SPI_CH_RX );
  
  /* Abort any pending DMA operations (in case of a soft reset) */
  HAL_DMA_ABORT_CH( HAL_SPI_CH_RX );

  /* The start address of the source */
  HAL_DMA_SET_SOURCE( ch, DMA_UxDBUF );

  /* Using the length field to determine how many bytes to transfer */
  HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

  /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
   * The byte after the Rx Data Buffer is the Baud Cfg Register,
   * which always has a known value. So init Rx buffer to inverse of that
   * known value. DMA word xfer will flip the bytes, so every valid Rx byte
   * in the Rx buffer will be preceded by a DMA_PAD char equal to the
   * Baud Cfg Register value.
   */
  HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD );

  /* The bytes are transferred 1-by-1 on Rx Complete trigger */
  HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED );
  HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX );

  /* The source address is constant - the Rx Data Buffer */
  HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 );

  /* The destination address is incremented by 1 word after each transfer */
  HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 );
  HAL_DMA_SET_DEST( ch, spiRxBuf );
  HAL_DMA_SET_LEN( ch, SPI_MAX_PKT_LEN );

  /* The DMA is to be polled and shall not issue an IRQ upon completion */
  HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE );

  /* Xfer all 8 bits of a byte xfer */
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

  /* DMA has highest priority for memory access */
  HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );

  volatile uint8 dummy = *(volatile uint8 *)DMA_UxDBUF;  /* Clear the DMA Rx trigger */
  HAL_DMA_CLEAR_IRQ(HAL_SPI_CH_RX);
  HAL_DMA_ARM_CH(HAL_SPI_CH_RX);
  (void)memset(spiRxBuf, (DMA_PAD ^ 0xFF), SPI_MAX_PKT_LEN * sizeof(uint16));
}
Exemplo n.º 10
0
/******************************************************************************
 * @fn      HalUARTInitDMA
 *
 * @brief   Initialize the UART
 *
 * @param   none
 *
 * @return  none
 *****************************************************************************/
static void HalUARTInitDMA(void)
{
  halDMADesc_t *ch;
#if (HAL_UART_DMA == 1)
  PERCFG &= ~HAL_UART_PERCFG_BIT;    // Set UART0 I/O to Alt. 1 location on P0.
#else
  PERCFG |= HAL_UART_PERCFG_BIT;     // Set UART1 I/O to Alt. 2 location on P1.
#endif
  PxSEL  |= HAL_UART_Px_SEL;         // Enable Peripheral control of Rx/Tx on Px.     p0.2 P0.3 set peripheral   //i0 setting
  UxCSR = CSR_MODE;                  // Mode is UART Mode.
  UxUCR = UCR_FLUSH;                 // Flush it.

  P2DIR &= ~P2DIR_PRIPO;                                                                                        //ÓÅÏȼ¶
  P2DIR |= HAL_UART_PRIPO;

  if (DMA_PM)
  {
    // Setup GPIO for interrupts by falling edge on DMA_RDY_IN.
    PxIEN |= DMA_RDYIn_BIT;
    PICTL |= PICTL_BIT;

    HAL_UART_DMA_CLR_RDY_OUT();
    PxDIR |= DMA_RDYOut_BIT;
  }

#if !HAL_UART_TX_BY_ISR
  // Setup Tx by DMA.
  ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX );

  // Abort any pending DMA operations (in case of a soft reset).
  HAL_DMA_ABORT_CH( HAL_DMA_CH_TX );

  // The start address of the destination.
  HAL_DMA_SET_DEST( ch, DMA_UxDBUF );

  // Using the length field to determine how many bytes to transfer.
  HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

  // One byte is transferred each time.
  HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE );

  // The bytes are transferred 1-by-1 on Tx Complete trigger.
  HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
  HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX );

  // The source address is incremented by 1 byte after each transfer.
  HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 );

  // The destination address is constant - the Tx Data Buffer.
  HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 );

  // The DMA Tx done is serviced by ISR in order to maintain full thruput.
  HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE );

  // Xfer all 8 bits of a byte xfer.
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

  // DMA has highest priority for memory access.
  HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH);
#endif

  // Setup Rx by DMA.
  ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX );

  // Abort any pending DMA operations (in case of a soft reset).
  HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );

  // The start address of the source.
  HAL_DMA_SET_SOURCE( ch, DMA_UxDBUF );

  // Using the length field to determine how many bytes to transfer.
  HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

  /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
   * The byte after the Rx Data Buffer is the Baud Cfg Register,
   * which always has a known value. So init Rx buffer to inverse of that
   * known value. DMA word xfer will flip the bytes, so every valid Rx byte
   * in the Rx buffer will be preceded by a DMA_PAD char equal to the
   * Baud Cfg Register value.
   */
  HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD );

  // The bytes are transferred 1-by-1 on Rx Complete trigger.
  HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED );
  HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX );

  // The source address is constant - the Rx Data Buffer.
  HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 );

  // The destination address is incremented by 1 word after each transfer.
  HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 );
  HAL_DMA_SET_DEST( ch, dmaCfg.rxBuf );
  HAL_DMA_SET_LEN( ch, HAL_UART_DMA_RX_MAX );

  // The DMA is to be polled and shall not issue an IRQ upon completion.
  HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE );

  // Xfer all 8 bits of a byte xfer.
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

  // DMA has highest priority for memory access.
  HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH);

  volatile uint8 dummy = *(volatile uint8 *)DMA_UxDBUF;  // Clear the DMA Rx trigger.
  HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX);
  HAL_DMA_ARM_CH(HAL_DMA_CH_RX);
  (void)memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX * sizeof(uint16));
}
Exemplo n.º 11
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
}
Exemplo n.º 12
0
/**************************************************************************************************
 * @fn          HalUARTPollSPI
 *
 * @brief       SPI Transport Polling Manager.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 */
static void HalUARTPollSPI(void)
{
#ifdef HAL_SPI_MASTER
#else
#if defined POWER_SAVING  
  pktFound = FALSE;
#endif
  if ( ( spiRdyIsr ) || (SPI_RDY_IN()) )
  {
    CLEAR_SLEEP_MODE();

#if defined HAL_SBL_BOOT_CODE
    if(!spiTxLen)
    {   
      UxDBUF = 0x00; /* Zero out garbage from UxDBUF */
      
      HAL_DMA_ARM_CH(HAL_SPI_CH_RX); /* Arm RX DMA */

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

      halIntState_t intState;      
      HAL_ENTER_CRITICAL_SECTION(intState);
      
      SPI_SET_RDY_OUT(); /* SPI_RDYOut = 0 */
      SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */

      HAL_EXIT_CRITICAL_SECTION(intState);
    }
#endif
#if defined POWER_SAVING      
    pktFound = TRUE;
#endif
  }
#endif

#if defined HAL_SPI_MASTER  
  if (!spiTxLen) 
#else
  if ((!spiTxLen) && (!SPI_RDY_IN()))
#endif
  {
    SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1; */
    spiParseRx();
  }

#if defined HAL_SPI_MASTER
  if( SPI_RX_RDY())
#else
  if (SPI_RX_RDY() && !spiTxLen)
#endif
  {
    if (spiCB != NULL)
    {
      spiCB((HAL_UART_SPI - 1), HAL_UART_RX_TIMEOUT);
    }
  }

  if (!spiTxLen)
  {
    if ( SPI_RDY_OUT () )
    {
      SPI_CLR_RDY_OUT();  /* Clear the ready-out signal */
    }
  }

#if defined POWER_SAVING
  if  ( SPI_RDY_IN()|| SPI_RX_RDY() || spiRxLen || spiTxLen || spiRdyIsr ||  pktFound || SPI_RDY_OUT() )
  {
    CLEAR_SLEEP_MODE();
  }
  else if ( (!pktFound) && (!SPI_NEW_RX_BYTE(spiRxIdx)) )
  {
    PxIEN |= SPI_RDYIn_BIT; 
    SPI_CLR_RDY_OUT();
  }
#endif
  spiRdyIsr = 0;

}
Exemplo n.º 13
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;
}
Exemplo n.º 14
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);
  }
}
Exemplo n.º 15
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_UART_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;
      dmaCfg.txTick = 35; // (32768Hz / (9600bps / 10 bits))
                          // 10 bits include start and stop bits.
      break;
    case HAL_UART_BR_19200:
      UxGCR = 9;
      dmaCfg.txTick = 18;
      break;
    case HAL_UART_BR_38400:
      UxGCR = 10;
      dmaCfg.txTick = 9;
      break;
    case HAL_UART_BR_57600:
      UxGCR = 10;
      dmaCfg.txTick = 6;
      break;
    default:
      // HAL_UART_BR_115200
      UxGCR = 11;
      dmaCfg.txTick = 3;
      break;
  }

  // 8 bits/char; no parity; 1 stop bit; stop bit hi.
  if (config->flowControl)
  {
    UxUCR = UCR_FLOW | UCR_STOP;
    PxSEL |= HAL_UART_Px_CTS;
    // DMA Rx is always on (self-resetting). So flow must be controlled by the S/W polling the Rx
    // buffer level. Start by allowing flow.
    PxOUT &= ~HAL_UART_Px_RTS;
    PxDIR |=  HAL_UART_Px_RTS;
  }
  else
  {
    UxUCR = UCR_STOP;
  }

  dmaCfg.rxBuf[0] = *(volatile uint8 *)DMA_UDBUF;  // Clear the DMA Rx trigger.
  HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX);
  HAL_DMA_ARM_CH(HAL_DMA_CH_RX);
  osal_memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX*2);

  UxCSR |= CSR_RE;
  
  // Initialize that TX DMA is not pending
  dmaCfg.txDMAPending = FALSE;
  dmaCfg.txShdwValid = FALSE;
}