UC3 with RPi 3 for data logging

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

I am very newbie to uc and general programming, yet I have this task to get done, and I am hoping this community will help me. Please all, come to my aid.

 

1. The current status of the project is a custom board with AT32UC3A1512 uc. The board specific is for some radar project, and in the project the uc process the acquired data from antennas and send them over (wireless) Zigbee connection to STK600 with another AT32UC3A1512 uc which connects to MATLAB running on a PC.

 

2. It is now desired to eliminate the Zigbee connection, and instead of sending the acquired data to a PC (with MATLAB), the data should be logged into some SD card which a RPi 3 can easily do.

 

I need help in interpreting the current codes (in C) that I have for the current status of the project, and help with changing these codes around for communicating with the RPi.

 

Note- connection to Zigbee module from the radar board/device is through SPI

This connection is still available to connect to the RPi, while another UART is additionally available too.

 

PS- I have a very lengthy code of about 3000 lines. Pasting them here may be disorderly. Please find in the attachment. A picture of the custom board is as well shown (without the UART connections anyway)

Attachment(s): 

Last Edited: Sat. Sep 9, 2017 - 04:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A quick glance indicates that the Zigbee configuration/control is done with trx_reg_write(,) and data is sent with trx_frame_write(,)
If you eliminate the Zigbee (a new circuit board ?), then all that configuration can be removed and trx_frame_write() can be still be used to send data via SPI to the RPi.
Seems to me that lines 1484 to 2906 will never be executed.

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

mikech wrote:
A quick glance indicates that the Zigbee configuration/control is done with trx_reg_write(,) and data is sent with trx_frame_write(,) If you eliminate the Zigbee (a new circuit board ?), then all that configuration can be removed and trx_frame_write() can be still be used to send data via SPI to the RPi. Seems to me that lines 1484 to 2906 will never be executed.

 

Hi mikech,

 

thanks for your suggestion/input.

 

I am afraid I may have some hardware problem, and I welcome your further suggestion. From revising RPi SPI configurations, I realised RPi only allows its SPI in Master mode, this looks to me that I may be risking having two (SPI) masters in my setup, since the MCU's SPI is better configured (or as configured in the previous code) as master.

 

Would you suggest I make my MCU SPI into slave? What implications may this have on my setup/the MCU?

 

On the other hand, I made provisions for UART in the board design:

1. would you advise I get started with UART and ditch SPI?

2. will the trx_frame_write() still be suitable to do UART for the MCU to RPi as suggested in your previous response?

 

 

PS- I am a newbie in embedded C, hence, I am taking the shortcut of hacking the codes other than developing on from start. And also hacking may be faster as the project has some deadlines.

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

A big problem when transferring data from a master to a slave is synchronization of the data stream.
With SPI the slave can use the chip-select line to indicate that a packet of data is being received., but the USART needs different technique(s) to indicate what should be considered a packet of data.,
for example ;
- timing (a long pause could indicate the end of a packet)
- framing (special codes indicate the start and/or end of a packet).
Welcome to the wide world of communications protocols, where there are hundreds of different ways to move data.


trx_frame_write() has been written to send a block of samples so I would modify it to use the USART and do something like ;
- drive a GPIO pin low (to indicate to the RPi that a packet of data is arriving),
- send a data-header to indicate how many bytes are being transmitted,
- send the data,
- drive the GPIO pin high (to indicate that no more data is being transmitted and that the RPi can now process the packet)

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

obabarin wrote:
I am very newbie to uc and general programming, yet I have this task to get done

So could you explain a little more why this task has fallen to you, specifically - as it is so obviously a task which requires familiarity microcontrollers & programming?

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

mikech wrote:
.... Welcome to the wide world of communications protocols, where there are hundreds of different ways to move data.

 

thanks mikech...this is insightful.

 

i will then get started on how to execute UART on the AVR UC3 mcu and the RPi. Would there be any resource you can recommend?

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

awneil wrote:

 

So could you explain a little more why this task has fallen to you, specifically - as it is so obviously a task which requires familiarity microcontrollers & programming?

 

it is a school project awneil. and it is expected of me to learn on the 'job'....i don't personally see any problem with that (my level of skills), getting this done is a matter of devotion and getting the right information/resources to work with.

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

It appears to me (from the arrangement of the .h header files) that the project is not exactly what the Atmel-Studio ASF-Wizard produces.,
therefore you might need to do some sleuthing to find the ASF files usart.h and usart.c and add them to your project.
(or use the Wizard to add the 'USART driver' and then move the files from where the Wizard puts them)


The USART has many operating modes, but 'normal' mode at (say) 115200 baud with 8 bits per character, 1 stop bit and no parity, would be a reasonable starting point.
usart.c will contain functions such as usart_init_rs232_tx_only(,,) and usart_putchar(,) which you can then use.

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

mikech wrote:

It appears to me ......... which you can then use.

 

Thanks for the tips and the interests to help. Expect my updates in the coming week.

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

My Update with USART

 

I had been looking up pages on the internet (and everywhere?). Yet to figure out much about the USART of a procedure. My updates are in the line below. Any suggestion on where I am right or wrong? What will my next step be?

#include <avr32/io.h>

#include <asf.h>
#include <parts.h>
#include <stdint.h>
#include <stdbool.h>

#include "stdio.h"
#include "gpio.h"
//#include "sysclk.h"
//#include "conf_clock.h"
#include "board.h"
#include "user_board.h"
//#include "pm.h"
//#include "delay.h"

#include "usart.h"
//#include "conf_usart.h"


// USART pins and Functions

#define USART               (&AVR32_USART3)

#define USART_RX_PIN        AVR32_USART3_RXD_0_0_PIN
#define USART_TX_PIN        AVR32_USART3_TXD_0_0_PIN

#define USART_RX_FUNCTION   AVR32_USART3_RXD_0_0_FUNCTION
#define USART_TX_FUNCTION   AVR32_USART3_TXD_0_0_FUNCTION

//#  define USART_CLOCK_MASK    AVR32_USART3_CLK_PBA
//#  define USART_IRQ           AVR32_USART3_IRQ // not sure i want to use interrupt

static const gpio_map_t USART_GPIO_MAP =
{
	{USART_RX_PIN, USART_RX_FUNCTION},
	{USART_TX_PIN, USART_TX_FUNCTION}
}; // I will need to do PIN assignment



// USART OPTIONS

#define USART_BAUDRATE						9600
#define USART_CHANNELMODE					USART_NORMAL_CHMODE
#define USART_CHAR_LENGTH					8
#define USART_PARITY_TYPE					USART_NO_PARITY
#define USART_STOP_BITS						USART_1_STOPBIT					



//create USART options struct

static usart_options_t USART_OPTIONS = {
	.baudrate = USART_BAUDRATE,
	.channelmode = USART_CHANNELMODE,
	.charlength = USART_CHAR_LENGTH,
	.paritytype = USART_PARITY_TYPE,
	.stopbits = USART_STOP_BITS
};


// CLOCK DEFINITIONS

#define CLOCK_PBA_FREQ				15000000 //need to find value for PBA Hz






// RPi Definitions








int main (void)
{
	// Insert system clock initialization code here (sysclk_init()).

	board_init();

	// Insert application code here, after the board has been initialized.
	
	// USART GPIO MAP
	
	//static const gpio_map_t USART_GPIO_MAP = 
	//{
		//{USART_RX_PIN, USART_RX_FUNCTION},
		//{USART_TX_PIN, USART_RX_FUNCTION}
	//};
	
	
	//ASSIGN GPIO TO USART
	
	gpio_enable_module(USART_GPIO_MAP, sizeof(USART_GPIO_MAP)/ 
	sizeof(USART_GPIO_MAP[2]));
	
	// Initialize USART RS232 mode
	usart_init_rs232(USART, &USART_OPTIONS, CLOCK_PBA_FREQ); //need to change this clock later
	
	//Usart write out line
	usart_write_line(USART, "Hello");
	
	
}

 

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

mikech wrote:
or (sic) use the Wizard to add the 'USART driver' 

