samd21g18a usart sync driver using atmel start code not working

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I'm trying to use atmel start to generate the necessary skeleton building blocks for my application which requires the use of several usart ports. Since I'm a newby with samd21s and with atmel start I decided to create a small project and build from there. My architecture uses two usarts as follows (one to communicate with a gsm module and another for debugging purposes):

 

struct usart_sync_descriptor U_GSM_COMM_0;

struct usart_sync_descriptor U_DEBUG_COMM;

void U_GSM_COMM_0_PORT_init(void)
{

	gpio_set_pin_function(PB10, PINMUX_PB10D_SERCOM4_PAD2);

	gpio_set_pin_function(PB11, PINMUX_PB11D_SERCOM4_PAD3);
}

void U_GSM_COMM_0_CLOCK_init(void)
{
	_pm_enable_bus_clock(PM_BUS_APBC, SERCOM4);
	_gclk_enable_channel(SERCOM4_GCLK_ID_CORE, CONF_GCLK_SERCOM4_CORE_SRC);
}

void U_GSM_COMM_0_init(void)
{
	U_GSM_COMM_0_CLOCK_init();
	usart_sync_init(&U_GSM_COMM_0, SERCOM4, (void *)NULL);
	U_GSM_COMM_0_PORT_init();
}

void U_DEBUG_COMM_PORT_init(void)
{

	gpio_set_pin_function(PB22, PINMUX_PB22D_SERCOM5_PAD2);

	gpio_set_pin_function(PB23, PINMUX_PB23D_SERCOM5_PAD3);
}

void U_DEBUG_COMM_CLOCK_init(void)
{
	_pm_enable_bus_clock(PM_BUS_APBC, SERCOM5);
	_gclk_enable_channel(SERCOM5_GCLK_ID_CORE, CONF_GCLK_SERCOM5_CORE_SRC);
}

void U_DEBUG_COMM_init(void)
{
	U_DEBUG_COMM_CLOCK_init();
	usart_sync_init(&U_DEBUG_COMM, SERCOM5, (void *)NULL);
	U_DEBUG_COMM_PORT_init();
}

void delay_driver_init(void)
{
	delay_init(SysTick);
}

void system_init(void)
{
	init_mcu();

	U_GSM_COMM_0_init();

	U_DEBUG_COMM_init();

	delay_driver_init();
}

 

I tweaked the code examples from atmel start and can write to both ports with success:

 

int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();

	struct io_descriptor *io_gsm;
	usart_sync_get_io_descriptor(&U_GSM_COMM_0, &io_gsm);
	usart_sync_enable(&U_GSM_COMM_0);

	struct io_descriptor *io_debug;
	usart_sync_get_io_descriptor(&U_DEBUG_COMM, &io_debug);
	usart_sync_enable(&U_DEBUG_COMM);
	
	const char buffer[128];
	
	while (1) 
	{
		
		io_write(io_debug, (uint8_t *)"1.", 2);	    // works
		io_write(io_gsm, (uint8_t *)"AT\n", 3);     // works
		io_write(io_debug, (uint8_t *)"2.", 2);     // works
		delay_ms(1000);
		io_write(io_debug, (uint8_t *)"3.", 2);     // works
		io_read(io_gsm,  (uint8_t *)buffer, 128);   // NOT WORKING!!!
		io_write(io_debug, (uint8_t *)"4.", 2);     // code not executed from this point on
		delay_ms(1000);
		io_write(io_debug, (uint8_t *)"5.", 2);
	}
}

But when I try to read the usart using the following code I get nothing (since it's a blocking call the program stays there forever):

io_read(io_gsm,  (uint8_t *)buffer, 128);   // NOT WORKING!!!

I'm using a basic clock configuration with the 8mhz internal oscillator (OSC8M) for GCG0 which I use for the CPU and both USARTs (I'm also using OSCULP32K with GCG1 for the USART slow clock - not sure if this is the correct way to do it though), all at 8mhz.

 

Should I change to a more barebone's approach (https://www.avrfreaks.net/forum/...)? Perhaps using the async driver instead (https://www.avrfreaks.net/forum/...)?

 

These are quite important design decisions because I'll be polling one of the usarts but will also need to be notified when data is available at any moment (my sensors trigger interrupts too). It would also be interesting to be able to use atmel start generated code because it's quite well organised in different layers.

 

These questions are surely basic for many of you, but any hints on what direction to take would be greatly appreciated.

 

Best

ajs

ajs

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can probably use usart_sync_is_rx_not_empty and read one character when it is not. The async driver is likely  a better solution. This thread could be useful:

https://community.atmel.com/comm...

/Lars

 

usart_sync_is_rx_not_empty
usart_sync_is_rx_not_empty
usart_sync_is_rx_not_empty
usart_sync_is_rx_not_empty
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

^ As Lars stated, I would definitely switch to the async implementation, and utilize the RX_Complete callback functionality.

 

If you change the module to Async in START, I believe the rxComplete_cb is generated for you and used in the example_drivers.c file.

murph

Debugging - Being a detective in a crime movie where you are also the murderer.