summary refs log tree commit diff stats
path: root/gitlab/issues_text/target_avr/host_missing/accel_missing/1525
blob: aec01b592d8ecf55ea4e8b397046139a43af0855 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
Wrong initial value of stack pointer on AVR devices
Description of problem:
The initial value of stack pointer of AVR MCUs should be RAMEND (address of the end of their RAM), but QEMU initialize them to 0.

`qemu-system-avr -machine help` lists 4 flavors of MCUs which are ATmega168, ATmega2560, ATmega1280, ATmega328P. According to their datasheets, the stack pointer should be initialized as follows on reset.

- [ATmega168](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-9365-Automotive-Microcontrollers-ATmega88-ATmega168_Datasheet.pdf#page=12): RAMEND (which is 0x04FF)
- [ATmega2560 and ATmega1280](https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf#page=15): RAMEND (which is 0x21FF)
- [ATmega328P](https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf#page=22): RAMEND (which is 0x08FF)
Steps to reproduce:
1. Assemble the assembly code below: `avrasm2 -fI test.asm`

    ```asm
    ;; test.asm
    .INCLUDE "m328Pdef.inc"

    .EQU F_CPU = 16000000
    .EQU BAUD_RATE = 9600
    .EQU PRESCALE = (F_CPU / (16 * BAUD_RATE)) - 1

    .CSEG
    start:
    	;; initialize USART (serial port)
    	LDI R16, LOW(PRESCALE)
    	LDI R17, HIGH(PRESCALE)
    	STS UBRR0L, R16
    	STS UBRR0H, R17
    	LDI R16, (1 << RXEN0) | (1 << TXEN0)
    	STS UCSR0B, R16

    	;; Get stack pointer low byte and print it in ASCII
    	IN R16, SPL
    	LDI R17, 0x30
    	ADD R16, R17
    print1:
    	LDS r17, UCSR0A
    	SBRS r17, UDRE0
    	RJMP print1
    	STS UDR0, r16

    	;; Get stack pointer high byte and print it in ASCII
    	IN R16, SPH
    	LDI R17, 0x30
    	ADD R16, R17
    print2:
    	LDS r17, UCSR0A
    	SBRS r17, UDRE0
    	RJMP print2
    	STS UDR0, r16

    end:
    	RJMP end
    ```

2. Convert it to bin file: `avr-objcopy --input-target=ihex --output-target=binary test.hex test.bin`

3. Run it with QEMU: `qemu-system-avr -machine uno -bios test.bin -serial stdio`

This should print 00 which means that the stack pointer is initialized to 0.
Additional information:
I examined the source code and I think that editing the function `avr_cpu_reset_hold` in `/target/avr/cpu.c` might fix this issue. This is my first time seeing QEMU source code, so I might be wrong, though.

```c
// in /target/avr/cpu.c line 70
static void avr_cpu_reset_hold(Object *obj)
{
    // ...

    env->rampD = 0;
    env->rampX = 0;
    env->rampY = 0;
    env->rampZ = 0;
    env->eind = 0;
    env->sp = 0;    // <-- change this value in accordance with board type?

    //...
}
```