[NO ASF] Hardware handshaking on SAMD21 (Arduino MKR 1400 GSM)

Hello,

I have been trying to write a code on the Arduino MKR 1400 GSM without using ASF or arduino libraries in Atmel Studio. This arduino comes with a GSM module - u blox SARA U201 which is already soldered on the board. I have been trying to establish UART communication with hardware handshaking.

Issue : GSM module doesn't accept any data and it seems to me that communication is not established at all even after initializing it properly and driving RTS and DTR pins low.

Here's the code I have written to initialize it.

void GSM_Init()
{

	//Reset Pin for GSM module
	PORT->Group[PORTB].DIRSET.reg = PORT_PB08;
	PORT->Group[PORTB].OUTSET.reg = PORT_PB08;
	delay_usec(1000);
	PORT->Group[PORTB].OUTCLR.reg = PORT_PB08;
	delay_usec(20000);

	//DTR Pin for GSM module
	PORT->Group[PORTA].DIRSET.reg = PORT_PA28;
	PORT->Group[PORTA].OUTSET.reg = PORT_PA28;
	delay_usec(1000);
	PORT->Group[PORTA].OUTCLR.reg = PORT_PA28;
	delay_usec(20000);

	//CTS pin as an output
	PORT->Group[PORTA].DIRCLR.reg = PORT_PA15;
	PORT->Group[PORTA].OUTCLR.reg = PORT_PA15; 

	//RTS Pin as an input
	PORT->Group[PORTA].DIRSET.reg = PORT_PA14;
	PORT->Group[PORTA].OUTSET.reg = PORT_PA14;
	delay_usec(1000);
	PORT->Group[PORTA].OUTCLR.reg = PORT_PA14;

	delay_usec(20000);

	PORT->Group[PORTA].DIRCLR.reg = PORT_PA13;  // RX as input
	PORT->Group[PORTA].OUTCLR.reg = PORT_PA13; 

	PORT->Group[PORTA].DIRSET.reg = PORT_PA12;  // TX as output
	PORT->Group[PORTA].OUTCLR.reg = PORT_PA12; 

	// Start the Software Reset and wait for it to finish
	SERCOM4->USART.CTRLA.bit.SWRST = 1;
	while ( SERCOM4->USART.CTRLA.bit.SWRST || SERCOM4->USART.SYNCBUSY.bit.SWRST ) ;

	//Setting clock
	GCLK->CLKCTRL.reg =
	GCLK_CLKCTRL_ID( GCLK_CLKCTRL_ID_SERCOM4_CORE_Val ) | // connected  SERCOMx to
	GCLK_CLKCTRL_GEN_GCLK0    | // generic Clock Generator 0
	GCLK_CLKCTRL_CLKEN;      // and enable it

	while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ); // Wait for synchronization	

	// set port multiplexer for peripheral TX
	// =======================================

	PORT->Group[PORTA].PINCFG[12].bit.PMUXEN = 1;
	PORT->Group[PORTA].PINCFG[13].bit.PMUXEN = 1;
	PORT->Group[PORTA].PINCFG[14].bit.PMUXEN = 1;
	PORT->Group[PORTA].PINCFG[15].bit.PMUXEN = 1;

        // PMUX = 3 for D which is SERCOM ALTERNATIVE PADS
	PORT->Group[PORTA].PMUX[6].bit.PMUXE = 3;
	PORT->Group[PORTA].PMUX[6].bit.PMUXO = 3;

	PORT->Group[PORTA].PMUX[7].bit.PMUXE = 3;
	PORT->Group[PORTA].PMUX[7].bit.PMUXO = 3;

	SERCOM4->USART.CTRLA.reg =
	SERCOM_USART_CTRLA_DORD           | // LSB_FIRST
	SERCOM_USART_CTRLA_TXPO(2)    | // TX on Pad 0, RTS on Pad 2, CTS on Pad 3
	SERCOM_USART_CTRLA_RXPO(1)  | // RX on Pad 1
	SERCOM_USART_CTRLA_MODE_USART_INT_CLK; // Use internal clock

	// Asynchronous arithmetic mode
	// 65535 * ( 1 - sampleRateValue * baudrate / SystemCoreClock);
	// 65535 - 65535 * (sampleRateValue * baudrate / SystemCoreClock));
	SERCOM4->USART.BAUD.reg = 65535.0f * ( 1.0f - (16.0 * (float)(115200)) / (float)(MAIN_CLK_FREQ));

	SERCOM4->USART.CTRLB.reg =
	SERCOM_USART_CTRLB_CHSIZE(0)  | // 8 bit character size
	SERCOM_USART_CTRLB_TXEN     | // Enable Transmit
	SERCOM_USART_CTRLB_RXEN     ; // Enable Receive

	// Get Synced
	while (SERCOM4->USART.SYNCBUSY.bit.CTRLB) ;

	//Set the Interrupt to use
	SERCOM4->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC; // Interrupt on received complete

	// Enable interrupts
	NVIC_EnableIRQ(SERCOM4_IRQn);

	// enable the peripheral block
	SERCOM4->USART.CTRLA.bit.ENABLE = 1;

	// Wait for sercom to enable
	while(SERCOM4->USART.SYNCBUSY.bit.ENABLE);
}

