Skip to content
This repository was archived by the owner on Aug 20, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
84ee69b
automake: don't treat warnings as errors.
Traumflug Nov 13, 2013
ec8cf93
src/avrreadelf.cpp: fix three formatting warnings.
Traumflug Jun 14, 2014
341cd1a
Allow to store simulation parameters inside the ELF file.
Traumflug Nov 15, 2013
ba900e0
ELF simulation info storage: bring SIMINFO_DEVICE() into action.
Traumflug Nov 16, 2013
acf7bf3
ELF simulation info storage: bring SIMINFO_CPUFREQUENCY() into action.
Traumflug Nov 16, 2013
a313903
ELF simulation info storage: introduce a length variable.
Traumflug Nov 16, 2013
f50960b
ELF simulation info storage: bail out on malformed .siminfo sections.
Traumflug Nov 18, 2013
d70b1ff
ELF simulation info storage: introduce SIMINFO_SERIAL_OUT().
Traumflug Nov 18, 2013
0552bc6
ui/serialrx: implement SerialRxFile.
Traumflug Nov 18, 2013
3c52240
ELF simulation info storage: bring SIMINFO_SERIAL_OUT() into action.
Traumflug Nov 18, 2013
5ac7b69
ELF simulation info storage: introduce SIMINFO_SERIAL_IN():
Traumflug Nov 19, 2013
1d1046a
ui/serialtx: implement SerialTxFile.
Traumflug Nov 19, 2013
6ee8cb8
ELF simulation info storage: bring SIMINFO_SERIAL_IN() into action.
Traumflug Nov 19, 2013
f5c049f
src/traceval.[h,cpp]: fix string indexing types.
miso- May 7, 2014
5c0ab6c
src/avrdevice.h: sync ELFLoad declaration with src/avrreadelf.h.
miso- May 14, 2014
1d2cc6b
src/avrreadelf.cpp: sync "#ifdef _MSC_VER" ELFLoad definition.
miso- May 14, 2014
9d0eaa2
src/avrreadelf.cpp: fix warning about wrong ELF signature.
Traumflug Feb 20, 2015
69d944d
src/atmega1284abase.cpp: also accept p variants.
Traumflug Feb 24, 2015
0e4d362
Partially revert breaking commit d6e3b58358cce6aa35eaf5fcc62
Traumflug Feb 24, 2015
076ca5c
src/cmd/main.cpp: fix termination message.
Traumflug Feb 24, 2015
66d3108
Print port as an unsigned number
simark Aug 28, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# common initialisation of autotools
####
AC_INIT([SimulAVR], [1.1dev], [simulavr-devel@nongnu.org])
AM_INIT_AUTOMAKE([1.10 -Wall -Werror foreign subdir-objects])
AM_INIT_AUTOMAKE([1.10 -Wall foreign subdir-objects])
AC_PREREQ([2.61])
AC_CONFIG_MACRO_DIR([m4])
AM_MAINTAINER_MODE
Expand Down
1 change: 1 addition & 0 deletions examples/simple_serial/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ AVR_GCC = @AVR_GCC@
AVR_CPU = atmega644
AVR_FREQUENCY = 20000000
AVR_CFLAGS = -g -O2 -mmcu=$(AVR_CPU) -DF_CPU=$(AVR_FREQUENCY)
AVR_CFLAGS += -Wl,--section-start=.siminfo=0x900000
AVR_OBJS = main.o serial.o
SIMULAVR_ARGS = -d $(AVR_CPU) -f $(EXAMPLE).elf

Expand Down
22 changes: 22 additions & 0 deletions examples/simple_serial/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@

#include <avr/interrupt.h>

/*
* Here we tell SimulAVR for which device and which frequency we build this
* code. The nice thing is, these macros add a section to the ELF file, so
* they can be read by SimulAVR, but they're also ignored when converted to
* an ihex file for hardware upload. Accordingly, the executed binary for
* SimulAVR and real hardware is the same, no need to recompile for one or
* another. The more important result of this is, behaviour is also exactly
* the same, no extra cycles for serving simulator matters.
*
* One small caveat: To stop the linker from stripping this section, avr-gcc
* needs an extra parameter when linking the binary (see Makefile.am):
*
* -Wl,--section-start=.siminfo=0x900000
*
* For details on these macros, see the comments in simulavr_info.h.
*/
#include "../../src/simulavr_info.h"
SIMINFO_DEVICE("atmega644");
SIMINFO_CPUFREQUENCY(F_CPU);
SIMINFO_SERIAL_IN("D0", "-", 19200);
SIMINFO_SERIAL_OUT("D1", "-", 19200);