My experience is that this is not just an option - it is the only way to do it.

 

Simply adding the files is, IME, not sufficient; there is other - undocumented, yet essential - stuff which the Wizard also does.

 

EDIT

 

See: http://www.avrfreaks.net/comment...

Last Edited: Wed. Sep 20, 2017 - 05:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can do it all yourself, but it does take a considerable amount of time and effort to find and organize files into a particular layout, and then configure the IDE.

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

First step would be to ensure that the pin multiplexing is correct for your target hardware.

 

Second step would be to modify your main() so that it doesn't try to 'finish' after it sends that "Hello" message., eg. add a

while ( 1 )  // many non-OS projects will do most of their work inside this endless loop.
  {
  usart_write_line( USART, "this is a test\r\n" );
  };

 

The decision as to whether to use interrupts (or not) will depend on your application, ie.

- how frequently do you need to send data ?

- how much data is sent ?

- do you have time-critical actions in your project that must be performed at regular intervals ?

- etc. etc.

 

 

 

 

<begin minor rant>

I find the ASF pin-naming system confusing.

The GPIO Controller Function Multiplexing table says that the USART3 Rx on a UC3A can be function B on PB10, or function B on PX08.

The ASF AVR32_USART3_RXD_0_0_PIN definition is not very explanatory, whereas AVR32_PIN_PB10 or AVR32_PIN_PX08 are.

Similarly AVR32_USART3_RXD_0_0_FUNCTION is rather opaque (is it 0, 1 or 2 ?) , but if you use 1 (= Function B) it is clearer.

<end minor rant>

 

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

mikech wrote:

 

<begin minor rant>

 

<end minor rant>

 

 

It took me some while to figure out what your rant was about. But when I did, it helped clarify my confusions too. I modified the pin-naming as follows

#define USART               (&AVR32_USART3)


#define USART_RX_PIN        AVR32_PIN_PB10 //GPIO 42
#define USART_TX_PIN        AVR32_PIN_PB11 //GPIO 43

#define USART_RX_FUNCTION   AVR32_USART3_RXD_0_0_FUNCTION
#define USART_TX_FUNCTION   AVR32_USART3_TXD_0_0_FUNCTION

Function B is given as FUNCTION 1 in the ASF and since my device is 100 pin, I can only use the TQFP100 numbering of page 45 of the Datasheet. Looks like I have figured out the pins and their functions correctly. kindly help confirm this.

 

I am not yet sure if interrupt is crucial to my application. The data are to be logged to SD card through the RPi at all times- without need for any trigger other  than external power, after a booting sequence. If there will be a change in specifications, I may consider interrupt later.

 

One major question I have is the use of put_char and write_line functions. Is USART limited to writing text only?

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

My apologies... my rant was not directed at you, but at those who created that extra layer of confusion with the pin names


