Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USART as SPI-master: incorrect timing / not properly simulated? #477

Open
kittennbfive opened this issue Feb 22, 2022 · 2 comments
Open

Comments

@kittennbfive
Copy link
Contributor

Hi,

the following code for mega1284P configures the USART1 as SPI-master and sends out the same byte again and again (stop the simulation with Ctrl+C!) at maximum speed=f_osc/2. It also sets a pin to measure the time needed for the transmission.

On real hardware with a 18,432MHz crystal this time is about 1,74µs (measured with a scope), but in the VCD-file produced by simavr the time is about 7,7µs! This is way too much.

Is an USART as a SPI-master actually properly simulated by simavr?

#include <avr/io.h>
#include <stdint.h>

uint8_t spi_send_receive(const uint8_t v)
{
	PORTB|=(1<<PB0);
	while(!(UCSR1A&(1<<UDRE1)));
	UDR1=v;
	while(!(UCSR1A&(1<<RXC1)));
	PORTB&=~(1<<PB0);
	return UDR1;
}

int main(void)
{
	DDRB|=(1<<PB0);
	
	//USART1 as SPI, max speed
	UBRR1=0;
	DDRD|=(1<<PD3)|(1<<PD4);
	UCSR1C=(1<<UMSEL11)|(1<<UMSEL10);
	UCSR1B=(1<<RXEN1)|(1<<TXEN1);
	UBRR1=0;
	
	while(1)
		spi_send_receive(0xaa);
	
	return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <err.h>
#include <signal.h>

#include "sim_avr.h"
#include "sim_elf.h"
#include "avr_uart.h"
#include "avr_ioport.h"
#include "sim_vcd_file.h"

volatile bool run=true;

static void sigint_handler(int sig)
{
	(void)sig;
	run=false;
}

int main(void)
{
	signal(SIGINT, &sigint_handler);
		
	avr_t *avr1;
	elf_firmware_t firmware1;

	if(elf_read_firmware("avr.elf", &firmware1))
	{
		printf("elf_read_firmware failed\n");
		return 1;
	}
	avr1 = avr_make_mcu_by_name("atmega1284p");
	if (!avr1) {
		printf("avr_make_mcu_by_name failed\n");
		return 1;
	}
	
	avr_init(avr1);
	avr1->frequency=18432000;
	avr_load_firmware(avr1, &firmware1);
	
	avr_vcd_t vcd1;
	avr_vcd_init(avr1, "test.vcd", &vcd1, 100);
	avr_vcd_add_signal(&vcd1, avr_io_getirq(avr1, AVR_IOCTL_IOPORT_GETIRQ('B'), 0), 1, "PB0");
	avr_vcd_start(&vcd1);
	
	//the simulator will block if nothing is "received", so just add a virtual connection
	avr_connect_irq(avr_io_getirq(avr1, AVR_IOCTL_UART_GETIRQ('1'), UART_IRQ_OUTPUT), avr_io_getirq(avr1, AVR_IOCTL_UART_GETIRQ('1'), UART_IRQ_INPUT));
	
	int state1;
	do
	{
		state1=avr_run(avr1);
		
	} while(state1!=cpu_Done && state1!=cpu_Crashed && run);

	avr_vcd_close(&vcd1);
	avr_terminate(avr1);

	return 0;
}
@kittennbfive
Copy link
Contributor Author

I can confirm that USART as SPI-master is not supported currently. Working on a patch...

@kittennbfive
Copy link
Contributor Author

I have patched some files to make this mode work, but it's an ugly hack and will currently only work for USART1 on mega1284P. This is enough for me currently to continue what i was actually doing. I attached the diff-files if somebody wants to take a look.

Any advice on how to implement this properly for a decent PR appreciated.

avr_uart.c.diff.txt
avr_uart.h.diff.txt
sim_megax4.h.diff.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant