Skip to content

Commit

Permalink
examples: Working i2c master test board
Browse files Browse the repository at this point in the history
Write a few bytes to an i2c eeprom, read them back...

Signed-off-by: Michel Pollet <[email protected]>
  • Loading branch information
buserror committed Mar 27, 2011
1 parent 0093da9 commit a722838
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 115 deletions.
2 changes: 2 additions & 0 deletions examples/board_i2ctest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ all: obj atmega48_${target}.axf ${target}
include ${simavr}/Makefile.common

atmega48_${target}.axf: atmega48_${target}.c
atmega48_${target}.axf: avr_twi_master.c avr_twi_master.h

board = ${OBJ}/${target}.elf

${board} : ${OBJ}/${target}.o
${board} : ${OBJ}/i2c_eeprom.o
${board} : ${simavr}/simavr/${OBJ}/libsimavr.a

${target}: ${board}
Expand Down
15 changes: 15 additions & 0 deletions examples/board_i2ctest/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

This contains a sample program to demonstrate the use of simavr
using 'custom' code, and own "peripherals". It shows how it is
possible to "hook" code to the AVR pins, and also how to make
"peripherals" and also hook them up to AVR pins.

This demo demonstrate how to write a i2c/twi "peripheral" and hook it to
an AVR, and then run a firmware that behaves as a TWI "master" to talk to it.

The code uses a generic i2c "eeprom" were the AVR writes some bytes,
then read them again. The AVR code is based on the Atmel reference
implementation, with quite a few changes to make it more functional.

Thid "board" doesn't use opengl, the eeprom will display what the
transactions are.
2 changes: 1 addition & 1 deletion examples/board_i2ctest/atmega48_i2ctest.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "avr_mcu_section.h"
AVR_MCU(F_CPU, "atmega48");

#include "avr_twi_master.c"
#include "avr_twi_master.h"

#include <stdio.h>

Expand Down
9 changes: 8 additions & 1 deletion examples/board_i2ctest/avr_twi_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*
****************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include "avr_twi_master.h"