You are correct to use GPIO42,43 for USART3. (I'd forgotten that you were using the UC3A1512).


Creating meaningful names for functions is somewhat of an art.
The ASF usart_putchar(,) will transmit one byte, it doesn't care if it is human-readable text (eg. Z (hex 5A)), or not (eg. binary 11111111).
The ASF usart_write_line(,) transmits bytes (text or binary) from a buffer until it finds a binary zero., the name is misleading because it is actually a 'write-a-C-string' routine.
To transmit a block/packet of bytes you can create your own 'usart_write_buffer(,,)' routine which uses usart_putchar(,) or usart_write_char(,)

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

mikech wrote:

You are correct to use GPIO42,43 for USART3. (I'd forgotten that you were using the UC3A1512).
[/i]

 

UPDATES

 

I managed to be able to send characters over USART1 (of UC3A1512 and STK600 development kit)- so excited for the small but meaningful progress.

 

Unfortunately, my custom board is configured to use USART3 on Function B, but I could not get this to work.

 

How to i rewrite this line to turn on to Function B?

 


#define USART_RX_FUNCTION   AVR32_USART3_RXD_0_0_FUNCTION
#define USART_TX_FUNCTION   AVR32_USART3_TXD_0_0_FUNCTION

I guess I am missing something- I tried many manipulations of the 0_0 to no avail.

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

I would just do
#define USART_RX_FUNCTION 1
#define USART_TX_FUNCTION 1


AVR32_USART3_RXD_0_0_FUNCTION and AVR32_USART3_TXD_0_0_FUNCTION are defined as 1 (=function B)


Basic questions ;
Does your custom board work ? ie. can you toggle an output pin (or LED) ?
How is USART3 connected to whatever you are using to monitor the communication ?

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

mikech wrote:
I would just do #define USART_RX_FUNCTION 1 #define USART_TX_FUNCTION 1

 

Thank you always for your tips and readiness to share your expertise.

 

Here are my updates-

1. I realised i made a little wiring connection. I fixed such and was able to see data from both my development and custom boards on PC.

2. I am using the USART-USB bridge adapter, and RealTerm for display on a Windows PC. But I cant see real data in any format given by the Realterm software- ASCII display wobbled texts, HEX, Binary and other display options give bunch of zero. I read on some other blogs that I may need to check my buad rate- will be doing that over the coming week.

 

Now trying to establish U(S)ART on RPi. If I may ask (minding that this is not a RPi forum), would you suggest using C or Python for this? I have seen several tutorials on this, and was wondering which is better suited for my application?

 

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

And the answer is ..... Whatever you like !


Seriously though, either C/C++ or Python will work, the deciding factors would be ;
- the volume of data that your board generates, and
- the learning-curve for writing code on the RPi.

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

There's plenty of examples of arduinos connected to raspis. If it is via serial (be it usb or actual serial) the technique is the same. My choice of language on the pi would be node-js, but any is suitable. Performance using an interpreted language should not be an issue on the pi.

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

Hello Contributors,

 

Here are my update and further seek for help. I had been trying to fix these issues on my own for the past days- but then i am eating the humble pie again to ask for help.

 

1. I have some python scripts running on my Rpi to which i confirm that the UART port of the RPI are fully functional- i could move data from the TX to RX and display on a console- both on the RPi using Minicom and a Windows PC using RealTerm client and a UART2USB bridge

 

2. I followed some sample ASF codes in Atmel Studio 6 to have working codes for testing my UC32 UART ports. I am certain my connections are correct- both using the UART2USB bridge and RS232 cable. My coding on the UC32 are as follows:

#include <asf.h>

#include <avr32/io.h>
#include "compiler.h"
#include "board.h"
#include "power_clocks_lib.h"
#include "gpio.h"
#include "usart.h"


#define USART				(&AVR32_USART3)
#define USART_RX_PIN		AVR32_USART3_RXD_0_0_PIN
#define USART_RX_FUNCTION	AVR32_USART3_RXD_0_0_FUNCTION
#define USART_TX_PIN		AVR32_USART3_TXD_0_0_PIN
#define USART_TX_FUNCTION	AVR32_USART3_TXD_0_0_FUNCTION
//#define	TARGET_PBACLK_FREQ_HZ	16000000
#define	TARGET_PBACLK_FREQ_HZ	12000000

int main (void)
{
	// Insert system clock initialization code here (sysclk_init()).

	board_init();

	// Insert application code here, after the board has been initialized.
	
	
	
	static const gpio_map_t USART_GPIO_MAP =
	{
		{USART_RX_PIN, USART_RX_FUNCTION},
		{USART_TX_PIN, USART_TX_FUNCTION}
	};

	// USART options.
	static const usart_options_t USART_OPTIONS =
	{
		.baudrate     = 115200,
		//.baudrate     = 57600,
		//.baudrate     = 9600,
		.charlength   = 8,
		.paritytype   = USART_NO_PARITY,
		.stopbits     = USART_1_STOPBIT,
		.channelmode  = USART_NORMAL_CHMODE
	};

	// Assign GPIO to USART.
	gpio_enable_module(USART_GPIO_MAP,
	sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

	// Initialize USART in RS232 mode.
	usart_init_rs232(USART, &USART_OPTIONS, TARGET_PBACLK_FREQ_HZ);

        //usart_init_rs232_tx_only(USART, &USART_OPTIONS, TARGET_PBACLK_FREQ_HZ);
	
	while (true){
	
	
	// Hello world!
	usart_write_line(USART, "Hello, this is the AVR UC3 MCU saying hello! (press enter)\r\n");

        //usart_putchar(USART, "1111111");            


	// Press enter to continue.
	//while (usart_get_echo_line(USART) == USART_FAILURE);  // Get and echo characters until end of line.

	//usart_write_line(USART, "Goodbye.\r\n");
	
	}
	
	
}

Here are my issues-

1. Whatever the text/char/numbers I put in usart_write_line or in usart_putchar, my console (Realterm via Serial or UART2USB bridge) always display the same thing in both ASCII, BIN or HEX format of the console software. Please see attached images. I am certain my baudrate was correctly set.

 

Can you suggest/troubleshoot this for me please? All suggestions are welcome- why is my UC32 not sending out the correct data?

 

2. Moving on, since I felt my UC32 was still spewing out some data- correct/otherwise, I connected it over UART to the RPi. But the RPi does not read or sense any data on the UART pins, hence, does not log any data to file. My python code is as below

#!/usr/bin/env python

import time
import serial
import os

ser = serial.Serial(
	#port='/dev/ttyAMA0',
	port =  '/dev/ttyS0',
	#baudrate = 9600,
	#baudrate = 57600,
	baudrate = 115200,
	parity = serial.PARITY_NONE,
	stopbits = serial.STOPBITS_ONE,
	bytesize = serial.EIGHTBITS,
	timeout = 1
	)
counter = 0

#logging

file = open("/home/pi/Documents/myPython/Data/log1.csv", "a")

if os.stat("/home/pi/Documents/myPython/Data/log1.csv").st_size==0:
	file.write("Data\n")

while 1:
	x = ser.readline()
	print x

	file.write(str(x)+ "\n")
	file.flush()
file.close()

What could be happening? Any suggestions/tips please?

 

I am not certain of what the output voltage level of the UC32 is, but I checked with a voltmeter and it was varying 1.0 to 1.8 V. I understand that Rpi takes in 3.3V, could this be where my problem lies? Knowing of certain that the code up there works perfectly?

 

Also, any suggestions on the relation between baudrate (of the UC32) and CPU clock? How could this affect my transmission or reception at the Rpi side? Someone please help me.

 

Thanks in advance.

Attachment(s): 

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

Most of the ASF routines have a return-code to indicate the result of calling a function, therefore it would be a 'good idea' to check that usart_init_rs232(,,) returns USART_SUCCESS (0)


What is the actual system clock frequency ?.
Do you have a 12 MHz crystal oscillator on your board ? (a #define TARGET_PBACLK_FREQ_HZ 12000000 does not guarantee that that is what you will actually get).
I am guessing that there is a sysclock_init() inside board_init() but sysclk_init() uses it's own set of #defines to configure the system clock(s).
The ASF has sysclk_get_cpu_hz() which would be better to use in usart_init_rs232(,,)


For historical reasons, serial baudrates have queer values, (4800, 19200, 57600) which are hard to achieve exactly with a clock-source that is not an almost-integer multiple of the baudrate.
eg. you might want 57600 baud, but with a 12 MHz system-clock you will actually get 57692 baud, which is a 0.16% error.
If there is more than about 3% baudrate mismatch between the sender and receiver it will cause problems with asynchronous serial communications and can often be detected in the receiver as a 'framing' error.
Receiver errors will probably (it depends on who wrote the code), cause the character with the error to be ignored.

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

mikech wrote:
...I am guessing that there is a sysclk_init() inside board_init() but sysclk_init() uses it's own set of #defines to configure the system clock(s). ......

 

Yes mikech, thanks for hinting this. Took me a while to figure that out, thanks to this thread and this link. I now have my mcu and rpi sending and receiving known data.

 

Moving on to the next stage....testing out all the functionality of my custom board, and creating better programs on Rpi for better logging.

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

Hello @mikech

 

1. I am asking for some tips and help. My UART worked well over the weekend- sending data over to PC Terminal program correctly which i was able to Rpi using python script. All went well over the weekend till i resumed on Monday morning and I began to experience errors, specifically UART Receiver Framing Error as detailed my the RealTerm Terminal Emulator. I have done all I could, from changing cables to ensuring good grounding between devices, this error persist, though it doesn't show up some times. And with this error, my RPi, does not detect any data on the RX line and hence, won't log. Any suggestions to check this error? Mind that I specified baudrate/bits/parity correctly on both devices.

 

2. I need some tip on how to write a UART frame function similar to this code:

void trx_frame_write(uint8_t * data, uint8_t length){

	uint8_t temp = TRX_CMD_FW;
	

	/* Start SPI transaction by pulling SEL low */
	spi_select_device(&AVR32_SPI1, &SPI_DEVICE_EXAMPLE);

	/* Send the command byte */
	spi_write_packet(&AVR32_SPI1, &temp, 1);

	spi_write_packet(&AVR32_SPI1, data, length);

	/* Stop the SPI transaction by setting SEL high */
	spi_deselect_device(&AVR32_SPI1, &SPI_DEVICE_EXAMPLE);

	
}

You suggested this earlier in one of your responses, but I have not been able to find adequate resources to get this done. I have been able to successfully use usart_write_line and usart_putchar before i start experiencing framing errors .

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

obabarin wrote:
 UART Receiver Framing Error ... I specified baudrate/bits/parity correctly on both devices.

Most likely means your baud rate is out, then - but only slightly out if it's "infrequent"

 

2. I need some tip on how to write a UART frame function

What makes you think that?

 

The "framing" is all done in hardware by the UART

 

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

awneil wrote:

 

 

Surprising thing is the baud rate and everything else worked perfectly just over the weekend, but since yesterday without changing anything, i began to experience errors. I do not even know where to look- cables, hardware or even the codes.

 

What makes you think that?

 

I do not really mean i wanna do the framing myself, what I intend to have is a function that will 'format' my data in format suitable for uart. my data is (supposedly) of the form of 3 bytes to be transmitted in every cycle of transmission.

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

obabarin wrote:
worked perfectly just over the weekend, but since yesterday without changing anything, i began to experience errors. 

was it working before the weekend?

 

does your office get cold(er) over the weekend - while nobody's there ... ?

 

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

was it working before the weekend?

Well, it took me about a week to figure how to get that part of initializing UART about 5 days -poor me. I only succeeded late friday evening, and was back on saturday to confirm progress and document the process. But by monday morning, I could not believe what was happening- wrong data being sent to pc, rpi refusing to log and the uart framing errors. as at today, my pc lost the driver to the STK 600 development board. I lost my sanity as I just could not explain what was happening.

 

I managed to fix the drivers and the likes. Mind that i was certain i shut everything down properly, so the possibility of voltage surge is ruled out. And my office dont really get colder nor hotter- and would crystals have been that sensitive to environment temperature?

 

About nobody's there.....i cant really say. But i know my colleagues wont have messed with my desk. Whatever could have happened anyway-forging ahead.

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

If your data contains bytes that are binary zero then you cannot use the ASF usart_write_line() because it will stop when it finds that zero value and not transmit it.

void usart_write_line(volatile avr32_usart_t *usart, const char *string)
{
  while (*string != '\0')
    usart_putchar(usart, *string++);
}

It is not difficult to use that as a basis to write your own routine to send a given number of bytes from a buffer.

There is still the issue of synchronising the data-flow, because you cannot simply transmit a stream of bytes and expect the receiver to interpret that stream correctly (data can be corrupted in transit, or the receiver loses data because it cannot cope, etc. etc)
With SPI, synchronisation is automatic because the chip-select line tells the slave when data is being transmitted
With USART there is no such automatic mechanism, hence you need to somehow 'tell' the target when a packet/block/burst of data is about to arrive., how you do that depends on many factors, such as ;

- how much data is in each 'packet/block/burst' ?

- how often are those packets transmitted ?

- is the data human-readable or binary ?

- how 'smart' is the receiving system ? (can the receiver tell the sender to pause for a while ?)

- what is the communications infrastructure and environment that the data is flowing through ? (eg. copper wire, optical, radio, ...)

Last Edited: Wed. Oct 4, 2017 - 01:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What baudrate are you using ?
Try something slower as an experiment.
A high baudrate might be too much for the target and hence causing overrun errors. (but the target might be coalescing overrun and framing errors as one generic error).

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

Hello mikech,

I am not sure if i found a solution to the issue of baudrate and the errors encountered on the UART. but i found something quite interesting as detailed as follows:

1. i start out with a new project, and edited conf-clock.h and user_board.h as detailed on some other threads and this did send data over UART successfully.

2. i uncomment

#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_OSC0 

in conf_clock.h and

 

3. added

#ifndef USER_BOARD_H
#define USER_BOARD_H

/* This file is intended to contain definitions and configuration details for
 * features and devices that are available on the board, e.g., frequency and
 * startup time for an external crystal, external memory devices, LED and USART
 * pins.
 */

#define BOARD_OSC0_HZ             16000000 
#define BOARD_OSC0_TYPE           XOSC_TYPE_XTAL 
#define BOARD_OSC0_IS_XTAL        true 
#define BOARD_OSC0_STARTUP_US     17000 

#endif // USER_BOARD_H

to the user_board.h

 

Question from these is that:

1. changing the values of BOARD_OSC0_HZ always give errors, not matter the buadrate used. Does this imply that I can not run UART above/below 16MHz?

 

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

NEW UPDATES AND REQUEST FOR HELP

I found it hard/impossible to send data over UART to rasp pi if the format is not strings enclosed in "", as shown in the code line below:

usart_write_line(USART, "4C\n"); // working with rpi

But the data I need to send over the UART will be in hex or bin formats and are in the elements of an array. The data structure are formed from the ADC of the mcu, and as shown in the code below:

    uint8_t IQsamples[77];
//	uint8_t SFCWsamples[121];
	IQsamples[0] = 0x4C;
//	SFCWsamples[0] = 0x78;
	
	int j;
	int k;
	int singletone;
//	int SFCW;
	
	
	//sensor1
	//cpu_delay_us(500, 3*BOARD_OSC0_HZ);
	//sensor2
	//cpu_delay_us(20000, 3*BOARD_OSC0_HZ);
	//sensor3
	//cpu_delay_us(40000, 3*BOARD_OSC0_HZ);	
		
while(1){



		//sensor2
		IQsamples[1] = 0x02;
		TxBits(0x5, calibration[41]);
		TxBits(0x3, 0x0000001D);
		TxBits(0x4, 0x00400000);
		cpu_delay_us(15000, 3*BOARD_OSC0_HZ);
		

		
	
while(1){
	

		for(singletone=0;singletone<20;singletone++){
		
			AVR32_GPIO.port[0].ovrc = 1 <<6;	// Switch connected to Radar
			cpu_delay_us(1000, 3*BOARD_OSC0_HZ);
			k=2;
			
			// Acquires and maps the 25 IQ samples in 75 bytes. A single IQ sample requires 20 bits and is mapped in 3 bytes.
			// A special mapping is applied to avoid more then 8 consecutive zero. This will generate and error for the USART.
			for(j=0;j<25;j++){


//				TxBits(0x5,0x00000F88); // VCO Subsystem 3 - enable RF output stage
//				cpu_delay_us(1000, 3*BOARD_OSC0_HZ);
				
				// launch conversion on all enabled channels
				adc_start(adc);

				// Acquire the I/Q channels
				Isample = adc_get_value(adc, I_CHANNEL);
				Qsample = adc_get_value(adc, Q_CHANNEL);

				// Creating byte 1
				temp1=0x8000;
				temp2 =((Isample & 0x00000300) << 5 );
				temp1=(temp1 | temp2);
				temp1= ((temp1 | 0x1000) >> 8  );
				temp2=((Isample & 0x000000F0) >> 4);
				IQsamples[k] = (uint8_t)(temp1 | temp2);
				
				// Creating byte 2
				temp1 =((Isample & 0x0000000F) << 4 );
				temp1= (temp1 | 0x08);
				temp2= ((Qsample & 0x380) >> 7);
				IQsamples[k+1] = (uint8_t)(temp1 | temp2);
				
				// Creating byte 3
				temp1=0x80;
				temp2= ((Qsample & 0x7F));
				IQsamples[k+2] = (uint8_t)(temp1 | temp2);
				
//				TxBits(0x5,0x00000D88); // VCO Subsystem 3 - disable RF output stage

				if (k<75) {					
					cpu_delay_us(4000, 3*BOARD_OSC0_HZ);
				}
								
				k=k+3;
		
			}

 

 

Any suggestions on how I can send hex or bin over UART and how to send each element of the array one after the other? Much help needed. Thanks in advance.

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

See post #29

A 'C' string is a sequential array of bytes and the 'end' of that string is indicated by a byte with a value of zero.

Your

usart_write_line(USART, "4C\n"); // working with rpi

will produce (somewhere in memory), the following 4 byte sequence ; (decimal) 52, 67, 10, 0,  ?, ... ?  (= hexadecimal values 0x34, 0x43, 0x0A, 0x00,  ?, ... ?)

 

usart_putchar(,) will transmit one byte, and the value of that byte will be the value that is in the byte that you give it., so a simple loop through the 75 bytes of IQsamples[] will do the job.

 

 

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

In the mode that you are using the USART the maximum baudrate will be the system clock frequency divided by either 16 or 8.

 

What errors ?

Is the compiler complaining about undefined/undeclared values ? (Check that user_board.h is #included before conf_clock.h )

or are you receiving garbage at the RPi because the AVR32 baudrate is incorrect ?

Note that with a system clock of 16 MHz you will probably not get an exact baudrate match with the RPi. (see post #22)

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

mikech,

 

It's been one trouble over another. with some configurations in conf_clock.h, the USART transmit correctly, with some other (in line with the previous codes I have), it does not transmit anything at all, or displays unreadable ASCII characters.

 

But one I need clarification on is this- why does it seem USART only works when my OSC0 or BOARD_OSC0_HZ is 16MHz. This i have found to be the case in all my configurations.

 

As well, I am trying to use the PLL0 and not the OSC0 for the clocking of the board, and it is expected that OSC0 be the source of my PLL0-

#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_PLL0

//#define CONFIG_PLL0_SOURCE          PLL_SRC_OSC0
//#define CONFIG_PLL0_SOURCE          PLL_SRC_OSC1

 

works on my board. But this does not

#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_PLL0

#define CONFIG_PLL0_SOURCE          PLL_SRC_OSC0
//#define CONFIG_PLL0_SOURCE          PLL_SRC_OSC1

 

Can you please give me any hint why this may be so? Where else is the PLL getting it source when neither OSC0 nor OSC1 is used as source?

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

"why does it seem USART only works when my OSC0 or BOARD_OSC0_HZ is 16MHz." is hard to answer because i don't know what baudrate you are trying to use now.
(BOARD_OSC0_HZ should be what the actual oscillator frequency is.., arbitrarily changing the #define is not recommended).


The ASF sysclk_init() tries to be a 'one-stop-shop' in terms of setting-up the clocks and it does that via a plethora of #defines .
The system clock on the UC3A and UC3B can only come from OSC0, PLL0 or RCOSC (default).
PLL0 can be fed from OSC0 or OSC1.


#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL0
//#define CONFIG_PLL0_SOURCE PLL_SRC_OSC0
will instruct sysclk_init() to not configure any clock (look at the code), therefore you are still running off the default RCOSC (115 kHz) and that will restrict the maximum usart baudrate.


#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL0
#define CONFIG_PLL0_SOURCE PLL_SRC_OSC0
will require that suitable values for CONFIG_PLL0_MUL and CONFIG_PLL0_DIV are defined.
What should those values be ?, well, what system-clock frequency do you want ?

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

"why does it seem USART only works when my OSC0 or BOARD_OSC0_HZ is 16MHz." is hard to answer because i don't know what baudrate you are trying to use now.
(BOARD_OSC0_HZ should be what the actual oscillator frequency is.., arbitrarily changing the #define is not recommended).

My baudrate is 115200, and even when I vary this values, I still receive the correct data on the receiver (RealTerm), as long as my frequency is 16MHz.

 

#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLL0
//#define CONFIG_PLL0_SOURCE PLL_SRC_OSC0

I do not expect this to work as well, surprisingly it works. here is the code in my main.c:

static void setMainClock(void)
{
    
    //// Enable the external Osc0 of 16Mhz
    pm_enable_osc0_crystal(&AVR32_PM, FOSC0);
    //pm_enable_osc1_crystal(&AVR32_PM, FOSC1);
    pm_enable_clk0(&AVR32_PM, 0x00000003);
    //
    ////Enable the PLL at 128 MHz
    pm_pll_setup(&AVR32_PM,
    0,					// PLL0
    //2,					// Fpll0 = Fclk * 2 * (PLL_mul+1), if DIV=0 //CONFIG_PLL0_MUL //default
    /*an mul=2. actually gives a 96Mhz, to get 128Mhz, mul should be 3*/
    
    1,					// Fpll0 = Fclk * 2 * (PLL_mul+1), if DIV=0 //CONFIG_PLL0_MUL
    0,	// DIV = 0 //default
    //1,	// DIV = 0	//gives divide by 2
    0,					// OSC0
    16);				// lockcount in main clock for the PLL wait lock
    //
    //////PLL output VCO frequency at 64MHz
    pm_pll_set_option(&AVR32_PM, 0, 0, 1, 0);
    //
    //////Enable PLL0
    pm_pll_enable(&AVR32_PM, 0);
    //
    ///////Wait for PLL0 locked
    pm_wait_for_pll0_locked(&AVR32_PM) ;
    //
    //////Set PBA and PBB clocks by 2 from main clock at 32 MHz
    pm_cksel(&AVR32_PM, 1, 0, 1, 0, 0, 0); //default
    //pm_cksel(&AVR32_PM, 0, 0, 0, 0, 0, 0);
    //
    //////Set PLL0 as main clock to 64MHz
    pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCSEL_PLL0); //default
    //
    ////main clock at 16Mhz?
    //pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCSEL_OSC0); 
    
    
}

static void local_start_gc(void)
{
    
    // setup a generic clock
    pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK0,
    1,  // Use Osc (=0) or PLL (=1), here PLL //default
    //0,  // Use Osc (=0) or PLL (=1), here OSC0
    0,  // Sel Osc0/PLL0 or Osc1/PLL1 //default
    //1,  // Sel Osc0/PLL0 or Osc1/PLL1
    0,  // disable divisor
    0); // no divisor

    /* Enable Generic clock */
    pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK0);
    
    /* Set the GCLOCK function to the GPIO pin */
    gpio_enable_module_pin(7, 1);//PA07
    
    
}
int main (void){
    // Insert system clock initialization code here (sysclk_init()).
	sysclk_init();

	board_init();
	
	setMainClock();
	
	local_start_gc();
    
}

 

 

 

 

when I run setMainClock and change the values of the mul and div, I could get frequencies as high as  96-128Mhz, and on monitoring on PA07 to which the generic clock is connected, I could see the frequency of the PLL (48/64Mhz) or the OSC (16Mhz), depending on what generator I choose with generic clock parameters. Question still remains, why does this work? indecision

 

1. If I had been running on the default RCOSC, would it have been possible to achieve a 96-128Mhz using CONFIG_PLL0_MUL and CONFIG_PLL0_DIV in pm_pll_setup? I am confused, please give me some insights.

 

2. A side question- is it possible to configure more than one (generic) clock on my mcu? Such that I leave one clock for some part of the system (so as not to mess with former settings of my custom board/mcu, running at say 48/64 or 96/128MHz) and have another clock for my USART (especially now that it chose to run at 16Mhz)

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

A1:
RCOSC cannot be connected to the PLLs.
Look at the "Power Manager block diagram" in the Power Manager (PM) section to see what connections are possible.


A2:
The "Synchronous Clock Generator" generates 4 clocks ; CPU, HSB, PBA and PBB clocks and it is fed from OSC0, PLL0 or RCOSC.
The "Maskable Module Clocks in AT32UC3A" table shows that all the USART modules are fed from the PBA clock. You cannot change that.
The Generic clocks are fed directly from OSC0, OSC1, PLL0 or PLL1.
The "Signals Descriptions List" table shows that there are 4 independent generic-clocks on the UC3A ; GCLOCK0 .. GCLOCK3, which appear in the "GPIO Controller Function Multiplexing" table as ; GCLK[0] .. GCLK[3].
All of the GCLK[x] functions on the UC3A are available on 2 different pins (see GPIO multiplexing table).



Why are you setting-up the clocks twice ???
Your setMainClock() will overwrite whatever the ASF sysclk_int() does.
The CONFIG_PLL0_MUL and CONFIG_PLL0_DIV #defines are used by sysclk_int() but not by pm_pll_setup()
The pm_pll_setup() appears to be using a PLL multiplier of 1 and a divisor of 0., so with OSC0 = 16 MHz that will produces a Fvco frequency of 2(1+1)*16 MHz = 64 MHz,
then the pm_pll_set_option() divides that 64 MHz Fvco by 2,
and then the pm_cksel() divides that by 2 which means that the clock to the USARTs is now 16 MHz !


The CPU/HSB/PBA/PBB clocks on the UC3A can run at 66 MHz.
The main reason for running the clocks slower is to reduce power-consumption.

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

@mikech, thanks so much for the insights. you're awesome!

Here are my updates:

1. sysclk_int() does indeed mess with my setMainClock(); so I didn't make a call to it, and was then able to use:

 

#define CONFIG_SYSCLK_SOURCE        SYSCLK_SRC_PLL0

#define CONFIG_PLL0_SOURCE          PLL_SRC_OSC0

 

2. USART works as well but ONLY when my PLL0 is not above 32MHz, and my OSC0 at 16MHz. My baudrate is 115200. At a different freq for PLL0, (text) data displayed by REalTerm (USART monitor) is unintelligible.

 

Now I was thinking, what will be the effect of this lower frequency on general board performance- other part of the board are for ADC, and programming an external waveform source. The initial board designer intended to run VCO at 128MHz but his code showed he did at 96MHz. His comment was that "The sensor can operate at both frequencies. You can pick one. At 64 MHz (of PLL0) of course the micro performs the instructions faster."

 

Now that my VCO is at 64, and PLL0 at 32MHz how fast/slow will slow be? I will experiment with this, and give some updates. Meanwhile, what do you think?

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

Higher system-clock speeds increase the computing-performance but will also increase the power consumption.
For your application the system clock-speed will depend on what the project requirements are, such as ;
- how fast do you need to acquire the ADC samples ? (note that the ADC has its' own speed limit).
- is power-consumption an issue ?
- are you using a lot of interrupts ?
Me ?., I generally run the system-clocks fast., it depends on the crystal but usually in the 55 to 60 MHz region.


I'm not sure why the USART only works with such a low PLL frequency, the datasheet says that a PLL fvco of less than 80 MHz is too low. :very puzzled:


What frequency are you using to initialise the USART with ?
The USART is fed from the PBA clock and that is the frequency that you should give to the ASF usart_init_rs232()



Try this experiment ;
1: comment-out the call to sysclk_init() and un-comment the call to setMainClock()
now., in setMainClock() ;
2: add a flashc_set_wait_state( 1 ); at the start., ie. before the PLL is selected to be the system clock. (**)
3a: change pm_pll_setup() to pm_pll_setup( &AVR32_PM, 0, 4-1, 0, 0, 16 ) (PLL0, multiplier of 4, divisor of 0, OSC0, 16 slow-clocks for settling)
3b: change pm_pll_set_option() to pm_pll_set_option( &AVR32_PM, 0, 1, 1, 0 ) (PLL0, frequency-band 80-180Mhz, divide fvco by 2, wideband mode)
3c: comment-out the pm_cksel() or set it to pm_cksel( &AVR32_PM, 0, 0, 0, 0, 0, 0 ) to not divide the CPU, HSB, PBA, PBB clocks.
That should set the PLL fvco to be 128 MHz and the bus-clocks to the CPU and USART to be 64 MHz.


(**) When the PBB clock is above about 33 MHz you need to tell the FLASHC module to add 1 wait-state for its' read operations.
If you use the ASF sysclk_init() it will call flash_set_bus_freq() which will eventually call flashc_set_wait_state( x )

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

What frequency are you using to initialise the USART with ?

I think I am giving it the OSC0 frequency by using the following:

#define TARGET_PBACLK_FREQ_HZ	BOARD_OSC0_HZ

What is the function to make

The USART is fed from the PBA clock and that is the frequency that you should give to the ASF usart_init_rs232()

happen? I am not sure of myself here.

 

For the experiment, my code is as follows:

#define USART				(&AVR32_USART3)
#define TARGET_PBACLK_FREQ_HZ	BOARD_OSC0_HZ
#define USART_RX_PIN		AVR32_USART3_RXD_0_0_PIN
#define USART_RX_FUNCTION	AVR32_USART3_RXD_0_0_FUNCTION
#define USART_TX_PIN		AVR32_USART3_TXD_0_0_PIN
#define USART_TX_FUNCTION	AVR32_USART3_TXD_0_0_FUNCTION

/////experiment from @mikech

static void setMainClock(void)
{	
	
	
	//add a flashc_set_wait_state( 1 ); at the start., 
	//ie. before the PLL is selected to be the system clock. (**)
	
	flashc_set_wait_state(1);
		
	//// Enable the external Osc0 of 16Mhz
	pm_enable_osc0_crystal(&AVR32_PM, FOSC0);
	//pm_enable_osc1_crystal(&AVR32_PM, FOSC1);
	pm_enable_clk0(&AVR32_PM, 0x00000003);
	//
	
	// change pm_pll_setup() to pm_pll_setup( &AVR32_PM, 0, 4-1, 0, 0, 16 )
	// (PLL0, multiplier of 4, divisor of 0, OSC0, 16 slow-clocks for settling)
	
	
	////Enable the PLL at 128 MHz
	pm_pll_setup(&AVR32_PM,
	0,					// PLL0
	//2,					// Fpll0 = Fclk * 2 * (PLL_mul+1), if DIV=0 //CONFIG_PLL0_MUL //default
	/*an mul=2. actually gives a 96Mhz, to get 128Mhz, mul should be 3*/
	
	//1,					// Fpll0 = Fclk * 2 * (PLL_mul+1), if DIV=0 //CONFIG_PLL0_MUL
	4-1, //mul of 4-1 or 3
	0,	// DIV = 0 //default
	//1,	// DIV = 1	//gives divide by 2
	0,					// OSC0
	16);				// lockcount in main clock for the PLL wait lock
	
	////change pm_pll_set_option() to pm_pll_set_option( &AVR32_PM, 0, 1, 1, 0 )
	////(PLL0, frequency-band 80-180Mhz, divide fvco by 2, wideband mode)
	//
	//////PLL output VCO frequency at 64MHz
	//pm_pll_set_option(&AVR32_PM, 0, 0, 1, 0);
	pm_pll_set_option(&AVR32_PM, 0, 1, 1, 0);
	//
	//////Enable PLL0
	pm_pll_enable(&AVR32_PM, 0);
	//
	///////Wait for PLL0 locked
	pm_wait_for_pll0_locked(&AVR32_PM) ;
	//
	//////Set PBA and PBB clocks by 2 from main clock at 32 MHz
	//pm_cksel(&AVR32_PM, 1, 0, 1, 0, 0, 0); //default
	pm_cksel(&AVR32_PM, 0, 0, 0, 0, 0, 0);
	//
	//////Set PLL0 as main clock to 64MHz
	pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCSEL_PLL0); //default
	//
	////main clock at 16Mhz?
	//pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCSEL_OSC0); 
	
	
}
//
//
static void local_start_gc(void)
{
	
	// setup a generic clock
	pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK0,
	1,  // Use Osc (=0) or PLL (=1), here PLL //default
	//0,  // Use Osc (=0) or PLL (=1), here OSC0
	0,  // Sel Osc0/PLL0 or Osc1/PLL1 //default
	//1,  // Sel Osc0/PLL0 or Osc1/PLL1
	0,  // disable divisor
	0); // no divisor

	/* Enable Generic clock */
	pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK0);
	
	/* Set the GCLOCK function to the GPIO pin */
	gpio_enable_module_pin(7, 1);//PA07
	
	
}


int main(void){
 
 	// char for USART
	uint8_t IQsamples[3];
	
	//IQsamples[0] = 0b10110111;
	//IQsamples[1] = 0b11001111;
	//IQsamples[2] = 0b10110011;
	
	IQsamples[0] = 'b';
	IQsamples[1] = 'i';
	IQsamples[2] = 'm';
	
	int n;
	
    // Insert system clock initialization code here (sysclk_init()).
	
	
	//sysclk_init();
	
	setMainClock();
	
	local_start_gc();

	board_init();
	
	
	
	static const gpio_map_t USART_GPIO_MAP =
	{
		{USART_RX_PIN, USART_RX_FUNCTION},
		{USART_TX_PIN, USART_TX_FUNCTION}
	};
	
		// USART options.
		static const usart_options_t USART_OPTIONS =
		{
			.baudrate     = 115200,
			//.baudrate     = 57600,
			//.baudrate     = 9600,
			//.baudrate     = 1200,
			.charlength   = 8,
			.paritytype   = USART_NO_PARITY,
			.stopbits     = USART_1_STOPBIT,
			.channelmode  = USART_NORMAL_CHMODE
		};

		// Assign GPIO to USART.
		gpio_enable_module(USART_GPIO_MAP,
		sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

	// Insert application code here, after the board has been initialized.
	
		//usart_init_rs232(USART, &USART_OPTIONS, BOARD_OSC0_HZ);
		usart_init_rs232(USART, &USART_OPTIONS, TARGET_PBACLK_FREQ_HZ);
		//usart_init_rs232(USART, &USART_OPTIONS, sysclk_get_cpu_hz());
		//usart_init_rs232(USART, &USART_OPTIONS, 16000000);
		
		
		while(1){
			usart_write_line(USART, "hello\r\n");
			//
			//for (n=0; n<3; n++)
			//{
				////usart_write_char(USART,"\n" );
				//usart_putchar(USART, IQsamples[n]);
				////usart_write_char(USART, "\n");
			//}//for
			//
		}//while
		
    }

Observations:

1. OSC0 runs at 16MHz. PLL0 at 64MHz

2. ASCII characters on USART 'monitor' is in attachment. I was expecting to see hello across my screen.

Attachment(s): 

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

BOARD_OSC0_HZ is 16000000 which is the frequency of the external crystal connected to OSC0.
From the code in post #41 the output from PLL0 is 64 MHz and that is what will be going to the USART on the PBA clock.
Therefore TARGET_PBACLK_FREQ_HZ should now be ( BOARD_OSC0_HZ * 4 )


You desire a particular baudrate from the USART, but the USART has a prescaler and a divider connected to the PBA clock, therefore usart_init_rs232(,,); needs to know the actual PBA frequency to correctly calculate the baudrate.
If TARGET_PBACLK_FREQ_HZ is defined as BOARD_OSC0_HZ (16 MHz) but the actual PBA frequency is 64 MHz then the baudrate from the USART will be 16/4 times faster than what you wanted.

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

Much thanks for the tips. Now I really understand what I am doing: if I have to use pm_cksel(1,0,1,0,0,0) which will divide f_PBA further by 2, I should give usart_init_rs232(**,BOARD_FREQ_HZ*2). I appreciate your patience in guiding me. God bless.

 

PS- I stopped calling flashc_set_wait_state(1);. What do I risk doing such?

 

 

New challenge:

I created an array of characters(?), such as below:

////// data over USART /////////

	uint8_t IQsamples[4];
	//char IQsamples[4];
	
	//IQsamples[0] = 0b10110111;
	//IQsamples[1] = 0b11001111;
	//IQsamples[2] = 0b10110011;
	//IQsamples[1] = 0b11001101;
	
	
	IQsamples[0] = 'R';
	IQsamples[1] = 'P';
	IQsamples[2] = 'i';
	IQsamples[3] = '\r';
	
	int n;
	
	//while(1){
			//usart_write_line(USART, "hello RPi\r\n");
			////usart_write_line(USART, "1234\r\n");
			//usart_write_line(USART, "b\r\n");
			//usart_write_char(USART,"12\n" );
			
			for (n=0; n<4; n++)
			{
				usart_putchar(USART, IQsamples[n]);
				
			}//for
			////
	//}//while

 

Using RealTerm to monitor the USART RXD/TXD lines, I could change the display to different character formats- ASCII, BIN, HEX, INT, etc. My observation is that if the display is not intelligible characters (ie A-Z, 0-9) in the ASCII display, the RPi does not log such that- they all get dropped. But as long as data is normal alphabets, they get logged/displayed by the RPi- using a python script here.

 

In the above code, I could send "RPi\r", but not 0b101...... As their ascii values are not represented by A-z, but when 'viewed' on RealTerm as BIN or HEX, I see correct data values.

 

This makes me wonder, is it that UART on RPi only accept strings? If so, how do I convert my DEC,BIN and HEX values to strings.

Though I figure that a problem will arise here, on the RPi end, I will need to have another script to (immediately) convert strings to DEC before logging. Is this even feasible?

 

Sir, what am I missing this time? Looking forward to reading from you.

 

 

 

 

 

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

 

Since you've solved your uart clocking problem, your current problem has little to do with the uarts on both ends, but more about strings and how data is represented. The uarts themselves do not concern themselves with strings or data representation - they merely pass values. It is up to each end to determine what these values represent.

 

If you want to send binary data, then you'll need to ensure you write the python script to accept this. Then you have to ask the question - do you really want to send binary data? Or are you happy with sending a human readable representation? The main reason for sending binary is it is more compact - less bytes to send so it is faster. If speed is not super critical, then send your data as human readable. Read up on the C print formatting functions like sprintf(). Also read up on C string representation as I can forsee you making some fundamental errors otherwise.

 

For data logging, a popular method of sending data is 'comma delimited'. Programs like Excel can load this data so you can print pretty graphs etc. It looks something like this:

12345,23,65,99<CR>

 

#define NUM_IQ 4

char buff[10];//can hold a string of no more than 9 chars!

for (int a = 0; a < NUM_IQ; a++)
{
    sprintf(buff,"%d,",IQ_samples[a]);
    uart_write_line(USART,buff);
}
uart_write_line(USART,"\n");

Hopefully the above should get you going. Any questions about sprintf() - it's standard C, so there's a zillion references on the interwebs.

 

If you REALLY want to send binary data, you'll need to think how you'll align it. Given a stream of characters, how do you know what is the start and end? With my sample code, the carriage return "\n" signals the end of the line - this is a standard convention that goes back to the days of the teletype. - but this does not work with binary data, as the value 0x0d which represents a carriage return might be valid binary data representing a value of 13. There's a number of ways you can 'frame' binary data - escaping is a common technique. Say our magic start token is the value 0x5e. If the value 0x5e appears in our data, we follow it with a 0xff. The other end needs to unescape the data to restore the original values. By doing this we can have the value 0x5e act as a start token. Thus we can determine the start of the data. How do we determine the length of the data? I'll leave this for you to ponder. Nevertheless, sending binary data is very common and there's plenty written about it.

 

Last Edited: Sun. Oct 22, 2017 - 09:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi @Kartman. Thanks for your contribution. I had been wondering if it was only myself and @mikech that were on this thread. Then you showed up with this cool response. Permit me to say "posters from Australia are awesome! wink"

Also read up on C string representation as I can forsee you making some fundamental errors otherwise.

I can't agree less with the above observation. I found two problems- clocking and data representation. And yes, there are fundamental errors in my data representation. I'm gonna use your tips and hopefully get them restored. Expect my updates.

My actual data will be outputs of the ADC of the mcu, I figure they will be best represented as decimals on the mcu part.

Read up on the C print formatting functions like sprintf()

I started out with sprintf(); before now, and seems I could not call it until I have #included some libraries. In all, expect my updates.

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

obabarin wrote:
and seems I could not call it until I have #included some libraries.
That would be:

#include <stdio.h>

which is not a "library". It's a library header. The connection to the "library" comes at link time. Almost all C compilers (unless asked not to) do an implied -lc which means "link with libc.a". It provides functions such as sprintf() if they are called.

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

Apologies for the misuse of terminologies there. I do mean library header and not library. I will ensure to #include all necessary headers.

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

I had previously kept quiet as I have no experience with AVR32. They are not particularly popular, so that's why you don't get many responses.

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

obabarin wrote:
I do mean library (sic) header

Note that a header is a header - there is no difference between a "library header" and any other header.

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

Hello everyone,

 

I will like to give some updates about my progress, and welcome your inputs again. This will be a long post- please endure with me.

 

I am trying to perform ADC on my mcu, having been able to configure clocking with the PLL and send data over USART. board_init is defined in the init.c file as below:

//

#include "board.h"
#include "conf_board.h"
#include "gpio.h"
#include "adc.h"
//#include "spi.h"
#include "usart.h"


void board_init(void)
{

	//USART definitions

	static const gpio_map_t USART_GPIO_MAP =
	{
		
		{42,	1	},				//RXD
		{43,	1	},				//TXD
		
		
		
		//{USART_RX_PIN, USART_RX_FUNCTION},
		//{USART_TX_PIN, USART_TX_FUNCTION}
	};

	// Assign GPIO to USART.
	gpio_enable_module(USART_GPIO_MAP,
	sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

///////ADC configuration

	// GPIO pin/adc-function map.
	static const gpio_map_t ADC_GPIO_MAP =
	{
		#if defined(I_CHANNEL)
	{ADC_PIN_I, ADC_PIN_I_FUNCTION},
		#endif
		#if defined(Q_CHANNEL)
	{ADC_PIN_Q, ADC_PIN_Q_FUNCTION},
		#endif
	};

	// Assign and enable GPIO pins to the ADC function.
	gpio_enable_module(ADC_GPIO_MAP, sizeof(ADC_GPIO_MAP) / sizeof(ADC_GPIO_MAP[0]));

	/////// --------------------------
}//init

It is intended to digitized and then transmit over USART signals denoted as I and Q samples from a Baseband Amplifier.

 

main.c content is as follows:

 

#include <asf.h>

#include <avr32/io.h>
//#include "compiler.h"
#include "board.h"
//#include "power_clocks_lib.h"
#include "gpio.h"
#include "usart.h"

#include <asf.h>
#include <stdint.h>
#include <stdbool.h>
#include "stdio.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>


#include <asf.h>
#include <parts.h>
#include <stdint.h>
#include <stdbool.h>
#include "stdio.h"
#include "gpio.h"
#include "sysclk.h"
#include "conf_clock.h"
#include "board.h"
#include "conf_board.h"
#include "user_board.h"
#include "board.h"
#include "gpio.h"
#include "pm.h"
#include "adc.h"
//#include "spi.h"
#include "delay.h"
#include "usart.h"



////defines
#define USART				(&AVR32_USART3)

#define AVR32_SCIF_OSCCTRL0_STARTUP_2048_RCOSC	0x00000003


//Data formatting
//#define NUM_IQ			4
#define NUM_IQ			75



//Global variable declarations
int Nm[4][32];

uint32_t Target_VCO_CAP_Address = 0;
uint32_t calibration[41];
double	Ftune = 0.0;


//Variables to store I/Q samples

#if defined(I_CHANNEL)
unsigned long Isample = 1;
#endif

#if defined(Q_CHANNEL)
unsigned long Qsample = 1;
#endif

unsigned long temp1 = 1;
unsigned long temp2 = 1;

///////-------------

static void setMainClock(void){

//// Enable the external Osc0 of 16Mhz
pm_enable_osc0_crystal(&AVR32_PM, FOSC0);
//pm_enable_osc1_crystal(&AVR32_PM, FOSC1);
pm_enable_clk0(&AVR32_PM, 0x00000003);

////Enable the PLL at 128 MHz
pm_pll_setup(&AVR32_PM,
0,					// PLL0

3,					// Fpll0 = Fclk * 2 * (PLL_mul+1), if DIV=0 //CONFIG_PLL0_MUL
//4-1, //mul of 4-1 or 3
0,	// DIV = 0 //default
//1,	// DIV = 1	//gives divide by 2
0,					// OSC0
16);				// lockcount in main clock for the PLL wait lock

pm_pll_set_option(&AVR32_PM, 0, 1, 1, 0);
//
//////Enable PLL0
pm_pll_enable(&AVR32_PM, 0);
//
///////Wait for PLL0 locked
pm_wait_for_pll0_locked(&AVR32_PM) ;
//
//////Set PBA and PBB clocks by 2 from main clock at 32 MHz
pm_cksel(&AVR32_PM, 1, 0, 1, 0, 0, 0); //default
//pm_cksel(&AVR32_PM, 0, 0, 0, 0, 0, 0);
//
//////Set PLL0 as main clock to 64MHz
pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCSEL_PLL0); //default
//

}//setMailclock


//
//
static void local_start_gc(void)
{

// setup a generic clock
pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK0,
//1,  // Use Osc (=0) or PLL (=1), here PLL //default
0,  // Use Osc (=0) or PLL (=1), here OSC0
0,  // Sel Osc0/PLL0 or Osc1/PLL1 //default
//1,  // Sel Osc0/PLL0 or Osc1/PLL1
0,  // disable divisor
0); // no divisor

/* Enable Generic clock */
pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK0);

/* Set the GCLOCK function to the GPIO pin */
gpio_enable_module_pin(7, 1);//PA07


}//local_start_gc



int main(void){
	
	AVR32_GPIO.port[0].ovrc = 1 <<6;	// permanently disable zigbee, enable radar
	
	uint8_t IQsamples[75]; //array to store IQsamples
	
	//IQsamples[0] = 0x4B; //first element of IQsamples
	
	int j;
	int k;
	int singletone;
	
	char IQbuff[75]; //buffer to hold 75 digitized IQsamples
	
	setMainClock();
	
	local_start_gc();
	
	volatile avr32_adc_t *adc = &AVR32_ADC;
	
	board_init();
	
	////ADC options
	AVR32_ADC.mr |= 0x4 << AVR32_ADC_MR_PRESCAL_OFFSET; // ~ 4.8 MHz
	adc_configure(adc);
	
	// Enable the I/Q ADC channels.
	#if defined(I_CHANNEL)
	adc_enable(adc, I_CHANNEL);
	#endif
	#if defined(Q_CHANNEL)
	adc_enable(adc, Q_CHANNEL);
	#endif
	
	////USART options.
	static const usart_options_t USART_OPTIONS =
	{
	//.baudrate     = 115200,
	.baudrate     = 57600,
	//.baudrate     = 9600,
	//.baudrate     = 1200,
	.charlength   = 8,
	.paritytype   = USART_NO_PARITY,
	.stopbits     = USART_1_STOPBIT,
	.channelmode  = USART_NORMAL_CHMODE
	};
	
	usart_init_rs232(USART, &USART_OPTIONS, BOARD_OSC0_HZ*2); 
	
	cpu_delay_us(2000000, 4*BOARD_OSC0_HZ);
	
	//IQsamples[1] = 0x05;
	

while(1){//do adc
	
	
	for(singletone=0;singletone<20;singletone++){//for,1
	
	cpu_delay_us(1000, 3*BOARD_OSC0_HZ);
	k=2;
		for (j=0; j<25; j++){//for,2
			
			// launch conversion on all enabled channels
			adc_start(adc);
			
			// Acquire the I/Q channels
			Isample = adc_get_value(adc, I_CHANNEL);
			Qsample = adc_get_value(adc, Q_CHANNEL);
			
			// Creating byte 1
			temp1=0x8000;
			temp2 =((Isample & 0x00000300) << 5 );
			temp1=(temp1 | temp2);
			temp1= ((temp1 | 0x1000) >> 8  );
			temp2=((Isample & 0x000000F0) >> 4);
			IQsamples[k] = (uint8_t)(temp1 | temp2);
			
			// Creating byte 2
			temp1 =((Isample & 0x0000000F) << 4 );
			temp1= (temp1 | 0x08);
			temp2= ((Qsample & 0x380) >> 7);
			IQsamples[k+1] = (uint8_t)(temp1 | temp2);
			
			// Creating byte 3
			temp1=0x80;
			temp2= ((Qsample & 0x7F));
			IQsamples[k+2] = (uint8_t)(temp1 | temp2);
		}//for,2
		
			if (k<75){//if
				cpu_delay_us(4000, 3*BOARD_OSC0_HZ);			
			}//if
		k = k+3;
		
		
		////send IQsamples over usart
		
		//while(1){//test usart
			//usart_write_line(USART, "HELLO RPi");
			//usart_write_line(USART, "\r\n");
		//}//test usart
	
		
		
		while (1){//IQsamples over USART
			for (int a = 0; a < NUM_IQ; a++)
		{
		//sprintf(IQbuff,"%d;",IQsamples[a]);
		sprintf(IQbuff,"%x;",IQsamples[a]);
		//////
		usart_write_line(USART,IQbuff);
		}//for
		usart_write_line(USART,"\r\n");
		}//while
	
	
	}//for,1
	
	
}//while
	
}//main	
	


 

On the receiver end, the RPi, I have the following for displaying the content of received data over uart

 

#include <stdio.h>
#include <unistd.h>			//Used for UART
#include <fcntl.h>			//Used for UART
#include <termios.h>		//Used for UART

int main(int argc, char **argv){

///////code lines to open uart not shown///////
    
FILE*data;
const char *filename = "data.txt";
data = fopen(filename, "w");


while(1)
{
	if (uart0_filestream != -1)
	{
		// Read up to 255 characters from the port if they are there
		//unsigned char rx_buffer[256];
		unsigned char rx_buffer[75];
		//unsigned char rx_buffer[10];
		//int rx_length = read(uart0_filestream, (void*)rx_buffer, 255);		//Filestream, buffer to store in, number of bytes to read (max)
		int rx_length = read(uart0_filestream, (void*)rx_buffer, 75);
		
		if (rx_length < 0)
		{
			//An error occured (will occur if there are no bytes)
		}
		else if (rx_length == 0)
		{
			//No data waiting
		}
		else
		{
			//Bytes received
			rx_buffer[rx_length] = '\0';
			
			printf("%s", rx_buffer);
			
			
						
		}
    
    fclose(data);
	
////closing uart
////----- CLOSE THE UART -----
	close(uart0_filestream);
	
return 0;
    
}//main

I will like some feedback about these codes- am I missing anything?

On my RPi terminal, I could only see the following numbers across my screen

 

78;123;255;253;240;76;77;4;76;31;28;143;155;94;179;127;197;165;37;93;118;123;125;147;206;76;107;230;48;211;44;136;3;103;159;212;125;11;42;103;7;179;31;137;84;7;165;176;143;60;169;22;105;146;145;174;148;237;219;4;222;163;46;200;111;68;85;157;235;191;81;139;212;29;62;

I expect this number to be changing but they stay the same. This issue I suspect is related to the PLL/VCO (from Analog Devices, HMC834LPGE to be configured in OpenMode) on my board not configured properly yet. I will be looking into that later, and hopefully provide more updates.

 

Thank you everyone.