[NO ASF] [NO ARDUINO LIBRARIES] GSM module stops UART communication

I have been trying to program Arduino MKR GSM 1400 from scratch without using any Arduino or Atmel libraries. I have been facing UART communication issues with the GSM module.

Issue:

  • GSM moudle breaks the UART communication when SIM card is inserted and doesn't wake up/response after few seconds.

Behavior noticed:

  • Communication stays ON when no SIM card is inserted. (Note: UART communication with hardware handshaking)
  • Communication stays ON when SIM card is inserted if I upload the Arduino bootloader from Arduino software before starting the application. It again starts behaving as written in the issue after cycling the power

Here's the UART initialization and RX interrupt handler code:

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].OUTCLR.reg = PORT_PA14;	
	delay_usec(20000);
	
	PORT->Group[PORTA].DIRCLR.reg = PORT_PA13;  // RX as input
	PORT->Group[PORTA].OUTSET.reg = PORT_PA13; 
	
	PORT->Group[PORTA].DIRSET.reg = PORT_PA12;  // TX as output
	PORT->Group[PORTA].OUTSET.reg = PORT_PA12; 	

	//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	
	
	// 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 ) ;

	// 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[13].bit.INEN = 1;
	//PORT->Group[PORTA].PINCFG[14].bit.PMUXEN = 1;
	PORT->Group[PORTA].PINCFG[14].bit.INEN = 1;
	PORT->Group[PORTA].PINCFG[15].bit.PMUXEN = 1;
	//PORT->Group[PORTA].PINCFG[15].bit.INEN = 1;
		
	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;	
	
	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_SAMPR(SAMPLE_RATE_x16) | // 16 times oversampling
	SERCOM_USART_CTRLA_RUNSTDBY         | // Run in standby mode
	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);	
	
}

void SERCOM4_Handler()
{	
        //Assert RTS to let GSM module know not to send more data for now
	PORT->Group[PORTA].OUTSET.reg = PORT_PA14;	
	if (SERCOM4->USART.INTFLAG.bit.RXC)
	{			
		// Got a character
		uint16_t rxData = SERCOM4->USART.DATA.reg;	
		
		if(rxData == '\0')
		{		
	                //These function definitions are not added here as they are simple.
			GSMAcknowledgeError();
			GSMFlush();
			GSMClearStatus();			
			millis20Start = true;
			millis20Passed = false;	
			while(!millis20Passed);

                        //RESET GSM MODULE
			GSMPuts("AT+CFUN=16\r");
		}
		
		UartPutc(rxData);		
		if(rxData != '\0')
			GSM_buffer[gsm_cnt++] = rxData;			
		
	}	
	PORT->Group[PORTA].OUTCLR.reg = PORT_PA14;	
				
	return;
}

Any kind of suggestions and solutions are welcomed! Thanks in advance!

I found the solution today and that is not related to code at all (I know code isn't perfect eithercheeky). That is related to the power.

Solution:

In the Arduino MKR GSM 1400 product description, it is written that GSM module can draw the current up to 2A while registering to the network or other similar operations. I was using power supply that could only provide 1A max. There's an option to connect a battery on the board and that's what Arduino suggests.

Boom! I connected the battery along with the power supply and module is getting proper supply and working as it should be.