Society of Robots - Robot Forum

Software => Software => Topic started by: Max Web on May 17, 2012, 10:25:51 AM

Title: Webbot Lib and hardware UART
Post by: Max Web on May 17, 2012, 10:25:51 AM
Hi, I recently discovered the Webbot lib and right now I am facing my first problem getting a stupid Hello World program to work ;)
I'm using a custom board which I created with the Board Designer (it runs at 16 MHZ, so it says
Code: [Select]
# The processor speed
MCU_SPEED    = 16000000
in my makefile).

After successfully creating the board, I used the Project Generator to generate me a blank project which only uses a hardware UART.
My settings are: Hardware UART, receive buffer:100, send buffer:50, baudrate: 57600.
Then I wrote a program that sends "Hello World\r\n" over the generated UART about every second, but whenever I connect to my UART, I only receive the first char of my "Hello World", which is 'H'. This happens way faster than only every second... That's why I suspect that there's something messed up in the writer stuff...

I did not modify the code generated by the Project designer, all I did was writing this pretty simple stuff:
Code: [Select]
#include "hardware.h"

// Initialise the hardware
void appInitHardware(void) {
initHardware();
}
// Initialise the software
TICK_COUNT appInitSoftware(TICK_COUNT loopStart){
return 0;
}
// This is the main loop
TICK_COUNT appControl(LOOP_COUNT loopCount, TICK_COUNT loopStart) {
rprintf("Hello World!\r\n");
return 1000000;
}

The UART related stuff in hardware.h:
Code: [Select]
// ------------------- uart1 -------------------
extern MAKE_WRITER(uart1SendByte);
extern MAKE_READER( uart1GetByte);

// Create hardware UART uart1
extern HW_UART _uart1;
#define uart1 &_uart1
#define UART0 uart1

and the generated code in lib/lib_hardware.c:
Code: [Select]
/*
This file has been auto-generated by WebbotLib tools V1.1
** DO NOT MODIFY BY HAND **
*/
#ifndef _LIB_HARDWARE_C_
#define _LIB_HARDWARE_C_
#include "../hardware.h"
#  define USART0_RX_vect USART_RX_vect
#  define USART0_TX_vect USART_TX_vect

// ------------------- uart1 -------------------
// Make a transmit buffer for uart1
static unsigned char tx_uart1_Buf[50];
static cBuffer tx_uart1_Buffer = MAKE_BUFFER(tx_uart1_Buf);

// Make a receive buffer for uart1
static unsigned char rx_uart1_Buf[100];
static cBuffer rx_uart1_Buffer = MAKE_BUFFER(rx_uart1_Buf);


// Create a routine to write bytes to uart1
// You can set rprintf to use it by calling rprintfInit(&uart1SendByte)
MAKE_WRITER(uart1SendByte){
return uartSendByte(uart1,byte);
}

// Create a routine to read a byte from uart1
// Returns -1 if there was no data
MAKE_READER( uart1GetByte){
return uartGetByte(uart1);
}

// Create hardware UART uart1
HW_UART _uart1 = MAKE_HW_UART_Rx_Tx(&rx_uart1_Buffer,&tx_uart1_Buffer,UCSRA,UCSRB,UBRRL,UBRRH,UDR,null,BV(U2X),D0,D1,&uart1GetByte,&uart1SendByte);

#ifndef USART0_TX_vect
# error Uart0 Tx complete vector undefined
#else
ISR(USART0_TX_vect){
uartTransmitService(uart1);
}
#endif

#ifndef USART0_RX_vect
# error Uart0 Rx complete vector undefined
#else
ISR(USART0_RX_vect){
uartReceiveService(uart1);
}
#endif

// ----------- Define the ADC channels ----------
const uint8_t NUM_ADC_CHANNELS = 8;

// ----------- My devices -----------------------
static int stream_put(char c, FILE* f){
Writer w = (Writer)fdev_get_udata(f);
return (w) ? w(c) : EOF;
}
static int stream_get(FILE* f){
Reader r = (Reader)fdev_get_udata(f);
return (r) ? r() : EOF;
}
static FILE _stdout_= FDEV_SETUP_STREAM(&stream_put,null,_FDEV_SETUP_WRITE);
static FILE _stdin_ = FDEV_SETUP_STREAM(null,&stream_get,_FDEV_SETUP_READ);
static FILE _stderr_= FDEV_SETUP_STREAM(&stream_put,null,_FDEV_SETUP_WRITE);

// ----------- Initialise built in devices ------
void sysInitHardware(void){
}

// ----------- Initialise my added devices ------
void initHardware(void){
setErrorLog(&uart1SendByte);
stderr = &_stderr_;
fdev_set_udata(stderr, &uart1SendByte);
rprintfInit(&uart1SendByte);
stdout = &_stdout_;
fdev_set_udata(stdout, &uart1SendByte);
stdin = &_stdin_;
fdev_set_udata(stdin, &uart1GetByte);
uartInit(uart1,57600);
}
// ----------- Register the statusLED -----------
void registerLED(void){
}

#endif

I hope that this is enough information to solve my problem....

Thanks in advance!

