Hello,
We have an application in one of our products where we use UART with DMA to communicate with a Radio chip from Telit. Since this is a low powered application it is required to put the chip to sleep mode ,disable UART and switch the Rx,Tx pins to input mode. On hourly wakeup we enable the UART again , transmit some data and put the chip to sleep again.
At initialization we first initialize the UART and then initialize the DMA. When putting the chip in sleep or wakeup we do not enable/disable the DMA peripheral again. Is it OK if we don’t do that? If yes then how does the DMA module stay in sync with UART?
Below are code snippet for the peripheral initialization in the firmware on power up and other scenarios.
Microcontroller : MSP430FR5969
UART A1 used with DMA channels 0 and 1.
-
Function below called on power up for UART and DMA initialization
void Init_ZigBee_Interface(void)
{
PM5CTL0 &= ~LOCKLPM5;
EUSCI_A_UART_initParam param = {0};
param.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK;
param.clockPrescalar = 8;
param.firstModReg = 0; //not valid when overSampling is
param.secondModReg = 0xD6;
param.parity = EUSCI_A_UART_NO_PARITY;
param.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
param.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT;
param.uartMode = EUSCI_A_UART_MODE;
param.overSampling = EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
EUSCI_A_UART_init(EUSCI_A1_BASE, ¶m);
EUSCI_A_UART_enable(EUSCI_A1_BASE);
//DMA Rx
Param param1 = {0};
param1.channelSelect = DMA_CHANNEL_0;
param1.transferModeSelect = DMA_TRANSFER_REPEATED_SINGLE;
param1.transferSize = M_SERIAL_BUFFER_LEN;
param1.triggerSourceSelect = DMA_TRIGGERSOURCE_16;
param1.transferUnitSelect = DMA_SIZE_SRCBYTE_DSTBYTE;
param1.triggerTypeSelect = DMA_TRIGGER_RISINGEDGE;
DMA_init(¶m1);
//DMA_disableTransferDuringReadModifyWrite();
DMA_enableRoundRobinPriority();
DMA_setSrcAddress(DMA_CHANNEL_0,
(uint32_t)&(UCA1RXBUF),
DMA_DIRECTION_UNCHANGED);
DMA_setDstAddress(DMA_CHANNEL_0,
(uint32_t)&(zigBee_DMA_RxBuf.buffer[0]),
DMA_DIRECTION_INCREMENT);
DMA_enableTransfers(DMA_CHANNEL_0);
DMA_enableInterrupt(DMA_CHANNEL_0);
//DMA Tx
param1.channelSelect = DMA_CHANNEL_1;
param1.transferModeSelect = DMA_TRANSFER_BURSTBLOCK;
param1.transferSize = 1;
param1.triggerSourceSelect = DMA_TRIGGERSOURCE_17;
param1.transferUnitSelect = DMA_SIZE_SRCBYTE_DSTBYTE;
param1.triggerTypeSelect = DMA_TRIGGER_HIGH;
DMA_init(¶m1);
DMA_enableRoundRobinPriority();
DMA_setSrcAddress(DMA_CHANNEL_1,
(uint32_t)&(mZhData.SerialBuffer.TxBuf[1]), //transmission buffer
DMA_DIRECTION_INCREMENT);
DMA_setDstAddress(DMA_CHANNEL_1,
(uint32_t)&UCA1TXBUF, //receive buffer
DMA_DIRECTION_UNCHANGED);
DMA_enableInterrupt(DMA_CHANNEL_1);
}
2. Code snippet below called in an infinite loop to put the Telit module to sleep or wakeup the Telit module from sleep
/**check to put the zigbee module to sleep mode*/
if(mZhData.StateMachine.bSleeping)
{
EUSCI_A_UART_disable(EUSCI_A1_BASE);
if(!ZB_PwrCycFlg)
{
GPIO_setOutputHighOnPin(GPIO_PORT_P4,GPIO_PIN0); /**CTS High*/
}
/**putting TXD, RXD of ZE61 in tristate*/
GPIO_setAsInputPin(GPIO_PORT_P2,GPIO_PIN6);
GPIO_setAsInputPin(GPIO_PORT_P2,GPIO_PIN5);
LPM_Flag |= LPM_WIRELESS;
}
/**check to wake up the zigbee module*/
else
{
/**Setting UART Function RXD for Port 2, Pin 1*/
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_SECONDARY_MODULE_FUNCTION); /**TXD of ZE61*/
/**Setting UART Function TXD for Port 2, Pin 0*/
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN5, GPIO_SECONDARY_MODULE_FUNCTION); /**RXD of ZE61*/
GPIO_setOutputLowOnPin(GPIO_PORT_P4,GPIO_PIN0); //CTS Low
EUSCI_A_UART_enable(EUSCI_A1_BASE);
}
3. Code snippet below called in escalation mode to change the baud rate runtime
/*!
* @fn void coSetZigBeeUart9600(void)
* @brief this function is called to switch the ZigBee UART at 9600 baudrate
* @return None
*/
void coSetZigBeeUart9600()
{
#ifdef ZIGBEEHANDLER_FPI_H_DEBUG
printf("\r\nbaud9600\r\n");
#endif
EUSCI_A_UART_initParam param = {0};
param.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK;
//1Mhz 9600
param.clockPrescalar = 6;
param.firstModReg = 8;
param.secondModReg = 0x20;
//1Mhz 38400
// param.clockPrescalar = 1;
// param.firstModReg = 10;
// param.secondModReg = 0x00;
// param.clockPrescalar = 26;
// param.firstModReg = 0;
// param.secondModReg = 0xB6;
param.parity = EUSCI_A_UART_NO_PARITY;
param.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
param.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT;
param.uartMode = EUSCI_A_UART_MODE;
param.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
EUSCI_A_UART_init(EUSCI_A1_BASE, ¶m);
// if(!flg_FW_UpgradeUart)
EUSCI_A_UART_enable(EUSCI_A1_BASE);
DMA_clearInterrupt(DMA_CHANNEL_0);
DMA_enableInterrupt(DMA_CHANNEL_0);
// EUSCI_A_UART_clearInterrupt(EUSCI_A1_BASE,
// EUSCI_A_UART_RECEIVE_INTERRUPT);
//
// /* Enable USCI_A0 RX interrupt*/
// EUSCI_A_UART_enableInterrupt(EUSCI_A1_BASE,
// EUSCI_A_UART_RECEIVE_INTERRUPT); // Enable interrupt
}
/*!
* @fn void coSetZigBeeUart115200(void)
* @brief this function is called to switch the ZigBee UART at 115200 baudrate
* @return None
*/
void coSetZigBeeUart115200()
{
#ifdef ZIGBEEHANDLER_FPI_H_DEBUG
printf("\r\nbaud115200\r\n");
#endif
EUSCI_A_UART_initParam param1 = {0};
param1.selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK;
param1.clockPrescalar = 8;
param1.firstModReg = 0;
param1.secondModReg = 0xD6;
// param.clockPrescalar = 2;
// param.firstModReg = 2; //not valid when overSampling is
// param.secondModReg = 0xBB;
param1.parity = EUSCI_A_UART_NO_PARITY;
param1.msborLsbFirst = EUSCI_A_UART_LSB_FIRST;
param1.numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT;
param1.uartMode = EUSCI_A_UART_MODE;
param1.overSampling = EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
// param.overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
EUSCI_A_UART_init(EUSCI_A1_BASE, ¶m1);
// if(!flg_FW_UpgradeUart)
EUSCI_A_UART_enable(EUSCI_A1_BASE);
DMA_clearInterrupt(DMA_CHANNEL_0);
DMA_enableInterrupt(DMA_CHANNEL_0);
// EUSCI_A_UART_clearInterrupt(EUSCI_A1_BASE,
// EUSCI_A_UART_RECEIVE_INTERRUPT);
//
// /* Enable USCI_A0 RX interrupt*/
// EUSCI_A_UART_enableInterrupt(EUSCI_A1_BASE,
// EUSCI_A_UART_RECEIVE_INTERRUPT); // Enable interrupt
}
Regards,
Raman