File: atmega2560_uart_echo.c

package info (click to toggle)
simavr 1.6%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 20,268 kB
  • sloc: ansic: 362,806; makefile: 622; ruby: 70; python: 63
file content (131 lines) | stat: -rw-r--r-- 3,080 bytes parent folder | download | duplicates (2)
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
	atmega88_uart_echo.c

	This test case enables uart RX interupts, does a "printf" and then receive characters
	via the interupt handler until it reaches a \r.

	This tests the uart reception fifo system. It relies on the uart "irq" input and output
	to be wired together (see simavr.c)
 */

#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
#include <util/delay.h>

/*
 * This demonstrate how to use the avr_mcu_section.h file
 * The macro adds a section to the ELF file with useful
 * information for the simulator
 */
#include "avr_mcu_section.h"
AVR_MCU(F_CPU, "atmega2560");
// tell simavr to listen to commands written in this (unused) register
AVR_MCU_SIMAVR_COMMAND(&GPIOR0);
AVR_MCU_SIMAVR_CONSOLE(&GPIOR1);

/*
 * This small section tells simavr to generate a VCD trace dump with changes to these
 * registers.
 * Opening it with gtkwave will show you the data being pumped out into the data register
 * UDR0, and the UDRE0 bit being set, then cleared
 */
const struct avr_mmcu_vcd_trace_t _mytrace[]  _MMCU_ = {
	{ AVR_MCU_VCD_SYMBOL("UDR3"), .what = (void*)&UDR3, },
	{ AVR_MCU_VCD_SYMBOL("UDRE3"), .mask = (1 << UDRE3), .what = (void*)&UCSR3A, },
	{ AVR_MCU_VCD_SYMBOL("GPIOR1"), .what = (void*)&GPIOR1, },
};
#ifdef USART3_RX_vect_num	// stupid ubuntu has antique avr-libc
AVR_MCU_VCD_IRQ(USART3_RX);	// single bit trace
#endif
AVR_MCU_VCD_ALL_IRQ();		// also show ALL irqs running

volatile uint8_t cnt = 0;
volatile uint8_t done = 0;

static int uart_putchar(char c, FILE *stream)
{
	uint8_t startcnt;
	if (c == '\n')
		uart_putchar('\r', stream);
	loop_until_bit_is_set(UCSR3A, UDRE3);

	startcnt = cnt;
	UDR3 = c;
//	_delay_us(100);

	// Wait until we have received the character back
	while(!done && cnt == startcnt)
	{
		UDR1 = 'a';
		UDR1 = '\n';
		sleep_cpu();
	}

	UDR1 = 'b';
	UDR1 = '\n';

	_delay_us(1000);

	return 0;
}

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
                                         _FDEV_SETUP_WRITE);

volatile uint8_t bindex = 0;
uint8_t buffer[80];

ISR(USART3_RX_vect)
{
	UDR1 = 'c';
	UDR1 = '\n';

	uint8_t b = UDR3;
	GPIOR1 = b; // for the trace file
	buffer[bindex++] = b;
	buffer[bindex] = 0;
	cnt++;
	if (b == '\n')
		done++;
//	sleep_cpu();
}

int main()
{
	stdout = &mystdout;

	UCSR3C = (3 << UCSZ30); // 8 bits
	// see http://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html
#define BAUD 38400
#include <util/setbaud.h>
	UBRR3H = UBRRH_VALUE;
	UBRR3L = UBRRL_VALUE;
#if USE_2X
	UCSR3A |= (1 << U2X3);
#else
	UCSR3A &= ~(1 << U2X3);
#endif

	// enable receiver & transmitter
	UCSR3B |= (1 << RXCIE3) | (1 << RXEN3) | (1 << TXEN3);

	// this tells simavr to start the trace
	GPIOR0 = SIMAVR_CMD_VCD_START_TRACE;
	sei();
	printf("Hey there, this should be received back\n");
	loop_until_bit_is_set(UCSR3A, UDRE3);

	while (!done)
		sleep_cpu();

	cli();

	printf("Received: %s", buffer);

	// this quits the simulator, since interupts are off
	// this is a "feature" that allows running tests cases and exit
	sleep_cpu();
}