Max Web
Title: Re: Webbot Lib and hardware UART
Post by: Webbot on May 17, 2012, 11:45:00 AM
Send me your board design (ends in .brd), and project (.prj) and I'll take a look - the files will give me more info like which cpu your are using etc.
Also: let me know which version of WebbotLib you are using and a screen dump of the dialog from when you generate the project (so I can see settings like - where output is sent to, C or C++ etc)
Title: Re: Webbot Lib and hardware UART
Post by: Max Web on May 17, 2012, 12:05:24 PM
Hi,
unfortunately I can't send my board file here as the file size is restricted to 300kB, so I'll attach a screenshot of the program...
I'm using an ATMega32 running at 16 MHz

You can find my entire C project (generated files, *.prj file, makefile) in the zip file I attached.
the .prj file in projects/RP6Master/RP6Master.prj

I'm using Atmel AVR Studio 6 in combination with the C version of WebBot 2.09.

This is the compilation dialog:
Quote
------ Build started: Project: RP6Master, Configuration: Release AVR ------
Build started.
Project "RP6Master.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "D:\Program Files (x86)\Atmel\Atmel Studio 6.0\Vs\Compiler.targets" from project "D:\Max\Eigene Dokumente\AVR\WebBot\Projects\RP6Master\RP6Master.cproj" (target "Build" depends on it):
   Task "RunCompilerTask"
      D:\Program Files (x86)\Atmel\Atmel Studio 6.0\make\make.exe -C "D:\Max\Eigene Dokumente\AVR\WebBot\Projects\RP6Master" -f "makefile" all
      make: Entering directory `D:/Max/Eigene Dokumente/AVR/WebBot/Projects/RP6Master'
      avr-gcc -g -Wall  -DF_CPU=16000000 -mmcu=atmega32 -gdwarf-2 -fpack-struct -fshort-enums  -funsigned-char -funsigned-bitfields -I"../../../../../../webbotavrclib-2.09"  -MD -MP -MT RP6Master.o -MF dep/RP6Master.o.d  -std=gnu99  -Os -c -o RP6Master.o RP6Master.c
      avr-gcc -mmcu=atmega32 -Wl,-Map,RP6Master.map -o RP6Master.elf RP6Master.o  lib/lib_timerdef.o lib/lib_timers.o lib/gen_clock.o lib/lib_hardware.o lib/lib_iopins.o  -L"../../../../../../webbotavrclib-2.09" -L"lib" -lWebbot-ATmega32  -lPost -lm -lc
      avr-objdump -h -S RP6Master.elf > RP6Master.lst
      avr-objcopy -j .text -j .data -O ihex RP6Master.elf RP6Master.hex
      avr-objcopy -j .text -j .data -O binary RP6Master.elf RP6Master.bin
      avr-objcopy -j .text -j .data -O srec RP6Master.elf RP6Master.srec
      avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex RP6Master.elf RP6Master_eeprom.hex \
         || { echo empty RP6Master_eeprom.hex not generated; exit 0; }
      d:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
      avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary RP6Master.elf RP6Master_eeprom.bin \
         || { echo empty RP6Master_eeprom.bin not generated; exit 0; }
      d:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
      avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O srec RP6Master.elf RP6Master_eeprom.srec \
         || { echo empty RP6Master_eeprom.srec not generated; exit 0; }
      d:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
      avr-size --format=avr --mcu=atmega32 RP6Master.elf   
      AVR Memory Usage
      ----------------
      Device: atmega32
      Program:    5568 bytes (17.0% Full)
      (.text + .data + .bootloader)
      Data:        371 bytes (18.1% Full)
      (.data + .bss + .noinit)
      make: Leaving directory `D:/Max/Eigene Dokumente/AVR/WebBot/Projects/RP6Master'
   Done executing task "RunCompilerTask".
   Task "RunOutputFileVerifyTask"
      
      Display Output File Size Skipped due to : Output File not found
   Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "RP6Master.cproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "D:\Program Files (x86)\Atmel\Atmel Studio 6.0\Vs\Avr.common.targets" from project "D:\Max\Eigene Dokumente\AVR\WebBot\Projects\RP6Master\RP6Master.cproj" (entry point):
Done building target "Build" in project "RP6Master.cproj".
Done building project "RP6Master.cproj".

Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
Title: Re: Webbot Lib and hardware UART
Post by: Webbot on May 17, 2012, 01:50:05 PM
unfortunately I can't send my board file here as the file size is restricted to 300kB, so I'll attach a screenshot of the program...
I'm using an ATMega32 running at 16 MHz
But you CAN send it to me via the email link on my Avatar ie [email protected]

Quote
I'm using Atmel AVR Studio 6 in combination with the C version of WebBot 2.09.

Arrr(gh) yes. The Beta version of AVR Studio 6!  My advice would be to bin it and use WinAVR from sourceforge. That's what I test WebbotLib against - not sure what version of the gcc compiler gets used by AVR Studio 6
Title: Re: Webbot Lib and hardware UART
Post by: Max Web on May 17, 2012, 07:39:34 PM
Hi,

thanks for fixing the problem, it works perfectly now!

Just in case anybody else encounters this problem: There is a new Project Designer available on the website - it will fix the problem.
As it uses Java WebStart, it will probably auto-download the new version on the next start.

Max Web
Title: Re: Webbot Lib and hardware UART
Post by: Webbot on May 18, 2012, 12:06:21 PM
Just to explain the fix: it applied only to the ATMega32 where the name of the UART rx and tx interrupt vectors werewrong. Strangely the avr-gcc compiler lets this through with just a warning and installs the service routines in the wrong place. So I think the OPs code was sending the first character, the Tx complete interrupt happened, and it rebooted the chip - and so the first character kept being sent over and over.