Help with XDMAC setup for USART with hardware handshaking

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working with the SAMS70 (equivalent to SAME70) and have no real experience with using a DMA controller. I have a bluetooth module that communicates via TX, RX, RTS, CTS (115,200 baudrate). 

 

The bluetooth module will at any given time send messages with a 4 byte header first that describes the type of message and length of following payload (anywhere from 0-256 bytes). I was trying to do it without the DMA controller but I would get constant overrun errors. Can somebody help me setup a simple FIFO with (or without) the DMA controller to receive these messages? I found the USART hardware handshaking demo in the softpack v1.5 and I can see that I've received 4 bytes (confirmed with oscilloscope) but when I try to read it I only get 4 bytes of 0x00.

 

I'm also a little lost on the concept of DMA blocks, microblocks, etc. The data sheet doesn't to a great job in describing what the size of these are. I also have no idea what the mutex is, I'm just trying to follow how the example in the softpack is working and the datasheet doesn't have any reference of it (any clarification here would be greatly appreciated).

 

static bool BLE_Header_Ready = false;
static bool BLE_Payload_Ready = false;

static UsartDma Usartd;
static UsartChannel UsartTx, UsartRx;
#define APP_BUFFER         256
/**  Ring buffer */
COMPILER_ALIGNED(32) uint8_t pRxBuffer[APP_BUFFER];

/**  Application Rx buffer.*/
COMPILER_ALIGNED(32) uint8_t FirstAppBuff[APP_BUFFER];

static void _DmaRxCallback( uint8_t status, void* pArg )
{
	/*dummy*/
	status = status;
	pArg = pArg;
	
	mutexTimeout = 0x7FF;
	while (LockMutex(semaphore, mutexTimeout)); // lock semaphore
	USART0->US_CR = US_CR_RTSEN;
	
	ReleaseMutex(semaphore);
	
	if(!BLE_Header_Ready)
	{
		BLE_Header_Ready = true;
	}
	else
	{
		BLE_Payload_Ready = true;
	}
}

__STATIC_INLINE void _ConfigureUsart(uint32_t baudrate, uint32_t rxTimeout)
{
	uint32_t mode = 0
	| US_MR_USART_MODE_HW_HANDSHAKING
	| US_MR_USCLKS_MCK
	| US_MR_CHRL_8_BIT
	| US_MR_PAR_NO
	| US_MR_NBSTOP_1_BIT
	| US_MR_CHMODE_NORMAL;

	/* Reset the Tx and Rx Channel */
	memset(&UsartTx, 0, sizeof(UsartChannel));
	memset(&UsartRx, 0, sizeof(UsartChannel));

	/* Initialize the Rx DMA channel of USART*/
	UsartRx.BuffSize= BLE_HEADER_SIZE;
	UsartRx.pBuff = pRxBuffer;
	UsartRx.callback = _DmaRxCallback;
	UsartRx.dmaProgrammingMode = XDMAD_SINGLE;
	UsartRx.dmaBlockSize = 10;
	UsartRx.dmaRingBuffer = 1;
	UsartRx.dmaProgress = 1;

	/* Initialize the Tx DMA channel of USART*/
	UsartTx.BuffSize= APP_BUFFER;
	UsartTx.pBuff = FirstAppBuff;
	UsartTx.callback = _DmaTxCallback;
	UsartTx.dmaProgrammingMode = XDMAD_SINGLE;
	UsartTx.dmaBlockSize =  0;
	UsartTx.dmaRingBuffer = 0;
	
	UsartTx.dmaProgress = 1;

	Usartd.pXdmad = &ChDma;
	Usartd.pRxChannel = &UsartRx;
	Usartd.pTxChannel = &UsartTx;
	USARTD_Configure(&Usartd, ID_USART0, mode, baudrate, sysclk_get_peripheral_hz());

	NVIC_ClearPendingIRQ(USART0_IRQn);
	NVIC_SetPriority( USART0_IRQn , 3);

	//USART_EnableIt(USART0, US_IER_TIMEOUT);

	NVIC_EnableIRQ(USART0_IRQn);
	//USART_EnableRecvTimeOut( USART0, rxTimeout);
}

 initBluetoothUSART(void)
{
	/* Init USART */
	/* Configure systick for 1 ms. */
	//TimeTick_Configure();
	_ConfigureUsart(115200, 100000);
	
	/*Enable Rx channel of USART */
	USARTD_EnableRxChannels(&Usartd, &UsartRx);
	/*Enable Tx channel of USART */
	USARTD_EnableTxChannels(&Usartd, &UsartTx);
	
	USARTD_RcvData(&Usartd);
	
	/*Initialize Ring buffer */
	pUsartBuffer = (RignBuffer_t *)malloc(sizeof(RignBuffer_t));
	_initCircularBuffer(pUsartBuffer);
	
}

void ReadBTMessage( void )
{
    const struct ble_msg *BTMessage; //holds BLE message
    struct ble_header BTHeader; //holds header of message
    unsigned char data[256] = "\0";//holds payload of message
	
	mutexTimeout = 0x7FF;
	while (LockMutex(semaphore, mutexTimeout));  // lock mutex
	
	//read BLE message header ~ 4 bytes
	memcpy( &BTHeader , (uint32_t *)pUsartBuffer->pBuffer, 4 );
	memory_sync();
	
	if(BTHeader.lolen > 0)
	{
		//setup the receiving buffer for the payload size
		UsartRx.BuffSize = BUFFER_SIZE;
		XDMAC_SetSourceAddr(ChDma.pXdmacs, UsartRx.ChNum, UsartRx.pBuff);
		XDMAC_SetMicroblockControl(ChDma.pXdmacs, UsartRx.ChNum, UsartRx.BuffSize);
		//set RTS low to enable transfer from BLE112
		USART0->US_CR = US_CR_RTSDIS;
		
		//wait for transfer to complete
		while(!BLE_Payload_Ready);
		
		//read BLE payload ~ BTHeader.lolen bytes
		memcpy( data , (uint32_t *)pUsartBuffer->pBuffer, BTHeader.lolen);
		memory_sync();
		
		//reset the receiving buffer for the header size
		UsartRx.BuffSize= BLE_HEADER_SIZE;
		XDMAC_SetSourceAddr(ChDma.pXdmacs, UsartRx.ChNum, UsartRx.pBuff);
		XDMAC_SetMicroblockControl(ChDma.pXdmacs, UsartRx.ChNum, UsartRx.BuffSize);
		//set RTS low to enable transfer from BLE112
		BLE_Header_Ready = false;
		BLE_Payload_Ready = false;
	}
	else
	{
		BLE_Header_Ready = false;		
	}
     
    //find the appropriate message based on the header, which allows
    //the ble112 library to call the appropriate handler
    BTMessage = ble_get_msg_hdr(BTHeader);
     
    //print error if the header doesn't match any known message header
    if(!BTMessage)
    {
            //handle error here
            return;
    }
    //call the handler for the received message, passing in the received payload data
    BTMessage->handler(data);
	ReleaseMutex(semaphore);
	USART0->US_CR = US_CR_RTSDIS;
}