Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Interrupt-driven Usart not working in Ada, but in C working, why?

275 views
Skip to first unread message

Rego, P.

unread,
Mar 16, 2014, 4:37:45 PM3/16/14
to
I am trying to use interrupt-driven Usart on an Atmel AVR ATmega2560 chip.

The problem is that when I send anything to the usart, the Ada application restarts (continuously). I simplified the codes and created a C version (or the nearer of it) of the same code (because at first I thought that it could be a hw problem or a datasheet misunderstanding of me, and AVR community would not answer me if I had posted Ada code instead of C code ...). But the C code worked (i.e., the usart echo appears, and the board is not restarted), ao now I became clueless. Maybe the AVR guys could help me? Thanks.

The simplified version of the codes are

-- main.adb
with System.Machine_Code;
with AVR.USART;
with TEST;
pragma Unreferenced (TEST);

procedure Main is
F_CPU : constant := 16_000_000;
USART_BAUDRATE : constant := 9600;
begin
AVR.USART.Reg_USART1.UCSRB.RXEN := True;
AVR.USART.Reg_USART1.UCSRB.TXEN := True;
AVR.USART.Reg_USART1.UCSRB.RXCIE := True;
AVR.USART.Reg_USART1.UCSRC.UCSZ0 := True;
AVR.USART.Reg_USART1.UCSRC.UCSZ1 := True;

AVR.USART.Reg_USART1.UBRR (0) := AVR.Byte_Type ((F_CPU / (USART_BAUDRATE * 16)) - 1);
AVR.USART.Reg_USART1.UBRR (1) := 0;

System.Machine_Code.Asm ("sei", Volatile => True);

loop
null;
end loop;
end Main;

-- test.ads
package TEST is

USART1RX : constant String := "__vector_36";

procedure Handle_Interrupt_USART1_RX;
pragma Machine_Attribute
(Entity => Handle_Interrupt_USART1_RX,
Attribute_Name => "signal");
pragma Export
(Convention => C,
Entity => Handle_Interrupt_USART1_RX,
External_Name => USART1RX);

end TEST;

with AVR;
with AVR.USART;

-- test.adb
package body Test is

procedure Handle_Interrupt_USART1_RX is
Curr_Buffer : AVR.Byte_Type;
begin
Curr_Buffer := AVR.USART.Reg_USART1.UDR;
AVR.USART.Reg_USART1.UDR := Curr_Buffer;
end Handle_Interrupt_USART1_RX;
end Test;


Given that I have mapped the Usart registers correctly on AVR.USART package (because my JtagICE said so).

The C code is
-- simple_isr_usart.c
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 16000000
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

int main (void){
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
UBRR0H = (BAUD_PRESCALE >> 8);
UBRR0L = BAUD_PRESCALE;
sei();
while (1) {}
}

ISR(USART0_RX_vect){
char ReceivedByte;
ReceivedByte = UDR0;
UDR0 = ReceivedByte;
}

Oliver Kleinke

unread,
Mar 16, 2014, 6:54:24 PM3/16/14
to
Am Sun, 16 Mar 2014 13:37:45 -0700 (PDT)
schrieb "Rego, P." <pvr...@gmail.com>:

> I am trying to use interrupt-driven Usart on an Atmel AVR ATmega2560
> chip.

Which compiler/version?

If you're using the GNU toolchain then you can use "(avr-)objdump -S"
to generate an assembly listing that's interspersed with source code.
(Compile with debugging symbols '-g'.)

You can then compare the disassembly of both programs.

> Given that I have mapped the Usart registers correctly on AVR.USART
> package (because my JtagICE said so).

Code?

Oliver Kleinke

unread,
Mar 16, 2014, 7:09:16 PM3/16/14
to
Am Sun, 16 Mar 2014 13:37:45 -0700 (PDT)
schrieb "Rego, P." <pvr...@gmail.com>:

> The problem is that when I send anything to the usart, the Ada
> application restarts (continuously).

This usually happens if you either blow the stack/heap or the PC
(program counter) overflows (reset/power on vector is at 0), e.g., if
the compiler optimizes away your main loop.

Rego, P.

unread,
Mar 16, 2014, 8:21:58 PM3/16/14
to
On Sunday, March 16, 2014 10:54:24 PM UTC, Oliver Kleinke wrote:
> Which compiler/version?
> If you're using the GNU toolchain then you can use "(avr-)objdump -S"
> to generate an assembly listing that's interspersed with source code.
> (Compile with debugging symbols '-g'.)
> You can then compare the disassembly of both programs.

