Reply
Highlighted
Posts: 3
Registered: ‎09-01-2015

EFM32GG330 USART must read RXDATAX instead of RXDATA

Problem:

For the USART to work properly I have to read from the RXDATAX register. When reading from the RXDATA register (in the interrupt) I am trapped in an endless loop or if I am not in an interrupt routine the data inside RXDATA is just wrong (i.e. consecutive 0x02D8D8363660 instead of 0xD88039506093 over SPI).

 

I have read the receiving data also by using an oscilloscope. The data and timings are ok. The reading from the registers are bad.

 

Reading from the RXDATAX works but it is different to the behavior of the EFM32LG so I must be doing something wrong.

 

This happens on ALL of the USARTs.

 

What I am using:

  • EFM32GG330F1024
  • All of the USARTs:
    USART0 as async UART
    USART1 as async UART
    USART2 as sync SPI
  • 48 MHz external oscillator (if you mind the timings)

The code:

USART0:

 

#include <USART0_drv.h>
#include "stddef.h"
#include "em_cmu.h"
#include "em_usart.h"
#include "em_gpio.h"

pfunc_par USART0_RX_Function;
pfunc USART0_TX_Function;

static bool USART0_DRV_Initialized = false;

//==========================================================================
// This is where the endless loop happens. mentioned in the description above void USART0_RX_IRQHandler ( void ) { if ( USART0_RX_Function ) { // THIS NEXT STATEMENT IS THE PLACE WHERE THINGS GO WRONG USART0_RX_Function ( USART0_RX_DATA ); } USART_IntClear ( USART0, USART_IEN_RXDATAV ); } //========================================================================== void USART0_TX_IRQHandler ( void ) { if ( USART0_TX_Function ) { USART0_TX_Function ( ); } USART_IntClear ( USART0, USART_IEN_TXC ); } //========================================================================== void USART0_DRV_RxIrq_Enable ( void ) { // Clear previous RX interrupts USART_IntClear ( USART0, USART_IF_RXDATAV ); NVIC_ClearPendingIRQ ( USART0_RX_IRQn ); // Enable RX interrupts USART_IntEnable ( USART0, USART_IF_RXDATAV ); NVIC_EnableIRQ ( USART0_RX_IRQn ); } //========================================================================== void USART0_DRV_RxIrq_Disable ( void ) { // Disable RX interrupts USART_IntDisable ( USART0, USART_IF_RXDATAV ); NVIC_DisableIRQ ( USART0_RX_IRQn ); } //========================================================================== void USART0_DRV_TxIrq_Enable ( void ) { // Clear previous RX interrupts USART_IntClear ( USART0, USART_IEN_TXC ); NVIC_ClearPendingIRQ ( USART0_TX_IRQn ); // Enable RX interrupts USART_IntEnable ( USART0, USART_IEN_TXC ); NVIC_EnableIRQ ( USART0_TX_IRQn ); } //========================================================================== void USART0_DRV_TxIrq_Disable ( void ) { // Disable RX interrupts USART_IntDisable ( USART0, USART_IEN_TXC ); NVIC_DisableIRQ ( USART0_TX_IRQn ); } //========================================================================== void USART0_DRV_Disable ( void ) { USART_Enable ( USART0, usartDisable ); USART0_DRV_Initialized = false; } //========================================================================== void USART0_DRV_Init ( uint32_t baud ) { if ( USART0_DRV_Initialized == false ) { // Enable clock for USART0 CMU_ClockEnable ( cmuClock_USART0, true ); GPIO_PinModeSet ( USART0_TX_Port, USART0_TX_Pin, gpioModePushPull, 1 ); GPIO_PinModeSet ( USART0_RX_Port, USART0_RX_Pin, gpioModeInput, 0 ); USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT; init.enable = usartDisable; init.baudrate = baud; init.oversampling = usartOVS8; init.databits = usartDatabits8; init.parity = usartNoParity; init.stopbits = usartStopbits1; init.mvdis = 0; init.prsRxEnable = 0; USART_InitAsync ( USART0, &init ); // Enable signals TX, RX USART0->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC0; USART_IntClear ( USART0, _USART_IFC_MASK ); // USART_IntEnable ( USART0, USART_IEN_RXDATAV ); // USART_IntEnable ( USART0, USART_IEN_TXC ); NVIC_ClearPendingIRQ ( USART0_RX_IRQn ); // NVIC_EnableIRQ ( USART0_RX_IRQn ); NVIC_ClearPendingIRQ ( USART0_TX_IRQn ); // NVIC_EnableIRQ ( USART0_TX_IRQn ); USART_Enable ( USART0, usartEnable ); USART0_DRV_Initialized = true; } } //========================================================================== void USART0_DRV_ChangeBaudrate ( uint32_t baud ) { USART_BaudrateAsyncSet ( USART0, 0, baud, usartOVS8 ); } //==========================================================================

