Страницы

Страницы

воскресенье, 13 ноября 2016 г.

EFM32 UART DMA Tx

#include "em_device.h"
#include "em_chip.h"
#include "em_usart.h"
#include "em_gpio.h"
#include "em_dma.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_timer.h"
#include "em_int.h"
#include "em_prs.h"
#include "InitDevice.h"

#define DMA_CHANNEL_UART_TX    0  //
/* DMA init structure */
DMA_Init_TypeDef dmaInit;
/* DMA callback structure */
DMA_CB_TypeDef cb[DMA_CHAN_COUNT];//DMA_CHAN_COUN????
/** DMA control block, requires proper alignment. */
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2] __attribute__ ((aligned(256)));

uint8_t  ucComplete = 0;
uint8_t  Tx_buffer[8] = {0x30,0x31,0x32,0x33,0x34,0x35,0x0D,0x0A};

void UARTTxTransferComplete(unsigned int channel, bool primary, void *user)
{
    ucComplete = 1;
 GPIO_PinOutToggle(gpioPortE, 12);
}

void DMA_for_UART_Tx(void)
{
    DMA_CfgChannel_TypeDef  chnlCfg;
    DMA_CfgDescr_TypeDef    descrCfg;
 
    /* Setting up call-back function */
    cb[DMA_CHANNEL_UART_TX].cbFunc = UARTTxTransferComplete; //Set DMA is completed, whether to call the callback function. If there is no callback function, it is set to NULL
    cb[DMA_CHANNEL_UART_TX].userPtr = NULL;
 
    /* Setting up channel */
    chnlCfg.highPri = false;
    chnlCfg.enableInt = true;
    //Set the DMA to send the next byte of the conditions, here is: When the Tx is completed, DMA then start to take down a byte to send
    chnlCfg.select = DMAREQ_USART1_TXEMPTY;
 
    //Initializes the function of the callback part of the DMA register
    chnlCfg.cb = &(cb[DMA_CHANNEL_UART_TX]);
    DMA_CfgChannel(DMA_CHANNEL_UART_TX, &chnlCfg);
 
    //Register that defines the logical portion of the DMA
    /* Setting up channel descriptor */
    descrCfg.dstInc = dmaDataIncNone;   //Meaning of the target address unchanged
    descrCfg.srcInc = dmaDataInc1;      //This means that the source address is incremented by one byte at a time
    descrCfg.size = dmaDataSize1;       //The byte unit of each transmission
    descrCfg.arbRate = dmaArbitrate1;   //DMA arbitration, one arbitration for every 1 byte sent
    descrCfg.hprot = 0;
    DMA_CfgDescr(DMA_CHANNEL_UART_TX, true, &descrCfg);
}
void DMAInit(void)
{
    CMU_ClockEnable(cmuClock_DMA, true);
  /* Initializing the DMA */
  dmaInit.hprot = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);
}

int main(void)
{
/* Initialize chip */
CHIP_Init();
enter_DefaultMode_from_RESET();
GPIO_PinModeSet(gpioPortE, 12,  gpioModePushPullDrive, 0); /* TX */
DMAInit();
DMA_for_UART_Tx();
ucComplete = 1;
GPIO_PinOutSet(DE_PORT, DE_PIN);
/* Infinite blink loop */
while(1)
  {
  if(ucComplete)
    {
GPIO_PinOutSet(DE_PORT, DE_PIN);          
    DMA_ActivateBasic(DMA_CHANNEL_UART_TX,
      true,
      false,
      (void *)&(USART1->TXDATA),
      (void *)&Tx_buffer,
      sizeof(Tx_buffer) - 1);
    ucComplete = 0;
    }
  }
}

среда, 9 ноября 2016 г.

EFM32 Peripheral Reflex System (PRS)

   PRS позволяет периферийным устройствам общаться друг с другом, без участия процессора, даже когда он находится в состоянии сна. В качестве сигнала используется передача уровня или импульса (level or pulse).

  Producers, consumers and channels (Источники, приемники и каналы)
 
  Перефирийные устройства, которые создают сигналы называют источниками (produsers), а принимающие их приемниками (consumers). PRS для EFM32 в зависимости от серии содержит до 12 каналов для передачи сигналов, каждый из которых может быть подключен к любому источнику и к любому приемнику. Некоторые приемники способны принимать уровень сигнала, но большинство реагирует только на фронт имрульсного сигнала. Канал можно сконфигурировать с помощью emlib функции

 void PRS_SourceSignalSet(unsigned int ch, uint32_t source, uint32_t signal, PRS_Edge_TypeDef  edge)

/***************************************************************************//**
 * @brief
 *   Set source and signal to be used for a channel.
 *
 * @param[in] ch
 *   Channel to define signal and source for.
 *
 * @param[in] source
 *   Source to select for channel. Use one of PRS_CH_CTRL_SOURCESEL_x defines.
 *
 * @param[in] signal
 *   Signal (for selected @p source) to use. Use one of PRS_CH_CTRL_SIGSEL_x
 *   defines.
 *
 * @param[in] edge
 *   Edge (for selected source/signal) to generate pulse for.
 ******************************************************************************/
void PRS_SourceSignalSet(unsigned int ch,
                         uint32_t source,
                         uint32_t signal,
                         PRS_Edge_TypeDef edge)

Эта функция задает PRS каналы по которым будут передавться сигналы между периферийными устройствами. Сигналы можно генерировать и программно с помощью регистров PRS_SWPULSE и PRS_SWLEVEL.


EFM32 Timer frequency meter

// $[TIMER0...3  initialization]
TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT;

init.enable = 1;
init.debugRun = 0;
init.dmaClrAct = 0;
init.sync = 0;
init.clkSel = timerClkSelHFPerClk;
init.prescale = timerPrescale1;
init.fallAction = timerInputActionNone;
init.riseAction = timerInputActionNone;
init.mode = timerModeUp;
init.quadModeX4 = 0;
init.oneShot = 0;
init.count2x = 0;
init.ati = 0;
TIMER_Init(TIMER3, &init);
// [TIMER0...3  initialization]$


// $[TIMER CC0 ... CC2 init]
TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT;

initCC0.prsInput = false;
initCC0.prsSel = timerPRSSELCh0;
initCC0.edge = timerEdgeRising;
initCC0.mode = timerCCModeOff;
initCC0.eventCtrl = timerEventEveryEdge;
initCC0.filter = 0;
initCC0.cofoa = timerOutputActionNone;
initCC0.cufoa = timerOutputActionNone;
initCC0.cmoa = timerOutputActionNone;
initCC0.coist = 0;
initCC0.outInvert = 0;
TIMER_InitCC(TIMER3, 0, &initCC0);
// [TIMER CC0 ... CC2 init]$

вторник, 8 ноября 2016 г.

EFM32 Timer pulse generate with & without IRQ

// with IRQ (GPIO output)

/**************************************************************************//**
 * @brief TIMER0_IRQHandler
 * Interrupt Service Routine TIMER0 Interrupt Line
 *****************************************************************************/
void TIMER0_IRQHandler(void)
{
  /* Clear flag for TIMER0 overflow interrupt */
  TIMER_IntClear(TIMER0, TIMER_IF_OF);

  /* Toggle LED ON/OFF */
  GPIO_PinOutToggle(gpioPortC, 0);
}
/**************************************************************************//**
 * @brief  Main function
 * Main is called from __iar_program_start, see assembly startup file
 *****************************************************************************/
int main(void)
{
  /* Initialize chip */
  CHIP_Init();
 
  /* Enable clock for GPIO module */
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Enable clock for TIMER0 module */
  CMU_ClockEnable(cmuClock_TIMER0, true);

  /* Configure pin as push pull output for LED/pin drive */
  GPIO_PinModeSet(LED_PORT, LED_PIN, gpioModePushPullDrive, 0);

  /* Select TIMER0 parameters */
  TIMER_Init_TypeDef timerInit =
  {
    .enable     = true,
    .debugRun   = true,
    .prescale   = timerPrescale1024,
    .clkSel     = timerClkSelHFPerClk,
    .fallAction = timerInputActionNone,
    .riseAction = timerInputActionNone,
    .mode       = timerModeUp,
    .dmaClrAct  = false,
    .quadModeX4 = false,
    .oneShot    = false,
    .sync       = false,
  };

  /* Enable overflow interrupt */
  TIMER_IntEnable(TIMER0, TIMER_IF_OF);

  /* Enable TIMER0 interrupt vector in NVIC */
  NVIC_EnableIRQ(TIMER0_IRQn);

  /* Set TIMER Top value */
  TIMER_TopSet(TIMER0, TOP);

  /* Configure TIMER */
  TIMER_Init(TIMER0, &timerInit);

  while(1)
  {
    /* Go to EM1 */
    EMU_EnterEM1();
  }

}


//without IRQ (TIMER output)

/**************************************************************************//**
 * @brief  Main function
 * Main is called from __iar_program_start, see assembly startup file
 *****************************************************************************/
int main(void)
{
  /* Initialize chip */
  CHIP_Init();
   
  /* Enable clock for GPIO module */
  CMU_ClockEnable(cmuClock_GPIO, true);
 
  /* Enable clock for TIMER0 module */
  CMU_ClockEnable(cmuClock_TIMER0, true);
 
  /* Set CC0 location 3 pin (PD1) as output */
  GPIO_PinModeSet(gpioPortD, 1, gpioModePushPull, 0);

  /* Select CC channel parameters */
  TIMER_InitCC_TypeDef timerCCInit =
  {
    .cufoa      = timerOutputActionNone,
    .cofoa      = timerOutputActionToggle,
    .cmoa       = timerOutputActionNone,
    .mode       = timerCCModeCompare,
    .filter     = true,
    .prsInput   = false,
    .coist      = false,
    .outInvert  = false,
  };
 
  /* Configure CC channel 0 */
  TIMER_InitCC(TIMER0, 0, &timerCCInit);

  /* Route CC0 to location 3 (PD1) and enable pin */
  TIMER0->ROUTE |= (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_LOCATION_LOC3);
 
  /* Set Top Value */
  TIMER_TopSet(TIMER0, TOP);
 
  /* Select timer parameters */
  TIMER_Init_TypeDef timerInit =
  {
    .enable     = true,
    .debugRun   = true,
    .prescale   = timerPrescale64,
    .clkSel     = timerClkSelHFPerClk,
    .fallAction = timerInputActionNone,
    .riseAction = timerInputActionNone,
    .mode       = timerModeUp,
    .dmaClrAct  = false,
    .quadModeX4 = false,
    .oneShot    = false,
    .sync       = false,
  };
 
  /* Configure timer */
  TIMER_Init(TIMER0, &timerInit);
 
  while(1)
  {
    /* Go to EM1, while TIMER tuns compare output */
    EMU_EnterEM1();
  }
 
}