Dropping UART bits after ATXMEGAA3Bu clock speed change

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

Hi,

 

First, I've RTFMed the A3B7 and AU datasheets quite a bit, and then I read this post:  "ATxmega256A3BU-xplained / clk_per selection" in this forum.  While the code is not yet working correctly, it seems I'm getting closer.

 

I changed the CPU speed on my A3BU Xplained board to 32MHz and began seeing random bit patterns in the byte received by UART.  The byte being transferred is always 0x2B.

 

NB:  I'm feeding the UART data on the A3BU Xplained board via Jumper J1.  The code does not utilize the bootloader.

 

After reading the above-stated post, I set conf_clock.h to:

#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32MHZ
#define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1

 

I am sending bits across a db9 serial cable from a linux box.  The linux commands used are:

$ stty -F /dev/ttyS0 9600 cs8 -cstopb -parenb
$ echo -ne '\x2b' > /dev/ttyS0

 

Now I consistently lose / drop bits:

 

0x2B sent, 0x0B received;

0x4B sent, 0x0B received;

0xFF sent, 0x1F received.

 

UART speed is set to 9600, parity N, data 8 bits, stop 1 bit.

 

In the startup code I've got:

ccp_write_io((uint8_t *)&CLK.CTRL, CLK_SCLKSEL_RC32M_gc);

but I'm not sure if that is needed.  My apologies for being such a n00b on clocks!

 

If someone could please tell me what I'm doing wrong, I would truly appreciate it.

 

Thanks In Advance!

This topic has a solution.
Last Edited: Mon. Oct 10, 2016 - 09:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe not that useful, but...did you recalculate your UART baud value after doing this clock change?

 

In many cases the application doesn't know what freq the app is running at after compile time. So perhaps if the baud value is being autocalculated (or manually do it), you just have to tell your app what the new crystal speed is?

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

Are you calling sysclk_init() to initialize the system clock?  If not, then the parameters in conf_clock.h are meaningless.  If so, then there is no need to do this:

ccp_write_io((uint8_t *)&CLK.CTRL, CLK_SCLKSEL_RC32M_gc);

To switch from the default RC2M clock you must first enable the RC32M oscillator, wait for it to become ready, then switch to it as the system clock source.

 

How are you determining F_CPU and the BAUDCTRL?

 

Post your USART and system clock init code.

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

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

@ryanfleming

> did you recalculate your UART baud value after doing this clock change?

 

If you mean baud rate as in "bits per second", no, that has not changed.  It was 9600 before the "clock change" and it remains 9600.  As I have to transfer ~4MB, I would like to bump that value up for production's sake, but for now during testing, I feel 9600 is a "reasonable" value.  The maximum it can be depends upon the sector write time for the dataflash (~30ms).

 

@Greg_Muth

> To switch from the default RC2M clock you must first enable the RC32M oscillator, wait for it to become ready, then switch to it as the system clock source.

 

I was not aware of that, thanks!

 

> How are you determining F_CPU and the BAUDCTRL?

 

I set F_CPU to 32000000UL at the beginning of the compile thusly:

#define F_CPU 32000000UL

but was not aware that i had to set a variable BAUDCTRL...

 

> Post your USART and system clock init code.

 

Ok, I have included it below.  First, the pertinent first few lines in the main() routine:

 

int main(void) {

    sysclk_init();

    ccp_write_io((uint8_t *)&CLK.CTRL, CLK_SCLKSEL_RC32M_gc);

    board_init();

    at45dbx_init();

    ...
    

 

Next, the sysclk_init() routine in sysclk.c (I am using ASF).  Please note that this code has not been touched since it's inclusion:

void sysclk_init(void)
{
(snippage due to length)
}
#endif // XMEGA_AU || XMEGA_B || XMEGA_C

The main() routine calls a setup routine if it determines the "read serial data via uart" needs to be run.  The setup routine invokes the uart setup thusly:

	// USART options.
	static usart_rs232_options_t USART_SERIAL_OPTIONS = {
		.baudrate   = 9600,
		.paritytype = 0,
		.charlength = 8,
		.stopbits   = 1
	};

	//	Initialize usart driver in RS232 mode
	sysclk_enable_module(SYSCLK_PORT_C, PR_USART0_bm);
	usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS);