// This is all we need:
int main (void) {
Expand Down
6 changes: 6 additions & 0 deletions src/atmega1284abase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ AVR_REGISTER(atmega324, AvrDevice_atmega324A)
AVR_REGISTER(atmega644, AvrDevice_atmega644A)
AVR_REGISTER(atmega1284, AvrDevice_atmega1284A)

AVR_REGISTER(atmega164p, AvrDevice_atmega164A)
AVR_REGISTER(atmega324p, AvrDevice_atmega324A)
AVR_REGISTER(atmega644p, AvrDevice_atmega644A)
AVR_REGISTER(atmega1284p, AvrDevice_atmega1284A)

AvrDevice_atmega1284Abase::~AvrDevice_atmega1284Abase() {
delete usart1;
delete usart0;
Expand Down Expand Up @@ -203,6 +208,7 @@ AvrDevice_atmega1284Abase::AvrDevice_atmega1284Abase(unsigned ram_bytes,
21, // (22) UDRE vector
22); // (23) TX complete vector

// TODO: ATmega644P has USART1, but ATmega644 (maybe others) has not.
usart1 = new HWUsart(this,
irqSystem,
PinAtPort(&portd, 3), // TXD1
Expand Down
2 changes: 1 addition & 1 deletion src/avrdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ class AvrDevice: public SimulationMember, public TraceValueRegister {
//! When a call/jump/cond-jump instruction was executed. For debugging.
void DebugOnJump();

friend void ELFLoad(const AvrDevice * core);
friend void ELFLoad(AvrDevice * core);

};

Expand Down
4 changes: 3 additions & 1 deletion src/avrfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ AvrDevice* AvrFactory::makeDevice(const char *in) {
for(unsigned int i = 0; i < devname.size(); i++)
devname[i] = tolower(devname[i]);
if(devname == "unknown")
avr_error("Device type not specified, use -d | --device TYPE or insert '#insert <avr/signature.h>' into your source to specify device signature");
avr_error("Device type not specified, use -d | --device TYPE or "
"insert a SIMINFO_DEVICE(name) macro into your source to "
"specify the device name");
AVRDeviceMap::iterator i = devmap.find(devname);
if(i == devmap.end())
avr_error("Invalid device specification: %s", in);
Expand Down
200 changes: 179 additions & 21 deletions src/avrreadelf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@
#include "elfio/elfio.hpp"

#include <string>
#include <cstring>
#include <map>
#include <limits>

#include "avrdevice_impl.h"
#include "avrsignature.h"
#include "serialrx.h"
#include "serialtx.h"
#include "simulavr_info.h"

#include "avrreadelf.h"

Expand Down Expand Up @@ -87,19 +92,19 @@ typedef struct {
Elf32_Word p_align; /* memory/file alignment */
} Elf32_Phdr;

void ELFLoad(const AvrDevice * core) {
FILE * f = fopen(core->actualFilename.c_str(), "rb");
void ELFLoad(AvrDevice * core) {
FILE * f = fopen(core->GetFname().c_str(), "rb");
if(f == NULL)
avr_error("Could not open file: %s", core->actualFilename.c_str());
avr_error("Could not open file: %s", core->GetFname().c_str());

Elf32_Ehdr header;
fread(&header, sizeof(header), 1, f);
if(header.e_ident[0] != 0x7F || header.e_ident[1] != 'E'
|| header.e_ident[2] != 'L' || header.e_ident[3] != 'F')
avr_error("File '%s' is not an ELF file", core->actualFilename.c_str());
avr_error("File '%s' is not an ELF file", core->GetFname().c_str());
// TODO: fix endianity in header
if(header.e_machine != 83)
avr_error("ELF file '%s' is not for Atmel AVR architecture (%d)", core->actualFilename.c_str(), header.e_machine);
avr_error("ELF file '%s' is not for Atmel AVR architecture (%d)", core->GetFname().c_str(), header.e_machine);

for(int i = 0; i < header.e_phnum; i++) {
fseek(f, header.e_phoff + i * header.e_phentsize, SEEK_SET);
Expand All @@ -114,7 +119,7 @@ void ELFLoad(const AvrDevice * core) {
continue; // not into a Flash
if(progHeader.p_filesz != progHeader.p_memsz) {
avr_error("Segment sizes 0x%x and 0x%x in ELF file '%s' must be the same",
progHeader.p_filesz, progHeader.p_memsz, core->actualFilename.c_str());
progHeader.p_filesz, progHeader.p_memsz, core->GetFname().c_str());
}
unsigned char * tmp = new unsigned char[progHeader.p_filesz];
fseek(f, progHeader.p_offset, SEEK_SET);
Expand All @@ -127,24 +132,23 @@ void ELFLoad(const AvrDevice * core) {
fclose(f);
}

unsigned int ELFGetSignature(const char *filename) {
unsigned int ELFGetDeviceNameAndSignature(const char *filename, char *devicename) {
return std::numeric_limits<unsigned int>::max();
}

#endif

#ifndef _MSC_VER

void ELFLoad(const AvrDevice * core) {
void ELFLoad(AvrDevice * core) {
ELFIO::elfio reader;

if(!reader.load(core->actualFilename))
if(!reader.load(core->GetFname()))
avr_error("File '%s' not found or isn't a elf object",
core->actualFilename.c_str());
core->GetFname().c_str());

if(reader.get_machine() != EM_AVR)
avr_error("ELF file '%s' is not for Atmel AVR architecture (%d)",
core->actualFilename.c_str(),
core->GetFname().c_str(),
reader.get_machine());

// over all symbols ...
Expand Down Expand Up @@ -204,13 +208,74 @@ void ELFLoad(const AvrDevice * core) {
/* lock bits starting from 0x830000, do nothing */;
} else if(value >= 0x840000 && value < 0x840400) {
/* signature space starting from 0x840000, do nothing */;
} else if(!strncmp("siminfo" , name.c_str(), 7)) {
/* SIMINFO symbol, do nothing */
} else
avr_warning("Unknown symbol address range found! (symbol='%s', address=0x%llx)",
avr_warning("Unknown symbol address range found! (symbol='%s', address=0x%lx)",
name.c_str(),
value);

}
}
if(psec->get_name() == ".siminfo") {
/*
* You wonder why SIMINFO is read here, ignoring symbols?
* Well, doing things this way is pretty independent from ELF
* internals, other than finding the .siminfo section start pointer.
* Accordingly, we can add pretty much anything, as long as the
* interpretation here matches what's given in simulavr_info.h.
*/
ELFIO::Elf_Xword filesize = psec->get_size();
const char *data = psec->get_data();
const char *data_ptr = data, *data_end = data + filesize;

while(data_ptr < data_end) {
char tag = *data_ptr;
char length = *(data_ptr + 1);
// Length check already done in ELFGetDeviceNameAndSignature().

switch(tag) {
case SIMINFO_TAG_DEVICE:
// Device name. Handled in ELFGetDeviceNameAndSignature().
break;
case SIMINFO_TAG_CPUFREQUENCY:
core->SetClockFreq((SystemClockOffset)1000000000 /
((siminfo_long_t *)data_ptr)->value);
break;
case SIMINFO_TAG_SERIAL_IN:
avr_message("Connecting file %s as serial in to pin %s at %d baud.",
((siminfo_serial_t *)data_ptr)->filename,
((siminfo_serial_t *)data_ptr)->pin,
((siminfo_serial_t *)data_ptr)->baudrate);
{
Net *net = new Net();
SerialTxFile *serial =
new SerialTxFile(((siminfo_serial_t *)data_ptr)->filename);
serial->SetBaudRate(((siminfo_serial_t *)data_ptr)->baudrate);
net->Add(core->GetPin(((siminfo_serial_t *)data_ptr)->pin));
net->Add(serial->GetPin("tx"));
}
break;
case SIMINFO_TAG_SERIAL_OUT:
avr_message("Connecting pin %s as serial out to file %s at %d baud.",
((siminfo_serial_t *)data_ptr)->pin,
((siminfo_serial_t *)data_ptr)->filename,
((siminfo_serial_t *)data_ptr)->baudrate);
{
Net *net = new Net();
SerialRxFile *serial =
new SerialRxFile(((siminfo_serial_t *)data_ptr)->filename);
serial->SetBaudRate(((siminfo_serial_t *)data_ptr)->baudrate);
net->Add(core->GetPin(((siminfo_serial_t *)data_ptr)->pin));
net->Add(serial->GetPin("rx"));
}
break;
default:
avr_warning("Unknown tag in ELF .siminfo section: %hu", tag);
}
data_ptr += length;
}
}
}

// load program, data and - if available - eeprom, fuses and signature
Expand Down Expand Up @@ -248,23 +313,25 @@ void ELFLoad(const AvrDevice * core) {
} else if(vma >= 0x840000 && vma < 0x840400) {
// read and check signature, if available, space from 0x840000 to 0x840400
if(filesize != 3)
avr_error("wrong device signature size in elf file, expected=3, given=%llu",
avr_error("wrong device signature size in elf file, expected=3, given=%lu",
filesize);
else {
unsigned int sig = (((data[2] << 8) + data[1]) << 8) + data[0];

if(core->devSignature != std::numeric_limits<unsigned int>::max() && sig != core->devSignature)
if(core->GetDeviceSignature() != std::numeric_limits<unsigned int>::max() &&
sig != core->GetDeviceSignature())
avr_error("wrong device signature, expected=0x%x, given=0x%x",
core->devSignature,
core->GetDeviceSignature(),
sig);
}
}
}
}
}

unsigned int ELFGetSignature(const char *filename) {
unsigned int signature = std::numeric_limits<unsigned int>::max();
unsigned int ELFGetDeviceNameAndSignature(const char *filename, char *devicename) {
unsigned int signature = 0, sig_cli = 0, sig_elf = 0, sig_siminfo = 0;
char siminfo_name[128];
ELFIO::elfio reader;

if(!reader.load(filename))
Expand All @@ -275,6 +342,18 @@ unsigned int ELFGetSignature(const char *filename) {
filename,
reader.get_machine());

// Search command line for signature.
if(strcmp(devicename, "unknown")) {
std::map<std::string, unsigned int>::iterator cur =
AvrNameToSignatureMap.find(devicename);
if(cur != AvrNameToSignatureMap.end()) {
sig_cli = cur->second;
} else {
avr_warning("signature for device '%s' not found", devicename);
}
}

// Search ELF binary for signature.
ELFIO::Elf_Half seg_num = reader.segments.size();

for(ELFIO::Elf_Half i = 0; i < seg_num; i++) {
Expand All @@ -290,18 +369,97 @@ unsigned int ELFGetSignature(const char *filename) {
if(vma >= 0x840000 && vma < 0x840400) {
// read and check signature, if available, space from 0x840000 to 0x840400
if(filesize != 3)
avr_error("wrong device signature size in elf file, expected=3, given=%llu",
filesize);
avr_error("wrong device signature size in elf file, "
"expected=3, given=%lu", filesize);
else {
const unsigned char* data = (const unsigned char*)pseg->get_data();

signature = (((data[2] << 8) + data[1]) << 8) + data[0];
sig_elf = (((data[2] << 8) + data[1]) << 8) + data[0];

std::map<unsigned int, std::string>::iterator cur =
AvrSignatureToNameMap.find(sig_elf);
if(cur == AvrSignatureToNameMap.end()) {
avr_warning("unknown signature in ELF file: 0x%x",
sig_elf);
sig_elf = 0;
}
break;
}
}
}
}

// Search SIMINFO for device name.
for(ELFIO::Elf_Half i = 0; i < seg_num; i++) {
ELFIO::section* psec = reader.sections[i];

if(psec->get_name() == ".siminfo") {
ELFIO::Elf_Xword filesize = psec->get_size();
const char *data = psec->get_data();
const char *data_ptr = data, *data_end = data + filesize;

while(data_ptr < data_end) {
char tag = *data_ptr;
char length = *(data_ptr + 1);
if(length == 0)
avr_error("Field of zero length in .siminfo"
"section in ELF file found.");
if(tag == SIMINFO_TAG_DEVICE) {
strncpy(siminfo_name,
((siminfo_string_t *)data_ptr)->string, 128);
siminfo_name[127] = '\0'; // safety

std::map<std::string, unsigned int>::iterator cur =
AvrNameToSignatureMap.find(siminfo_name);
if(cur != AvrNameToSignatureMap.end()) {
sig_siminfo = cur->second;
}
else {
avr_warning("signature for device '%s' not found",
siminfo_name);
}
break;
}
// Everything else handled in ELFLoad().
data_ptr += length;
}
}
}

// Now we have searched all possible sources, take the one with the highest
// precedence: command line over ELF over SIMINFO.
if(sig_cli) {
signature = sig_cli;
if(sig_elf && sig_elf != sig_cli) {
avr_warning("Command line device name '%s' taking precedence over "
"device signature 0x%x in ELF file.",
devicename, sig_elf);
}
if(sig_siminfo && sig_siminfo != sig_cli) {
avr_warning("Command line device name '%s' taking precedence over "
"SIMINFO device name '%s'.", devicename, siminfo_name);
}
}
else if(sig_elf) {
signature = sig_elf;
if(sig_siminfo && sig_siminfo != sig_elf) {
avr_warning("Device signature 0x%x in ELF file taking precedence "
"over SIMINFO device name '%s'.",
sig_elf, siminfo_name);
}
}
else if(sig_siminfo) {
signature = sig_siminfo;
}

// Done.
std::map<unsigned int, std::string>::iterator cur =
AvrSignatureToNameMap.find(signature);
if(cur != AvrSignatureToNameMap.end()) {
strncpy(devicename, cur->second.c_str(), 1024);
}
avr_message("Device name is %s, signature 0x%x.", devicename, signature);

return signature;
}

Expand Down
Loading