note : Bus clock is provided to enable SERCOM4

Here are the Transmit and Receive Routines for SERCOM4:

//receive interrupt handler
void SERCOM4_Handler()
{
	if (SERCOM4->USART.INTFLAG.bit.RXC)
	{
		uint16_t rxData = SERCOM4->USART.DATA.reg;
		return;
	}
}

void GSMPutc(char data)
{
	while(SERCOM4->USART.INTFLAG.bit.DRE == 0); // wait for TX data empty
	SERCOM4->USART.DATA.reg = data;
}

void GSMPuts(char *s)
{
	while (*s)
	{
		GSMPutc(*s++);
	}

}

I am sending "AT" string to the SERCOM4 and I expect "OK" string back when the GSM module receives it. Data never leaves the UART data register from the controller.

Can any one please help me establish the communication?

I did find the solution. All the SERCOM4 configuration was correct. The issue was with the Port configuration and had to enable some more bits in the port configuration. Here's what worked.

This is what I wrote initially.

PORT->Group[PORTA].PINCFG[12].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[13].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[14].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[15].bit.PMUXEN = 1;

// PMUX = 3 for D which is SERCOM ALTERNATIVE PADS
PORT->Group[PORTA].PMUX[6].bit.PMUXE = 3;
PORT->Group[PORTA].PMUX[6].bit.PMUXO = 3;
PORT->Group[PORTA].PMUX[7].bit.PMUXE = 3;
PORT->Group[PORTA].PMUX[7].bit.PMUXO = 3;

I changed it to this

//Pin 14 is RTS
//Pin 15 is CTS

PORT->Group[PORTA].PINCFG[12].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[13].bit.PMUXEN = 1;
PORT->Group[PORTA].PINCFG[14].bit.INEN = 1;
PORT->Group[PORTA].PINCFG[15].bit.PMUXEN = 1;

//pin 28 is DTR		
PORT->Group[PORTA].PINCFG[28].bit.INEN = 1;
PORT->Group[PORTA].PINCFG[28].bit.PMUXEN = 0;
PORT->Group[PORTA].PINCFG[14].bit.DRVSTR = 0;
	
PORT->Group[PORTA].PMUX[6].bit.PMUXE = 3;
PORT->Group[PORTA].PMUX[6].bit.PMUXO = 3;
	
PORT->Group[PORTA].PMUX[14].bit.PMUXE = 0;
PORT->Group[PORTA].PMUX[7].bit.PMUXO = 3;

This is the conclusion to this thread so that everyone else can get the help.

This forums is so poor, I just read another topic where a topic poster answers own questions. Glad at least you share solution to problem you experienced, it is always welcome. I keep looking for solution to GSM.begin() and SMS.available() freezing the loop() for short while because of delays implemented in MKRGSM lib but found nobody able to help resolve the problem.