The usart_init_rs232() code looks like this:

bool usart_init_rs232(USART_t *usart, const usart_rs232_options_t *opt)
{
	bool result;
	sysclk_enable_peripheral_clock(usart);
	usart_set_mode(usart, USART_CMODE_ASYNCHRONOUS_gc);
	usart_format_set(usart, opt->charlength, opt->paritytype,
			opt->stopbits);
	result = usart_set_baudrate(usart, opt->baudrate, sysclk_get_per_hz());
	usart_tx_enable(usart);
	usart_rx_enable(usart);

	return result;
}

 

Thanks Again!

TOU

Last Edited: Tue. Oct 11, 2016 - 05:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@ryanfleming:

were you referring to this chart, image attached?

 

Thanks

TOU

Attachment(s): 

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

Ok!  I changed the USART initialization code to look like this:

	//	Initialize usart driver in RS232 mode
	sysclk_enable_module(SYSCLK_PORT_C, PR_USART0_bm);
	//	set UART speed based on big chart
	usart_set_bsel_bscale_value(USART_SERIAL, 12, 4);				//	32MHz and 9600 baud
	usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS);

and the startup code that sets the 32MHz clock to look like this:

	sysclk_init();
	//	bump the internal clock to 32MHZ
	osc_enable(OSC_ID_RC32MHZ);
	osc_wait_ready(OSC_ID_RC32MHZ);

and when I transmit 0xFF i still get 0x1F.

 

Did I miss something?

 

Thanks

TOU

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Never mind - I found the right combination.  Thanks for all your help!

 

TOU

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

TOU,

 

You are (re-) doing things that ASF does for you:

  • calling sysclk_init() sets your clock frequency per the config parameters in conf_clk.h, so there is no need for this:
    	//	bump the internal clock to 32MHZ
    	osc_enable(OSC_ID_RC32MHZ);
    	osc_wait_ready(OSC_ID_RC32MHZ);
  • calling usart_init_rs232() sets BAUDCTRL for you; it also enables the peripheral clock for the USART., so there is no need to do this:

    sysclk_enable_module(SYSCLK_PORT_C, PR_USART0_bm);
  • in your USART setup routine or this:

    	usart_set_bsel_bscale_value(USART_SERIAL, 12, 4);
  • in the USART initialization routine.

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

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

Greg,

 

thanks for the comments.  wrt your commments:

 

> calling sysclk_init() sets your clock frequency per the config parameters in conf_clk.h,

 

I have no module "conf_clk.h":

C:\...\Uno_AS7_003>dir/s conf_clk.h
 Volume in drive C is CAD_C
File Not Found

 

I *do* have a conf_clock.h:

#ifndef _CONF_CLOCK_H
#define _CONF_CLOCK_H

//	#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32MHZ
//	#define CONFIG_OSC_RC32_CAL         48000000UL
//	#define CONFIG_OSC_AUTOCAL          OSC_ID_RC32MHZ
//	#define CONFIG_OSC_AUTOCAL_REF_OSC  OSC_ID_USBSOF

#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC32MHZ
#define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1

#endif  // _CONF_BOARD_H

I assUme that's what you meant.  When I saw the "48000000UL" I removed the parameters "wrapped around it".  I'm thinking now that I should bring some of those #define's back in, so I'm in RTFM mode.  The #define's I inserted were from an 'Freaks post I read that made sense "at the time".  More to research...

 

Right now, I'm transmitting 2.5MB across the serial link, and without the overhead of actually writing dataflash, I'm only getting around 6K worth of characters, so "an intense code review" is underway.  But I believe in minimization, so if I have duplicate code, that's "got to go", after I ensure that the device actually reads 2.5MB worth of data.

 

I'll try testing again after removing the mods you pointed out, and see how that goes.

 

Thanks again!

TOU

 

Last Edited: Tue. Oct 11, 2016 - 03:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I discovered that it helps to make certain that the USART is not actively receiving or transmitting characters while changing the clock speed . . .