header file:

 

 

#ifndef _USART1_H_
#define _USART1_H_

#include "div.h"
#include "em_gpio.h"

#define USART0_TX_Port		gpioPortE
#define USART0_TX_Pin			10
#define USART0_RX_Port		gpioPortE
#define USART0_RX_Pin			11
#define USART0_TX_DATA		USART0->TXDATA
//#define USART0_RX_DATA	USART0->RXDATA //does not work
#define USART0_RX_DATA USART0->RXDATAX extern pfunc_par USART0_RX_Function; extern pfunc USART0_TX_Function; void USART0_DRV_RxIrq_Enable ( void ); void USART0_DRV_RxIrq_Disable ( void ); void USART0_DRV_TxIrq_Enable ( void ); void USART0_DRV_TxIrq_Disable ( void ); void USART0_DRV_Disable ( void ); void USART0_DRV_Init ( uint32_t ); void USART0_DRV_ChangeBaudrate ( uint32_t ); #endif

 

USART1:

just the same as USART0 but with USART1 instead of USART0.

 

USART2:

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_dbg.h"
#include "em_usart.h"
#include "spi_usart2.h"

bool SPIDRV_Initialized = false;
uint32_t currentBaud = 0;

//============================================================================
void SPI_USART2_Init ( void )
{
	if ( SPIDRV_Initialized )
	{
		return;
	}

	CMU_ClockEnable ( cmuClock_USART2, true );

	GPIO_PinModeSet ( gpioPortC, 2, gpioModePushPull, 0 ); //	TX - MOSI
	GPIO_PinModeSet ( gpioPortC, 3, gpioModeInput, 0 ); 	// RX - MISO
	GPIO_PinModeSet ( gpioPortC, 4, gpioModePushPull, 0 ); // CLK

	USART_Reset ( USART2 );

	USART_InitSync_TypeDef inits_spi = USART_INITSYNC_DEFAULT;

	inits_spi.enable = usartEnable;
	inits_spi.refFreq = 0;
	inits_spi.baudrate = 9000000;
	inits_spi.databits = usartDatabits8;
	inits_spi.master = true;
	inits_spi.msbf = true;
	inits_spi.clockMode = usartClockMode0;
	inits_spi.prsRxEnable = false;
	inits_spi.autoTx = false;

	/* Initialize USART, in SPI master mode. */
	USART_InitSync ( USART2, &inits_spi );

	USART2->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN | USART_ROUTE_LOCATION_LOC0;

	USART_Enable ( USART2, usartEnable );

	SPIDRV_Initialized = true;
	currentBaud = inits_spi.baudrate;
}

//============================================================================
void SPI_USART2_Disable ( )
{
	USART_Enable ( USART2, usartDisable );

	GPIO_PinModeSet ( gpioPortC, 2, gpioModeDisabled, 0 ); 	// TX - MOSI
	GPIO_PinModeSet ( gpioPortC, 3, gpioModeDisabled, 0 ); 	// RX - MISO
	GPIO_PinModeSet ( gpioPortC, 4, gpioModeDisabled, 0 ); 	// CLK
	CMU_ClockEnable ( cmuClock_USART2, false );
	USART2->ROUTE = 0;
	SPIDRV_Initialized = false;
}

//============================================================================
uint8_t SPI_USART2_RW_Byte ( uint8_t data )
{
	if ( !SPIDRV_Initialized )
	SPI_USART2_Init ( );

	USART_Tx ( USART2, data );
	//data = USART_Rx ( USART2 ); //does not work
	data = USART_RxExt ( USART2 ); //does work
	return data;
}
//==========================================================================
void SPI_USART2_ChangeBaudrate ( uint32_t baud )
{
	if ( currentBaud == baud )
	{
		return;
	}

	USART_BaudrateAsyncSet ( USART2, 0, baud, usartOVS8 );
	currentBaud = baud;
}
//==========================================================================

 

If you could point out where I have to look for the error that would be great.