Hi,
I want to use simulavrxx to test my AVR code (the original
AVR studio was way too slow, and possibilities to interface
the simulated core with my programs and Verilog are really
important to me).
My AVR code intensively uses the UART interface.
Unfortunately it also sends smetimes the double quote character
("), which caused the Tcl/Tk GUI to crash.
Additionally I wanted to have more tight integration between my code
and the simulavr, and therefore I have decided to use pysimulavr.
My first finding was, that I'm unable to access periferials
defined in serialtx and serialrx from pysimulavr, but I've worked around
this by adding
#include "ui/ui.h"
#include "ui/extpin.h"
#include "ui/keyboard.h"
#include "ui/lcd.h"
#include "ui/scope.h"
#include "ui/serialrx.h"
#include "ui/serialtx.h"
and
%include "ui/ui.h"
%include "ui/extpin.h"
%include "ui/keyboard.h"
%include "ui/lcd.h"
%include "ui/scope.h"
%include "ui/serialrx.h"
%include "ui/serialtx.h"
lines to the pysimulavr.i file (I attach the modified version).
After recompilation, I have built my simulation file mytest.py (attached).
i have found, that if I instantiated my UART receiver as below:
class AVRtest(SimulavrAdapter):
def __init__(self):
self.dmanSingleDeviceApplication()
proc, elffile = argv[1].split(":")
self.device = self.loadDevice(proc, elffile)
self.device.SetClockFreq(125)
rs_in=pysimulavr.Net()
mytest = AVRtest()
mytest.dmanStart()
d1=mytest.device.GetPin("D1")
rs_in.Add(d1)
rx=pysimulavr.SerialRxBuffered()
rx.SetBaudRate(9600)
r0=rx.GetPin("rx")
rs_in.Add(r0)
the UART receiver was not simulated.
To cure it, I had to modify the SimulavrAdapter class, adding the
following method:
def addComponent(self,c):
self.__sc.Add(c)
return 0
Then I could register mu UART interface with:
mytest.addComponent(rx)
right after its creation.
What's interesting, is that when I have done the same with the
SerialTxBuffered component, I got the following error after invocation
of mytest.doRun:
FATAL: file ui/serialtx.cpp: line 98: Illegal state in SerialTx
It appears, that SerialTxBuffered must register itself in its
void SerialTxBuffered::Send(unsigned char data) procedure:
[...]
SystemClock::Instance().Add(this);
[...]
to work correctly.
The final version of my test file "mytest.py" is also attached.
My test is put in the examples/python directory and may be run with:
LD_LIBRARY_PATH=../../src/.libs \
PYTHONPATH=../../src \
/usr/bin/python -i mytest.py atmega16:code.elf
I hope, that this code may be useful for someone else, and I'd also
appretiate any improvements and corrections, if I've done something in a
wrong way.
--
Regards,
WZab
# -*- coding: UTF-8 -*-
# Python simulation with UART
import sys
import os
import select
from sys import argv
import pysimulavr
from ex_utils import SimulavrAdapter
class AVRtest(SimulavrAdapter):
def __init__(self):
self.dmanSingleDeviceApplication()
proc, elffile = argv[1].split(":")
self.device = self.loadDevice(proc, elffile)
self.device.SetClockFreq(125)
def uart_rcv():
while rx.Size()>0:
os.write(my_tty,chr(rx.Get()))
#os.flush(my_tty)
def uart_snd(text):
for c in text:
tx.Send(ord(c))
def myrun():
#This procedure performs the main loop
#It should be rather done in two separate threads,
#But this is only a "proof of the concept" implementation
while True:
mytest.doStep(10000) #You may need to adjust this value to assure smooth interaction...
uart_rcv()
(r,w,x)=select.select([my_tty,],[],[],0)
if r:
c=os.read(my_tty,1)
if c!= "":
tx.Send(ord(c))
if __name__ == "__main__":
rs_in=pysimulavr.Net()
rs_out=pysimulavr.Net()
mytest = AVRtest()
mytest.dmanStart()
d1=mytest.device.GetPin("D1")
d0=mytest.device.GetPin("D0")
rs_in.Add(d1)
rs_out.Add(d0)
#rx=pysimulavr.SerialRxBasic()
rx=pysimulavr.SerialRxBuffered()
mytest.addComponent(rx)
rx.SetBaudRate(9600)
r0=rx.GetPin("rx")
rs_in.Add(r0)
tx=pysimulavr.SerialTxBuffered()
#mytest.addComponent(tx)
tx.SetBaudRate(9600)
r1=tx.GetPin("tx")
rs_out.Add(r1)
#Create the pseudoterminal
(my_tty, slave_tty) = os.openpty()
slave_name = os.ttyname(slave_tty)
os.spawnl(os.P_NOWAIT,"/usr/bin/xterm","xterm", "-e", "microcom", "-p",slave_name)
# Enter the main loop
myrun()
# EOF
%module(directors="1") pysimulavr
%{
#include "systemclocktypes.h"
#include "avrdevice.h"
#include "systemclock.h"
#include "hardware.h"
#include "externaltype.h"
#include "irqsystem.h"
#include "pin.h"
#include "net.h"
#include "ui/ui.h"
#include "ui/extpin.h"
#include "ui/keyboard.h"
#include "ui/lcd.h"
#include "ui/scope.h"
#include "ui/serialrx.h"
#include "ui/serialtx.h"
#include "rwmem.h"
#include "hwsreg.h"
#include "avrfactory.h"
#include "memory.h"
#include "flash.h"
#include "hweeprom.h"
#include "breakpoint.h"
#include "global.h"
#include "avrerror.h"
#include "pysimulationmember.h"
#include "hwport.h"
#include "hwstack.h"
// to get devices registered (automatically on linux, but necessary on
windows)
#include "atmega128.h"
#include "at4433.h"
#include "at8515.h"
#include "atmega668base.h"
#include "atmega16_32.h"
#include "attiny2313.h"
%}
%include "std_vector.i"
%include "std_iostream.i"
%include "std_sstream.i"
namespace std {
%template(DWordVector) vector<dword>;
};
%exception {
try {
$action
} catch(char const* s) {
PyErr_SetString(PyExc_SystemError, s);
return NULL;
} catch(int i) {
PyErr_Format(PyExc_RuntimeError, "%d", i);
return NULL;
}
}
%include "types.h"
%include "systemclocktypes.h"
%include "simulationmember.h"
%feature("director") PySimulationMember;
%include "pysimulationmember.h"
%include "externaltype.h"
%include "pinnotify.h"
%include "traceval.h"
%include "irqsystem.h"
%include "avrdevice.h"
%extend DumpManager {
void addDumpVCD(const std::string &vcdname,
const std::string &istr,
const std::string &timebase,
const bool rstrobe,
const bool wstrobe) {
DumpVCD *d = new DumpVCD(vcdname, timebase, rstrobe, wstrobe);
$self->addDumper(d, $self->load(istr));
}
}
%extend AvrDevice {
// getRWMem and setRWMem are deprecated, don't use it in new code!
unsigned char getRWMem(unsigned a) { return $self->GetRWMem(a); }
bool setRWMem(unsigned a, unsigned char v) { return $self->SetRWMem(a, v); }
}
%include "systemclock.h"
%extend SystemClock {
int Step() {
bool untilCoreStepFinished = false;
return $self->Step(untilCoreStepFinished);
}
}
%feature("director") Hardware;
%include "hardware.h"
%include "hwport.h"
%include "hwstack.h"
%feature("director") Pin;
%include "pin.h"
%extend Pin {
char toChar() {
char c = *$self;
return c;
}
void SetPin(const char c) {
*$self = c;
}
}
%include "net.h"
%include "ui/ui.h"
%include "ui/extpin.h"
%include "ui/keyboard.h"
%include "ui/lcd.h"
%include "ui/scope.h"
%include "ui/serialrx.h"
%include "ui/serialtx.h"
%feature("director") RWMemoryMember;
%include "rwmem.h"
%include "hwsreg.h"
%extend RWSreg {
unsigned char GetValue(void) {
unsigned char v = *$self;
return v;
}
void SetValue(unsigned char v) {
RWMemoryMember* m = $self;
*m = v;
}
}
%include "avrfactory.h"
%include "memory.h"
%extend Memory {
unsigned char GetMemory(unsigned int a) {
if(a < $self->GetSize())
return $self->myMemory[a];
return 0;
}
void PyWriteMem(char *src, unsigned int offset, unsigned int secSize) {
$self->WriteMem((unsigned char *)src, offset, secSize);
}
}
%include "flash.h"
%include "hweeprom.h"
%include "breakpoint.h"
%extend Breakpoints {
void RemoveBreakpoint(unsigned bp) {
Breakpoints::iterator ii;
if ((ii = find($self->begin(), $self->end(), bp)) != $self->end())
$self->erase(ii);
}
void AddBreakpoint(unsigned bp) {
$self->push_back(bp);
}
}
%include "global.h"
%include "avrerror.h"
// to get devices registered (automatically on linux, but necessary on windows)
%include "atmega128.h"
%include "at4433.h"
%include "at8515.h"
%include "atmega668base.h"
%include "atmega16_32.h"
%include "attiny2313.h"
// EOF
_______________________________________________
Simulavr-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/simulavr-devel