`avr-gcc --version` answers me
avr-gcc (GCC) 4.5.4 20120510 for GNAT GPL 2012 (20120509)

I put the complete Ada objectdump part at http://is.gd/au08Fs. And the C part got from .lss in Atmel Studio I put in http://is.gd/qKpAuk.

Anyway, the handle parts in both assemblies give, for the Ada part:

procedure Handle_Interrupt_USART1_RX is
2e84: 1f 92 push r1
2e86: 0f 92 push r0
2e88: 0f b6 in r0, 0x3f ; 63
2e8a: 0f 92 push r0
2e8c: 00 90 5b 00 lds r0, 0x005B
2e90: 0f 92 push r0
2e92: 11 24 eor r1, r1
2e94: 2f 93 push r18
2e96: 8f 93 push r24
2e98: 9f 93 push r25
2e9a: ef 93 push r30
2e9c: ff 93 push r31
2e9e: df 93 push r29
2ea0: cf 93 push r28
2ea2: 0f 92 push r0
2ea4: cd b7 in r28, 0x3d ; 61
2ea6: de b7 in r29, 0x3e ; 62
Curr_Buffer : AVR.Byte_Type;
begin
Curr_Buffer := AVR.USART.Reg_USART1.UDR;
2ea8: 88 ec ldi r24, 0xC8 ; 200
2eaa: 90 e0 ldi r25, 0x00 ; 0
2eac: fc 01 movw r30, r24
2eae: 86 81 ldd r24, Z+6 ; 0x06
2eb0: 89 83 std Y+1, r24 ; 0x01
AVR.USART.Reg_USART1.UDR := Curr_Buffer;
2eb2: 88 ec ldi r24, 0xC8 ; 200
2eb4: 90 e0 ldi r25, 0x00 ; 0
2eb6: 29 81 ldd r18, Y+1 ; 0x01
2eb8: fc 01 movw r30, r24
2eba: 26 83 std Z+6, r18 ; 0x06
end Handle_Interrupt_USART1_RX;
2ebc: 00 00 nop
2ebe: 0f 90 pop r0
2ec0: cf 91 pop r28
2ec2: df 91 pop r29
2ec4: ff 91 pop r31
2ec6: ef 91 pop r30
2ec8: 9f 91 pop r25
2eca: 8f 91 pop r24
2ecc: 2f 91 pop r18
2ece: 0f 90 pop r0
2ed0: 00 92 5b 00 sts 0x005B, r0
2ed4: 0f 90 pop r0
2ed6: 0f be out 0x3f, r0 ; 63
2ed8: 0f 90 pop r0
2eda: 1f 90 pop r1
2edc: 18 95 reti

