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!