//static unsigned char TWI_buf[ TWI_BUFFER_SIZE ]; // Transceiver buffer
Expand Down Expand Up @@ -162,7 +164,12 @@ ISR( TWI_vect )
if (TWI_sendStop)
TWCR = (1<<TWEN)| // TWI Interface enabled
(0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag
(0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition?
(0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition
(0<<TWWC); //
else
TWCR = (1<<TWEN)| // TWI Interface enabled
(0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // DO NOT Initiate a STOP condition
(0<<TWWC); //
}
break;
Expand Down
117 changes: 4 additions & 113 deletions examples/board_i2ctest/i2ctest.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
along with simavr. If not, see <http://www.gnu.org/licenses/>.
*/



#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
Expand All @@ -31,106 +29,7 @@
#include "sim_elf.h"
#include "sim_gdb.h"
#include "sim_vcd_file.h"


typedef struct i2c_eeprom_t {
avr_irq_t * irq; // irq list
uint8_t addr_base;
uint8_t addr_mask;

uint8_t selected; // selected address
int index; // byte index

uint16_t reg_addr; // read/write address register
int size; // also implies the address size, one or two byte
uint8_t ee[4096];
} i2c_eeprom_t;

#include <string.h>

/*
* called when a RESET signal is sent
*/
static void
i2c_eeprom_in_hook(
struct avr_irq_t * irq,
uint32_t value,
void * param)
{
i2c_eeprom_t * p = (i2c_eeprom_t*)param;
avr_twi_msg_irq_t v;
v.u.v = value;

if (v.u.twi.msg & TWI_COND_STOP) {
if (p->selected) {
// it was us !
printf("eeprom received stop\n");
}
p->selected = 0;
p->index = 0;
p->reg_addr = 0;
}
if (v.u.twi.msg & TWI_COND_START) {
p->selected = 0;
p->index = 0;
if ((p->addr_base & p->addr_mask) == (v.u.twi.addr & p->addr_mask)) {
// it's us !
p->selected = v.u.twi.addr;
avr_raise_irq(p->irq + TWI_IRQ_MISO,
avr_twi_irq_msg(TWI_COND_ACK, p->selected, 1));
}
}
if (p->selected) {
if (v.u.twi.msg & TWI_COND_WRITE) {
printf("eeprom write %02x\n", v.u.twi.data);
// address size is how many bytes we use for address register
avr_raise_irq(p->irq + TWI_IRQ_MISO,
avr_twi_irq_msg(TWI_COND_ACK, p->selected, 1));
int addr_size = p->size > 256 ? 2 : 1;
if (p->index < addr_size) {
p->reg_addr |= (v.u.twi.data << (p->index * 8));
printf("eeprom set address to %04x\n", p->reg_addr);
} else {
printf("eeprom WRITE data %04x: %02x\n", p->reg_addr, v.u.twi.data);
p->ee[p->reg_addr++] = v.u.twi.data;
}
p->reg_addr &= (p->size -1);
p->index++;
}
if (v.u.twi.msg & TWI_COND_READ) {
printf("eeprom READ data %04x: %02x\n", p->reg_addr, p->ee[p->reg_addr]);
uint8_t data = p->ee[p->reg_addr++];
avr_raise_irq(p->irq + TWI_IRQ_MISO,
avr_twi_irq_msg(TWI_COND_READ, p->selected, data));
p->reg_addr &= (p->size -1);
p->index++;
}
}
}

static const char * _ee_irq_names[2] = {
[TWI_IRQ_MISO] = "8>eeprom.out",
[TWI_IRQ_MOSI] = "32<eeprom.in",
};

void
i2c_eeprom_init(
struct avr_t * avr,
i2c_eeprom_t * p,
uint8_t addr,
uint8_t mask,
uint8_t * data,
size_t size)
{
memset(p, 0, sizeof(p));
memset(p->ee, 0xff, sizeof(p->ee));
p->irq = avr_alloc_irq(&avr->irq_pool, 0, 2, _ee_irq_names);
avr_irq_register_notify(p->irq + TWI_IRQ_MOSI, i2c_eeprom_in_hook, p);

p->size = size > sizeof(p->ee) ? sizeof(p->ee) : size;
if (data)
memcpy(p->ee, data, p->size);
}
#include "i2c_eeprom.h"

avr_t * avr = NULL;
avr_vcd_t vcd_file;
Expand All @@ -141,9 +40,7 @@ int main(int argc, char *argv[])
{
elf_firmware_t f;
const char * fname = "atmega48_i2ctest.axf";
char path[256];

sprintf(path, "%s/%s", dirname(argv[0]), fname);
printf("Firmware pathname is %s\n", fname);
elf_read_firmware(fname, &f);

Expand All @@ -160,13 +57,8 @@ int main(int argc, char *argv[])
// initialize our 'peripheral'
i2c_eeprom_init(avr, &ee, 0xa0, 0xfe, NULL, 1024);

// "connect" the IRQs of the button to the port pin of the AVR
avr_connect_irq(
ee.irq + TWI_IRQ_MISO,
avr_io_getirq(avr, AVR_IOCTL_TWI_GETIRQ(0), TWI_IRQ_MISO));
avr_connect_irq(
avr_io_getirq(avr, AVR_IOCTL_TWI_GETIRQ(0), TWI_IRQ_MOSI),
ee.irq + TWI_IRQ_MOSI );
i2c_eeprom_attach(avr, &ee, AVR_IOCTL_TWI_GETIRQ(0));
ee.verbose = 1;

// even if not setup at startup, activate gdb if crashing
avr->gdb_port = 1234;
Expand All @@ -187,8 +79,7 @@ int main(int argc, char *argv[])
avr_io_getirq(avr, AVR_IOCTL_TWI_GETIRQ(0), TWI_IRQ_STATUS), 8 /* bits */ ,
"TWSR" );

printf( "Demo launching:\n"
);
printf( "Demo launching:\n");

while (1)
avr_run(avr);
Expand Down

0 comments on commit a722838

Please sign in to comment.