SamD21 non-blocking USART interrupts [No ASF]

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

I'm working on something where I'd like non-blocking UART interrupts, or at least some direction on how to go about having a UART handler, or some way to receive characters over a UART and then do something with them.

 

The hardware is a MAX3232 connected to PA08 and 09; I can send characters over a serial port and they're received just fine, I'm just looking to receive characters with the same UART. The best success I've had is from a few forum threads (esp this one), but I can't find an example of receiving a character from the USART, then doing something with it. The microchip examples are, 'blink a pin when a character is received', which is incredibly frustrating.

 

Is there some sort of tutorial, or guide, or _something_ that shows non-blocking USART reading and writing?

 

The main.c:


#include <asf.h>
#include <string.h>

#include "config_usart.h"
#include "conf_clocks.h"

uint16_t ul_tickcount=0;

uint8_t ext_rx_data;


void setupBoard(void);

void usart_read_callback(struct usart_module *const usart_module);
void usart_write_callback(struct usart_module *const usart_module);
void configure_usart_callbacks(void);

struct usart_module usart_instance;

#define MAX_RX_BUFFER_LENGTH   256
volatile uint8_t rx_buffer[MAX_RX_BUFFER_LENGTH];

int main (void)
{
	setupBoard();
	
	while(1)
	{	
		__WFI();
		
		if((ul_tickcount % (UINT16_MAX/4) == 0))
		{
		//Does something here, but I'd like to also recieve 
		//characters over the serial port and do something with them
		}
	}
}

void SysTick_Handler(void)
{
	ul_tickcount++;
}

void conf_systick(void)
{
	//system_core_clk=48Mhz / 1000=48kHz systic clk if 48Mhz  is used
	SysTick_Config(SystemCoreClock/1000);
	system_interrupt_enable(SYSTEM_INTERRUPT_SYSTICK);
}

void configure_usart_callbacks(void)
{
	//! [setup_register_callbacks]
	usart_register_callback(&usart_instance,usart_write_callback, USART_CALLBACK_BUFFER_TRANSMITTED);
	usart_register_callback(&usart_instance, usart_read_callback, USART_CALLBACK_BUFFER_RECEIVED);

	//! [setup_enable_callbacks]
	usart_enable_callback(&usart_instance, USART_CALLBACK_BUFFER_TRANSMITTED);
	usart_enable_callback(&usart_instance, USART_CALLBACK_BUFFER_RECEIVED);

}

void usart_read_callback(struct usart_module *const usart_module)
{
	usart_write_buffer_job(&usart_instance,
	(uint8_t *)rx_buffer, MAX_RX_BUFFER_LENGTH);
}

void usart_write_callback(struct usart_module *const usart_module)
{
	//I'd like to receive a character here and send that character to another function
}

void setupBoard(void)
{

	system_init();


	configure_console();
	printf("Serial OK 9600 8N1\n\r");

    system_interrupt_enable_global();
}

The config_usart.c:

#include "config_usart.h"

void configure_console(void)
{
	struct usart_config config_usart;
	usart_get_config_defaults(&config_usart);

	config_usart.baudrate    = SERCOMBAUD;
	config_usart.mux_setting = SERCOMMUX;
	config_usart.pinmux_pad0 = SERCOMPAD0;
	config_usart.pinmux_pad1 = SERCOMPAD1;
	config_usart.pinmux_pad2 = SERCOMPAD2;
	config_usart.pinmux_pad3 = SERCOMPAD3;

	while (usart_init(&usart_instance,	 SERCOMMODULE, &config_usart) != STATUS_OK) { }

	stdio_serial_init(&usart_instance, SERCOMMODULE, &config_usart);
	usart_enable(&usart_instance);
}

void serialRead(uint16_t *const buffer){
	
	if (usart_read_wait(&usart_instance, buffer) == STATUS_OK) {
	}
}

config_usart.h:

#include <asf.h>
uint8_t read_buffer;

#define SERCOMBAUD		9600

/* Uncomment to use SERCOM 2 config settings! */
#define SERCOM2USART

#if defined(SERCOM2USART)
#define SERCOMMODULE	        SERCOM2
#define SERCOMMUX		USART_RX_1_TX_0_XCK_1
#define SERCOMPAD0		PINMUX_PA08D_SERCOM2_PAD0
#define SERCOMPAD1		PINMUX_PA09D_SERCOM2_PAD1
#define SERCOMPAD2		PINMUX_UNUSED
#define SERCOMPAD3		PINMUX_UNUSED
#else
#define SERCOMMODULE	        SERCOM3
#define SERCOMMUX		USART_RX_1_TX_0_XCK_1
#define SERCOMPAD0		PINMUX_PA22C_SERCOM3_PAD0
#define SERCOMPAD1		PINMUX_PA23C_SERCOM3_PAD1
#define SERCOMPAD2		PINMUX_UNUSED
#define SERCOMPAD3		PINMUX_UNUSED
#endif

struct usart_module usart_instance;

void configure_console(void);
void serialRead(uint16_t *const buffer);

 

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

Sorry but "[No ASF]"?  This code is using ASF. If that is actually ok then there is an example here (I searched for USART_CALLBACK_BUFFER_RECEIVED).

https://community.atmel.com/foru...

/Lars

 

 

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

But, again, you can look into the ASF source to see what it's doing - so it does provide the example you asked for.

 

Hint: when trying to follow ASF code, I find it much easier to do that at runtime, by stepping in the debugger, rather than just browsing the code and trying to untangle all the options.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...