UART overrrun error while using STM32L476RG - interrupt

I am running my code on an STM32L476RG which generates a UART interrupt every time it receives data. I am using UART2 for this purpose and USART2_IRQHandler is called after I send data from my terminal. But inside HAL_UART_IRQHandler, my code gets stuck on an overrun error interrupt. What is the reason for this? I've been pulling my hair trying to figure out the source of the problem. Here is my code -
UART configuration -
void uart_config(void)
{
/* Configure the UART peripheral ######################################*/
/* Put the USART peripheral in UART Mode */
/* UART configured as follows:
- Word Length = 8 Bits
- Stop Bit = One Stop bit
- Parity = None
- BaudRate = 9600 baud
- Hardware flow control disabled (RTS and CTS signals) */
UartHandle.Instance = USARTx;//USART2
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if(HAL_UART_DeInit(&UartHandle) != HAL_OK)
{
sprintf(errvar,"This is line %d of file %s (function %s)\n", __LINE__, __FILE__, __func__);
Error_Handler(101); // See "error codes.txt"
}
if(HAL_UART_Init(&UartHandle) != HAL_OK)
{
sprintf(errvar,"This is line %d of file %s (function %s)\n", __LINE__, __FILE__, __func__);
Error_Handler(102); // See "error codes.txt"
}
/* Put UART peripheral in reception process */
if(HAL_UART_Receive_IT(&UartHandle, &aRxBuffer, 1) != HAL_OK)
{
sprintf(errvar,"This is line %d of file %s (function %s)\n", __LINE__, __FILE__, __func__);
Error_Handler(103); // See "error codes.txt"
}
#ifdef DEBUG_MODE
sprintf(dispvar,"UART = USART%d \n BAUDRATE = %d \n Word Length = 8 bits \n Stop Bit = 1 \nParity = None \n Flow Control = None \n Mode = TxRx ", 2,UartHandle.Init.BaudRate );
serial_printf();
#endif
}
interrupt handler -
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags;
/* If no error occurs */
errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE));
if (errorflags == RESET)
{
/* UART in mode Receiver ---------------------------------------------------*/
#if defined(USART_CR1_FIFOEN)
if (((isrflags & USART_ISR_RXNE_RXFNE) != RESET)
&& (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET)
|| ((cr3its & USART_CR3_RXFTIE) != RESET)))
#else
if (((isrflags & USART_ISR_RXNE) != RESET)
&& ((cr1its & USART_CR1_RXNEIE) != RESET))
#endif
{
if (huart->RxISR != NULL)
{
huart->RxISR(huart);
}
return;
}
}
/* If some errors occur */
#if defined(USART_CR1_FIFOEN)
if ((errorflags != RESET)
&& ((((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != RESET)
|| ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != RESET))))
#else
if ((errorflags != RESET)
&& (((cr3its & USART_CR3_EIE) != RESET)
|| ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
#endif
{
/* UART parity error interrupt occurred -------------------------------------*/
if (((isrflags & USART_ISR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
{
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF);
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
/* UART frame error interrupt occurred --------------------------------------*/
if (((isrflags & USART_ISR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF);
huart->ErrorCode |= HAL_UART_ERROR_FE;
}
/* UART noise error interrupt occurred --------------------------------------*/
if (((isrflags & USART_ISR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF);
huart->ErrorCode |= HAL_UART_ERROR_NE;
}
/* UART Over-Run interrupt occurred -----------------------------------------*/
#if defined(USART_CR1_FIFOEN)
if (((isrflags & USART_ISR_ORE) != RESET)
&& (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) ||
((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != RESET)))
#else
if (((isrflags & USART_ISR_ORE) != RESET)
&& (((cr1its & USART_CR1_RXNEIE) != RESET) ||
((cr3its & USART_CR3_EIE) != RESET)))
#endif
{
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
/* Call UART Error Call back function if need be --------------------------*/
if (huart->ErrorCode != HAL_UART_ERROR_NONE)
{
/* UART in mode Receiver ---------------------------------------------------*/
#if defined(USART_CR1_FIFOEN)
if (((isrflags & USART_ISR_RXNE_RXFNE) != RESET)
&& (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET)
|| ((cr3its & USART_CR3_RXFTIE) != RESET)))
#else
if (((isrflags & USART_ISR_RXNE) != RESET)
&& ((cr1its & USART_CR1_RXNEIE) != RESET))
#endif
{
if (huart->RxISR != NULL)
{
huart->RxISR(huart);
}
}
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
consider error as blocking */
if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) ||
(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))
{
/* Blocking error : transfer is aborted
Set the UART gState ready to be able to start again the process,
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
UART_EndRxTransfer(huart);
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel */
if (huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback :
will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
/* Abort DMA RX */
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
{
/* Call Directly huart->hdmarx->XferAbortCallback function in case of error */
huart->hdmarx->XferAbortCallback(huart->hdmarx);
}
}
else
{
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Non Blocking error : transfer could go on.
Error is notified to user through user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
huart->ErrorCode = HAL_UART_ERROR_NONE;
}
}
return;
} /* End if some error occurs */
/* UART wakeup from Stop mode interrupt occurred ---------------------------*/
if (((isrflags & USART_ISR_WUF) != RESET) && ((cr3its & USART_CR3_WUFIE) != RESET))
{
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_WUF);
/* UART Rx gState is not reset as a reception process might be ongoing.
If UART handle gState fields need to be reset to READY, this could be done in Wakeup callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Wakeup Callback */
huart->WakeupCallback(huart);
#else
/* Call legacy weak Wakeup Callback */
HAL_UARTEx_WakeupCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return;
}
/* UART in mode Transmitter ------------------------------------------------*/
#if defined(USART_CR1_FIFOEN)
if (((isrflags & USART_ISR_TXE_TXFNF) != RESET)
&& (((cr1its & USART_CR1_TXEIE_TXFNFIE) != RESET)
|| ((cr3its & USART_CR3_TXFTIE) != RESET)))
#else
if (((isrflags & USART_ISR_TXE) != RESET)
&& ((cr1its & USART_CR1_TXEIE) != RESET))
#endif
{
if (huart->TxISR != NULL)
{
huart->TxISR(huart);
}
return;
}
/* UART in mode Transmitter (transmission end) -----------------------------*/
if (((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
UART_EndTransmit_IT(huart);
return;
}
#if defined(USART_CR1_FIFOEN)
/* UART TX Fifo Empty occurred ----------------------------------------------*/
if (((isrflags & USART_ISR_TXFE) != RESET) && ((cr1its & USART_CR1_TXFEIE) != RESET))
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Tx Fifo Empty Callback */
huart->TxFifoEmptyCallback(huart);
#else
/* Call legacy weak Tx Fifo Empty Callback */
HAL_UARTEx_TxFifoEmptyCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return;
}
/* UART RX Fifo Full occurred ----------------------------------------------*/
if (((isrflags & USART_ISR_RXFF) != RESET) && ((cr1its & USART_CR1_RXFFIE) != RESET))
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Rx Fifo Full Callback */
huart->RxFifoFullCallback(huart);
#else
/* Call legacy weak Rx Fifo Full Callback */
HAL_UARTEx_RxFifoFullCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return;
}
#endif
}

I solved it myself. Looks like there was some problem in HAL UART .c and .h files. I just copied them from another example program for the same board and it works fine.

Related

MSP430G2553 keeps SCL and SDA low

I am working with a BMP180 using I2C but it's not working.
My I2C settings are these
void inicializarI2C() {
UCB0CTL1 |= UCSWRST;
UCB0CTL0 &= ~(UCA10 | UCSLA10 | UCMM);
UCB0CTL0 |= (UCMST | UCMODE1 | UCMODE0 | UCSYNC);
UCB0CTL1 |= UCSSEL1 | UCSSEL0;
UCB0CTL1 |= UCTR;
UCB0STAT = 0;
UCB0BR0 = 80;
UCB0BR1 = 0;
UCB0I2COA = 0x1A;
UCB0I2CSA = 0xEE;
P1SEL |= BIT6;
P1SEL2 |= BIT6;
P1SEL |= BIT7;
P1SEL2 |= BIT7;
UCB0CTL1 &= ~UCSWRST;
}
I start an I2C communication with this
void inicioI2C(uint8_t dir) {
//UCB0I2CSA = dir;
UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT;
UCB0TXBUF = 5;
while((UCB0CTL1 & UCTXSTT) != 0) {
if((UCB0STAT & UCNACKIFG) != 0) {
UCB0CTL1 |= UCTXSTP;
while((UCB0CTL1 & UCTXSTP) != 0);
break;
}
}
}
This is my main function
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P1DIR |= 0x01;
P1OUT &= ~BIT0;
conf_reloj(8);
/*for(int i = 0; i < 20; i++) {
P1OUT ^= 0x01;
retardo_ms(1000);
}*/
inicializar_UART();
inicializarI2C();
while(1) {
inicioI2C(0xEE);
retardo_ms(5);
}
return 0;
}
I already checked SCL and SDA signals and they stay low all the time. I think I2C communication is not even starting. NACK flag doesn't activate even tough apparently the sensor it's not responding.

how do i work the I2C peripheral on STM32L412

I'm trying to get a 4 channel DAC working through the I2C peripheral on an STM32L412, I've read through the reference manual but I'm a little confused and my I2C doesn't work. So far, it sends out the first address byte OK, it seems like there's an ACK bit, but then nothing - just a stop condition. I'm trying to output 8 bytes - four 12bit values split over two bytes each.
I've set it up using the STM32cube but I found I had write a few things manually afterward - below is the initialisation. I'm operating in fast mode, 400KHz - ive used 300nS as the rise / fall times and the peripheral is clocked at 16MHz
Can anyone help me? I don't know what im doing wrong
static void MX_I2C2_Init(void)
{
hi2c2.Instance = I2C2;
hi2c2.Init.Timing = 0x00610611;
hi2c2.Init.OwnAddress1 = 192;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
{
Error_Handler();
}
}
i've included this in the main setup before the loop
I2C2->TXDR = DACdata[0]; //pre-load output register
I2C2 ->CR2 &= ~(1<<25); //AUTOLOAD = 0
I2C2 ->CR2 |= 0b1100000<<1; //enter slave address
I2C2 ->CR1 |= 1 << 6 | 1<<1; //enable finish interrupts
I2C2 ->CR2 |= 0b1000 << 16; //bytes to send = 8
I2C2 ->CR2 |= 1<<13; //start DAC
and this is my interrupt, but the program never gets here
void I2C2_EV_IRQHandler(void)
{
if (I2C2->ISR & 1<<1)
{
i2ccounter++;
I2C2->TXDR = DACdata[i2ccounter];
}
if (I2C2->ISR & 1<<6)
{
i2ccounter = 0;
I2C2->TXDR = DACdata[0];
I2C2 ->CR2 |= 1<<13; //start counter
}
HAL_I2C_EV_IRQHandler(&hi2c2);
}
and the main loop
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C2_Init();
MX_ADC1_Init();
MX_TIM1_Init();
MX_TIM2_Init();
I2C2->TXDR = DACdata[0]; //pre-load output register
I2C2 ->CR2 &= ~(1<<25); //autoend off
I2C2 ->CR2 |= 0b1100000<<1; //enter slave address
I2C2 ->CR1 |= 1 << 6 | 1<<1; //enable finish interrupts
I2C2 ->CR2 |= 0b1000 << 16; //bytes to send = 8
I2C2 ->CR2 |= 1<<13; //start DAC
while (1)
{
}
}

Why does UART transmit interrupt fail to work in this case?

I am using stm32f0 MCU.
I have a simple UART echo code in which every byte received will be transmitted out. I tested that it works. Here it is;
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit(&huart1, &Rx_data[0], 1, tx_timeout);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
I do not feel comfortable with the code even though it works. Firstly, tx_timeout is 0 and most code examples are non-zero. I do not know the side effect. Secondly, HAL_UART_Transmit() is a blocking call and it is not advisable to use blocking calls inside an interrupt. So, I decided to use an interrupt for uart transmission HAL_UART_Transmit_IT()instead of a blocking call. Here is the modified code;
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit_IT(&huart1, &Rx_data[0], 1);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
However, it does not work as expected. My PC transmits ASCII 12345678 to stm32. If things work as expected, the PC should be receiving 12345678 back. However, the PC receives 1357 instead. What is wrong with this code that uses HAL_UART_Transmit_IT()?
First:
As has been described in answers to your previous question null timeout just exclude wait for flag state. If you open HAL_UART_Transmit code - you will see that when you send 1 byte without timeout no any blocking state will!
Second:
It's not true method to send/receive one byte from a huge HAL's functions and their callbacks. I guess: next your question will "how i must implement parse there?". And I hope you will not insert you parse function in IRQ callback!
So generally you need buffers. And it is good idea to use cyclic buffer.
mxconstants.h:
/* USER CODE BEGIN Private defines */
/* Buffer's length must be select according to real messages frequency */
#define RXBUF_LEN 128 // must be power of 2
#define TXBUF_LEN 128 // must be power of 2
#define RXBUF_MSK (RXBUF_LEN-1)
#define TXBUF_MSK (TXBUF_LEN-1)
/* USER CODE END Private defines */
main.c:
uint8_t rx_buf[RXBUF_LEN], tx_buf[TXBUF_LEN];
/* xx_i - counter of input bytes (tx - pushed for transmit, rx - received)
xx_o - counter of output bytes (tx - transmitted, rx - parsed)
xx_e - counter of echoed bytes */
volatile uint16_t rx_i = 0, tx_o = 0;
uint16_t rx_o = 0, rx_e = 0, tx_i = 0;
volatile uint8_t tx_busy = 0;
void transmit(uint8_t byte)
{
tx_buf[TXBUF_MSK & tx_i] = byte;
tx_i++;
tx_busy = 1;
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE);
}
void main(void)
{
/* Initialization code */
/* ... */
/* Enable usart 1 receive IRQ */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
for (;;) {
/* Main cycle */
while (rx_i != rx_e) {
/* echo here */
transmit(rx_buf[RXBUF_MSK & rx_e]);
rx_e++;
}
while (rx_i != rx_o) {
/* parse here */
/* ... */
rx_o++;
}
/* Power save
while (tx_busy);
HAL_UART_DeInit(&huart1);
*/
}
}
stm32f0xx_it.c:
extern uint8_t rx_buf[RXBUF_LEN], tx_buf[TXBUF_LEN];
extern volatile uint16_t rx_i, tx_o;
extern uint16_t rx_o, rx_e, tx_i;
extern volatile uint8_t tx_busy;
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if((__HAL_UART_GET_IT(&huart1, UART_IT_RXNE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET))
{
rx_buf[rx_i & RXBUF_MSK] = (uint8_t)(huart1.Instance->RDR & 0x00FF);
rx_i++;
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(&huart1, UART_RXDATA_FLUSH_REQUEST);
}
if((__HAL_UART_GET_IT(&huart1, UART_IT_TXE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_TXE) != RESET))
{
if (tx_i == tx_o) {
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
} else {
huart1.Instance->TDR = (uint8_t)(tx_buf[TXBUF_MSK & tx_o] & (uint8_t)0xFF);
tx_o++;
}
}
if((__HAL_UART_GET_IT(&huart1, UART_IT_TC) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_TC) != RESET))
{
tx_busy = 0;
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);
}
/* And never call default handler */
return;
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
And third!!!
And about this:
Why HAL_UART_Transmit_IT not help/work?
Because it's too slow! And if you try to count HAL_BUSY results:
uint8_t Rx_data[5];
uint32_t tx_timeout = 0;
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static uint32_t hal_busy_counter = 0;
if (huart->Instance == USART1) //current UART
{
if (HAL_UART_Transmit_IT(&huart1, &Rx_data[0], 1) == HAL_BUSY) {
hal_busy_counter++;
}
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
When you pause MCU in debugger after data exchange - you will be suprised: it will be equal to count of missed chars.

I'm looking for sample code to service the USCI (UART) on an MSP430 via DMA not interrupts

I have code that works "ok" for reading the USCI (UART) via interrupts, but the TI SimpliciTI stack is a CPU hog and it drops UART bytes when servicing the radio.
I assume DMA is the way to go, but I couldn't find a full example of DMA using USCI as input.
Here's what I ended up doing. It works!
struct {
#ifndef USE_DMA
volatile uint8_t rx_head ;
#endif
volatile uint8_t rx_tail ;
uint8_t rx_buffer[128];
} uart = { 0,0};
void UART_Init(void)
{
#ifndef USE_DMA
uart.rx_head = 0;
#endif
uart.rx_tail = 0;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
PMAPPWD = 0x02D52; // Get write-access to port mapping regs
P1MAP5 = PM_UCA0RXD; // Map UCA0RXD output to P1.5
P1MAP6 = PM_UCA0TXD; // Map UCA0TXD output to P1.6
PMAPPWD = 0; // Lock port mapping registers
P1DIR |= BIT6; // Set P1.6 as TX output
P1SEL |= BIT5 + BIT6; // Select P1.5 & P1.6 to UART function
UCA0CTL1 = UCSWRST; // **Put state machine in reset**
#ifdef UART_9600
UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x03; // 32kHz/9600=3.41 (see User's Guide)
UCA0BR1 = 0x00; //
UCA0MCTL = UCBRS_3+UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0
#elif defined(UART_9600_SMCLK)
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 0xE2; // 12MHz/12500
UCA0BR1 = 0x04; //
UCA0MCTL = UCBRS_2+UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0
#elif defined(UART_115200)
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 104; // 12MHz/115200
UCA0BR1 = 0; //
UCA0MCTL = UCBRS_1 + UCBRF_0; // Modulation UCBRSx=1, UCBRFx=0
#else
#error Please select one of the supported baudrates.
#endif
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
#ifdef USE_DMA
memset(uart.rx_buffer,0,sizeof(uart.rx_buffer));
DMACTL0 = DMA0TSEL_16; // USCIA0 RX trigger
DMA0SAL = (uint16_t) &UCA0RXBUF; // Source address
DMA0DAL = (uint16_t) uart.rx_buffer; // Destination address
DMA0SZ = sizeof(uart.rx_buffer); // Block size. this counts down to 0, then reloads.
DMA0CTL = DMADSTINCR_3 + DMASBDB + DMADT_4 + DMALEVEL;
DMA0CTL |= DMAEN;
#else
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
#endif
}
int UART_GetChar(void)
{
#ifdef USE_DMA
if (DMA0SZ + uart.rx_tail != sizeof(uart.rx_buffer))
#else
if ( uart.rx_head != uart.rx_tail )
#endif
{
int c;
c = uart.rx_buffer[uart.rx_tail];
uint8_t next = uart.rx_tail + 1;
if (next >= sizeof(uart.rx_buffer)) next = 0;
uart.rx_tail = next;
return c;
}
return -1;
}

Calling methods and receiving signals using low-level APIs

I am trying to call the method ReadLocalBdAddrReq and receive its signal ReadLocalBdAddrCfm on dbus using the dbus low level APIs.
I have written the following code with the help of some forum posts and a dbus tutorial.
The thing is, I am not able to receive the signals back. The code is incomplete at some places as I didn't know what should be done.
So please help me so that I can receive the signals for the methods called.
Here the code I have written. Please correct any mistakes I've made.
#include <stdlib.h>
#include <stdio.h>
#include <dbus/dbus.h>
#define OBJ_PATH "/bt/cm"
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
{
if (!dbus_watch_get_enabled(watch))
return TRUE;
int fd = dbus_watch_get_unix_fd(watch);
unsigned int flags = dbus_watch_get_flags(watch);
int f = 0;;
if (flags & DBUS_WATCH_READABLE) {
f |= DBUS_WATCH_READABLE;
printf("Readable\n");
}
if (flags & DBUS_WATCH_WRITABLE) {
printf("Writeable\n");
f |= DBUS_WATCH_WRITABLE;
}
/* this should not be here */
if (dbus_watch_handle(watch, f) == FALSE)
printf("dbus_watch_handle() failed\n");
return TRUE;
}
static void remove_watch(DBusWatch *watch, void *data)
{
printf("In remove watch with fd = [%d]\n",dbus_watch_get_unix_fd(watch));
}
static void toggel_watch(DBusWatch *watch, void *data)
{
printf("In toggel watch\n");
/*
if (dbus_watch_get_enabled(watch))
add_watch(watch, data);
else
remove_watch(watch, data);
*/
}
/* timeout functions */
static dbus_bool_t add_time(DBusTimeout *timeout, void *data)
{
/* Incomplete */
printf("In add_time\n");
if (!dbus_timeout_get_enabled(timeout))
return TRUE;
//dbus_timeout_handle(timeout);
return 0;
}
static void remove_time(DBusTimeout *timeout, void *data)
{
/* Incomplete */
printf("In remove_time\n");
}
static void toggel_time(DBusTimeout *timeout, void *data)
{
/* Incomplete */
printf("In toggel_time\n");
/*
if (dbus_timeout_get_enabled(timeout))
add_timeout(timeout, data);
else
remove_timeout(timeout, data);
*/
}
/* message filter -- handlers to run on all incoming messages*/
static DBusHandlerResult filter (DBusConnection *connection, DBusMessage *message, void *user_data)
{
printf("In filter\n");
char *deviceaddr;
if (dbus_message_is_signal(message, "com.bluegiga.v2.bt.cm", "ReadLocalBdAddrCfm")) {
printf("Signal received is ReadLocalBdAddrCfm\n");
if ((dbus_message_get_args(message,NULL,DBUS_TYPE_STRING, &deviceaddr,DBUS_TYPE_INVALID) == FALSE))
{
printf("Could not get the arguments from the message received\n");
return -2;
}
printf("Got Signal and device address is [%s]\n", deviceaddr);
}
return 0;
}
/* dispatch function-- simply save an indication that messages should be dispatched later, when the main loop is re-entered*/
static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
{
printf("In dispatch_status\n");
if (new_status == DBUS_DISPATCH_DATA_REMAINS)
{
printf("new dbus dispatch status: DBUS_DISPATCH_DATA_REMAINS [%d]",new_status);
}
}
/* unregister function */
void unregister_func(DBusConnection *connection, void *user_data)
{
}
/* message function - Called when a message is sent to a registered object path. */
static DBusHandlerResult message_func(DBusConnection *connection, DBusMessage *message, void *data)
{
printf("Message [%s] is sent to [%s] from interface [%s] on path [%s] \n",dbus_message_get_member(message),dbus_message_get_destination(message),
dbus_message_get_interface(message),dbus_message_get_path(message)); return 0;
}
DBusObjectPathVTable table = {
.unregister_function = unregister_func,
.message_function = message_func,
};
int main(void) {
DBusMessage* msg;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
DBusPendingCall* pending;
int ret;
//unsigned int level;
char* appHandle = NULL;
//int *context;
int msg_serial;
int open;
char *deviceaddr;
dbus_error_init(&err);
// connect to the system bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
exit(1);
}
if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggel_watch, NULL, NULL))
{
printf("Error in dbus_set_watch_functions\n");
dbus_connection_unref(conn);
return -1;
}
/* These functions are responsible for making the application's main loop aware of timeouts */
if (!dbus_connection_set_timeout_functions(conn, add_time, remove_time, toggel_time, NULL, NULL))
{
printf("Error in dbus_set_timeout_functions\n");
dbus_connection_unref(conn);
return -1;
}
/* Used to register the handler functions run on incoming messages*/
if (!dbus_connection_add_filter(conn, filter, NULL, NULL))
{
printf("Error in adding filter\n");
dbus_connection_unref(conn);
return -1;
}
/* Filter added for incoming messages */
/* Set a function to be invoked when the dispatch status changes */
dbus_connection_set_dispatch_status_function(conn, dispatch_status, NULL ,NULL);
/* Register a handler for messages sent to a given path */
if(!dbus_connection_register_object_path(conn, OBJ_PATH, &table, NULL))
{
printf("Error in registering object\n");
return -1;
}
/* sending messages to the outgoing queue */
msg = dbus_message_new_method_call("com.bluegiga.v2.bt.cm", // target for the method call
OBJ_PATH, // object to call on
"com.bluegiga.v2.bt.cm", // interface to call on
"ReadLocalBdAddrReq"); // method name
if (NULL == msg) {
fprintf(stderr, "Message Null\n");
exit(1);
}
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT16,&appHandle)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
fprintf(stderr, "Sending the connections\n");
// send message and get a handle for a reply
if (!dbus_connection_send (conn, msg, &msg_serial)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
fprintf(stderr, "Connection sent and the msg serial is %d\n",msg_serial);
/* Message sent over */
/* not sure whether this should be here or above watch */
while (dbus_connection_get_dispatch_status(conn) == DBUS_DISPATCH_DATA_REMAINS)
{
//printf("Entered in dispatch\n");
/* Processes any incoming data. will call the filters registered by add_filer*/
dbus_connection_dispatch(conn);
}
return 0;
}
After I run this program it has the following output:
Readable
Sending the connections
Connection sent and the msg serial is
2(DBUS_MESSAGE_TYPE_METHOD_RETURN)
If the connection was sent to the object path then message_func should have been called correctly, but it never is called. Have I made any mistake in sending the method call?
You are missing the event loop which is otherwise available by default if you choose to go with one of the bindings. When you get a call to add_watch, libdbus expects that the application will attach an IO handler to it. The IOHandler added by application will watch for an activity on the fd (filedescriptor) queried for the watch. Whenever there is an activity on that file descriptor, the IOHandler will trigger a callback with appropriate flags that you need to convert to DBUS flags before calling dbus_watch_handle.
Suggest that you use glib if you don't know how to use event loops. I am able to get it if I use libUV or libEV as low footprint event loop.