and for the C part:
ISR(USART1_RX_vect)
{
114: 1f 92 push r1
116: 0f 92 push r0
118: 0f b6 in r0, 0x3f ; 63
11a: 0f 92 push r0
11c: 11 24 eor r1, r1
11e: 0b b6 in r0, 0x3b ; 59
120: 0f 92 push r0
122: 8f 93 push r24
124: ef 93 push r30
126: ff 93 push r31
char ReceivedByte;
ReceivedByte = UDR1;
128: ee ec ldi r30, 0xCE ; 206
12a: f0 e0 ldi r31, 0x00 ; 0
12c: 80 81 ld r24, Z
UDR1 = ReceivedByte;
12e: 80 83 st Z, r24
130: ff 91 pop r31
132: ef 91 pop r30
134: 8f 91 pop r24
136: 0f 90 pop r0
138: 0b be out 0x3b, r0 ; 59
13a: 0f 90 pop r0
13c: 0f be out 0x3f, r0 ; 63
13e: 0f 90 pop r0
140: 1f 90 pop r1
142: 18 95 reti

> > Given that I have mapped the Usart registers correctly on AVR.USART
> > package (because my JtagICE said so).
> Code?

Basically (you can also access the complete from ... http://is.gd/X9qVns),

type USART_Control_And_Register_Status_Register_A_Type is
record
MPCM : Boolean; -- Multi-processor Communication Mode
U2X : Boolean; -- Double the USART Transmission Speed
UPE : Boolean; -- USART Parity Error
DOR : Boolean; -- Data OverRun
FE : Boolean; -- Frame Error
UDRE : Boolean; -- USART Data Register Empty
TXC : Boolean; -- USART Transmit Complete
RXC : Boolean; -- USART Receive Complete
end record;
pragma Pack (USART_Control_And_Register_Status_Register_A_Type);
for USART_Control_And_Register_Status_Register_A_Type'Size use
BYTE_SIZE;

type USART_Control_And_Register_Status_Register_B_Type is
record
TXB8 : Boolean; -- Transmit Data Bit 8
RXB8 : Boolean; -- Receive Data Bit 8
UCSZ2 : Boolean; -- Character Size Bit 2
TXEN : Boolean; -- Transmitter Enable
RXEN : Boolean; -- Receiver Enable
UDRIE : Boolean; -- USART Data Register Empty Interrupt Flag
TXCIE : Boolean; -- Tx Complete Interrupt Flag
RXCIE : Boolean; -- Rx Complete Interrupt Flag
end record;
pragma Pack (USART_Control_And_Register_Status_Register_B_Type);
for USART_Control_And_Register_Status_Register_B_Type'Size use
BYTE_SIZE;

type USART_Control_And_Register_Status_Register_C_Type is
record
UCPOL : Boolean; -- Clock Polarity
UCSZ0 : Boolean; -- Character Size Bit 0
UCSZ1 : Boolean; -- Character Size Bit 1
USBS : Boolean; -- Stop Bit Select
UPM : Bit_Array_Type (0 .. 1); -- Parity Mode Bits
UMSEL : Bit_Array_Type (0 .. 1); -- Mode Select
end record;
pragma Pack (USART_Control_And_Register_Status_Register_C_Type);
for USART_Control_And_Register_Status_Register_C_Type'Size use
BYTE_SIZE;

type USART_Type is
record
UCSRA : USART_Control_And_Register_Status_Register_A_Type;
UCSRB : USART_Control_And_Register_Status_Register_B_Type;
UCSRC : USART_Control_And_Register_Status_Register_C_Type;
Spare : Spare_Type (0 .. 7);
UBRR : Byte_Array_Type (0 .. 1); -- USART Baud Rate Register L/H Bytes
UDR : Byte_Type; -- USART I/O Data Register
end record;
pragma Pack (USART_Type);
for USART_Type'Size use 7 * BYTE_SIZE;

...and ...
Reg_USART1 : USART_Type;
for Reg_USART1'Address use System'To_Address (16#C8#);

when I do &Reg_USART1.<***> from the debugger it points correctly to each register position given by datasheet. For example, &Reg_USART1.UCSRA points me to
(gdb) &avr.usart.reg_usart1.ucsra
$2 = (access avr.usart.usart_control_and_register_status_register_a_type) 0x8000c8.

Rego, P.

unread,
Mar 16, 2014, 8:32:26 PM3/16/14
to
On Sunday, March 16, 2014 8:09:16 PM UTC-3, Oliver Kleinke wrote:

> > The problem is that when I send anything to the usart, the Ada
> > application restarts (continuously).
> This usually happens if you either blow the stack/heap or the PC
> (program counter) overflows (reset/power on vector is at 0), e.g., if
> the compiler optimizes away your main loop.

I have a feeling that I did not blow the ram, mainly because the problem does not happen in a simpler board as ATmega328P (ATmega2560 has 8KB SRAM, while the last has only 2K). Also I am using -O for optimization.

rrr.e...@gmail.com

unread,
Mar 17, 2014, 8:17:33 AM3/17/14
to
On Sunday, March 16, 2014 9:37:45 PM UTC+1, Rego, P. wrote:
> I am trying to use interrupt-driven Usart on an Atmel AVR ATmega2560 chip.

AVR-Ada has both polled and interrupt driven UART packages. Both work at least on atmega328. I never tried ATmega2560.

As far as I remember one of the two versions exhibited a bug in the FSF-gnat of the time (gcc-4.5 or gcc-4.6). It was fixed in a later gcc release (4.7.1?). You also might try a more recent gcc version.

Rolf

Oliver Kleinke

unread,
Mar 17, 2014, 10:08:11 AM3/17/14
to
Am Sun, 16 Mar 2014 17:21:58 -0700 (PDT)
schrieb "Rego, P." <pvr...@gmail.com>:

> I put the complete Ada objectdump part at http://is.gd/au08Fs. And
> the C part got from .lss in Atmel Studio I put in http://is.gd/qKpAuk.

The interrupt vector table in the disassembly is total garbage, the
vector for your ISR is not even generated.
The IV at 0x90 points to 0x2f46 <__bad_interrupt> which contains
this instruction:

00002f46 <__bad_interrupt>:
2f46: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

So there you have your reset. I guess you should follow Rolf's advice
and try a newer gcc.

Rego, P.

unread,
Mar 17, 2014, 4:28:13 PM3/17/14
to
On Monday, March 17, 2014 9:17:33 AM UTC-3, rrr.e...@gmail.com wrote:
> AVR-Ada has both polled and interrupt driven UART packages. Both work at least on atmega328. I never tried ATmega2560.

Yes, I also tried with ATmega328P and fully worked.

> As far as I remember one of the two versions exhibited a bug in the FSF-gnat of the time (gcc-4.5 or gcc-4.6). It was fixed in a later gcc release (4.7.1?). You also might try a more recent gcc version.

That means I would have to build the cross-compiler, right? (it takes off the fun of using gnat-gpl-2012-avr-windows-bin.exe installer :)

Oliver Kleinke

unread,
Mar 18, 2014, 10:08:54 AM3/18/14
to
Am Mon, 17 Mar 2014 13:28:13 -0700 (PDT)
schrieb "Rego, P." <pvr...@gmail.com>:
Here's a script/instructions to build a cross-compiler:
http://arduino.ada-language.com/automating-avr-gnat-and-avr-ada-installation.html

Rego, P.

unread,
Mar 20, 2014, 10:52:06 PM3/20/14
to
On Tuesday, March 18, 2014 11:08:54 AM UTC-3, Oliver Kleinke wrote:
> Here's a script/instructions to build a cross-compiler:
> http://arduino.ada-language.com/automating-avr-gnat-and-avr-ada-installation.html

Thanks!
I started to build gcc on a virtual machine running Windows XP with cygwin. But at some point of the gcc build I got several messages like

ada/a-except.o: In function `ada__exceptions__exception_message':
/cygdrive/f/Cross/gcc-obj-4.7.2/gcc/../../gcc-4.7.2/gcc/ada/a-except.adb:609: undefined reference to `__gnat_rcheck_CE_Explicit_Raise'

followed by
collect2: error: ld returned 1 exit status
../../gcc-4.7.2/gcc/ada/gcc-interface/Make-lang.in:553: recipe for target 'gnat1.exe' failed
make[3]: *** [gnat1.exe] Error 1
make[3]: Leaving directory '/cygdrive/f/Cross/gcc-obj-4.7.2/gcc'
Makefile:4101: recipe for target 'all-stage1-gcc' failed
make[2]: *** [all-stage1-gcc] Error 2
make[2]: Leaving directory '/cygdrive/f/Cross/gcc-obj-4.7.2'
Makefile:16443: recipe for target 'stage1-bubble' failed
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory '/cygdrive/f/Cross/gcc-obj-4.7.2'
Makefile:16747: recipe for target 'bootstrap' failed
make: *** [bootstrap] Error 2
ERROR: gcc: make bootstrap

Would you know what could fix it?

Regards.

rrr.e...@gmail.com

unread,
Mar 24, 2014, 10:28:55 AM3/24/14
to
On Friday, March 21, 2014 3:52:06 AM UTC+1, Rego, P. wrote:
> Would you know what could fix it? Regards.

If you don't know exactly what you're doing, don't try to bootstrap on Cygwin. You can way too easily mix up the cygwin and the pure windows tools that end in problems as above. If you start delving into building the cross toolchain, try it in a Linux environment first.

Regards
Rolf

rrr.e...@gmail.com

unread,
Mar 24, 2014, 10:36:34 AM3/24/14
to
On Monday, March 17, 2014 3:08:11 PM UTC+1, Oliver Kleinke wrote:
> 00002f46 <__bad_interrupt>:
> 2f46: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

> So there you have your reset.
> I guess you should follow Rolf's advice and try a newer gcc.

No, you don't need a newer compiler, you need a better link script.
Copy one of the existing linker scripts in your local work space and correct it there according to the data sheet.

Alternatively you might try rebuildig the avr-libc (V1.8.0) which includes newer binutils and link scripts

best regards
Rolf
0 new messages