Using TWI on the Xplain Demo board - Newbie needs help

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Coming from an assembler and old-fashioned C background, I am struggling a bit with the new way of programming as in the software-framework that comes with the Xplain demo kit. Perhaps a kind soul can push me in the right direction to get me going?

My task is relatively simple: receive data via a TWI (slave) interface, using the Xplain demo board (Xmega128A1) and display that data on the Display Xplained screen. Refresh.

To that purpose I have wired the SDA to port F0 and SCL to port F1 (switch 1 and 2 on the demo board) to communicate with an external master (a mega328P, happily talking to other slaves already)

Using the Xplain-demo of the software-framework, I modified the app_font.c so it is ready to display the incoming data.

I have further found the TWI_example.c from the AVR1308 tutorial (doc8054) and related twi_slave_driver.c and .h

Here is the big question:
How do I combine/install/implement the TWI driver, so I can fetch the data and display it? How do I tell the driver to use the port F for TWI?

Any help/nudge/push in the right direction would be greatly appreciated.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, progressed a little further: figured out how to tell it to use Port F and the tutorial is running fine receiving data from an external master.
Now I am trying to embed this function into my main.c routine, which is the Xplain-demo straight out of the book. Here it fails with an obscure error, which I don't seem to be able to get rid of:

Build started 19.6.2011 at 23:05:05
CC apps/display-demo/main.o
LD display-demo.elf
apps/display-demo/main.o: In function `main':
C:\xplainsf1\source\build\display-demo\xplain\GNU/../../../../apps/display-demo/main.c:103: undefined reference to `TWI_SlaveInitializeDriver'
C:\xplainsf1\source\build\display-demo\xplain\GNU/../../../../apps/display-demo/main.c:104: undefined reference to `TWI_SlaveInitializeModule'
make[1]: *** [display-demo.elf] Error 1
make: *** [delegate] Error 2
Build failed with 2 errors and 0 warnings...

needless to mention, I have included the twi_slave_driver.c and .h files and #inlcude twi_slave_driver.h in the main.c file.

What is happening? Why does the error only show up after the build and not immediately?

Of course I am using the same files as in the TWI exercise, copy and paste, so no typos...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Luftwaffle wrote:
I have included the twi_slave_driver.c and .h files and #include twi_slave_driver.h in the main.c file.

But where are you including them. The error message is saying that the linker cannot find the object file containing the twi driver methods you have referenced in main.c. It seems that either twi_slave_driver.c is not being built, or it is not being passed in the final linking step; do you see a twi_slave_driver.o anywhere?

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is indeed no twi_slave_driver.o to be found. All others are there. :(

The files are at the same level as main.c and all others. I have left the file structure untouched.

The #include is right at the beginning of the main.c file. In fact the whole file isn't particularly long:

/**
 * Display demo
 */
#include 
#include 
#include 
#include 

#include 

#include 
#include 
#include 

#ifdef CONFIG_TOUCH_RESISTIVE
#include 
#endif

#include "twi_slave_driver.h"
#include "app_desktop.h"

#ifdef CONFIG_FS_TSFS
#include 
#include 
#include 
#include 

DECLARE_SPI_MASTER(CONFIG_APP_DATAFLASH_SPI_ID, my_master);
DECLARE_SPI_DEVICE(CONFIG_APP_DATAFLASH_SPI_ID, my_device);

/* PG ADDED STUFF */

#define SLAVE_ADDRESS    0x30			// address is shifted left by one !!
#define NUM_BYTES 	8					// this might change
#define CPU_SPEED       2000000	
#define BAUDRATE 100000
#define TWI_BAUDSETTING TWI_BAUD(F_CPU, BAUDRATE)

/* Global variables */
TWI_Slave_t twiSlave;      /*!< TWI slave module. */

void TWIF_SlaveProcessData(void);

/* END OF PG ADDED STUFF */

static struct block_device     *bdev;
static struct workqueue_task   ready_task;
struct tsfs                    myfs;
struct spi_master              *master;
struct spi_device              *device;

/* PG ADDED functions */

void TWIF_SlaveProcessData(void) {
	uint8_t bufIndex = twiSlave.bytesReceived;
	twiSlave.sendData[bufIndex] = (twiSlave.receivedData[bufIndex]);
}

/* END OF PG added functions */

static void tsfs_ready_callback(struct workqueue_task *task)
{
}

static void spi_ready_callback(struct workqueue_task *task)
{
	workqueue_task_set_work_func(&ready_task, tsfs_ready_callback);
	tsfs_init(&myfs, bdev, &ready_task);
}
#endif

int main(void)
{
	cpu_irq_enable();
	sysclk_init();
	dbg_init();
	board_init();
	led_activate(BOARD_LED2_ID);
	workqueue_init(&main_workqueue);

/* PG ADDED FUNCTIONS */

	/* Initialize TWI slave. */
	TWI_SlaveInitializeDriver(&twiSlave, &TWIF, TWIF_SlaveProcessData);
	TWI_SlaveInitializeModule(&twiSlave, SLAVE_ADDRESS, TWI_SLAVE_INTLVL_LO_gc);
	
	/* Enable LO interrupt level. */
	PMIC.CTRL |= PMIC_LOLVLEN_bm;
	sei();

/* END OF PG ADDED FUNCTIONS */

#ifdef CONFIG_TOUCH_RESISTIVE
	touch_init();
	touch_enable();
#endif
	gfx_init();
	membag_init(CPU_DMA_ALIGN);
	win_init();

#ifdef CONFIG_FS_TSFS
	master = spi_master_get_base(CONFIG_APP_DATAFLASH_SPI_ID, &my_master);
	device = spi_device_get_base(CONFIG_APP_DATAFLASH_SPI_ID, &my_device);

	spi_enable(CONFIG_APP_DATAFLASH_SPI_ID);

	spi_master_init(CONFIG_APP_DATAFLASH_SPI_ID, master);
	spi_master_setup_device(CONFIG_APP_DATAFLASH_SPI_ID, master, device,
			SPI_MODE_0, CONFIG_CPU_HZ, BOARD_DATAFLASH_SS);

	workqueue_task_init(&ready_task, spi_ready_callback);
	bdev = dataflash_blkdev_init(CONFIG_APP_DATAFLASH_SPI_ID, master, device,
			&ready_task);
#endif

	app_desktop_setup();

	mainloop_run(&main_workqueue);

}

/*! TWIC Slave Interrupt vector. */
ISR(TWIF_TWIS_vect)
{
	TWI_SlaveInterruptHandler(&twiSlave);
}

Normally, if the compiler can't find a file, it complains straight away and not at the second run. What's happening here?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you building with AVR Studio or with an external make file. The symptoms are of main.c being built correctly ( it just needs the .h which it seems to be finding ), and failing only at the link. If you do not see a twi_slave_driver.o then it is not being built. That could be because there are errors in building, or it could be because the build system is never trying - if that's the case, you wouldn't receive any error until trying to link.

So we will need to know how this is all being built.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using the makefile which comes with the display-demo. Without it, it throws up all kinds of errors. The display-demo is extremely nested (all kinds of links to all kinds of files within the tree structure) so I left this untouched. But even the makefile links up to a chain of other makefiles and I probably haven't found all the dependencies. Going through it with a fine comb now...

Thanks for your help so far. Has given me a few ideas where to look.

Peter

P.S. what optimization would you use for the debug run?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Martin,

thanks for the tip with the makefile. I have manually amended it to include the twi_slave_driver.c and .h and hey presto! it compiles without errors now.
But this wouldn't be a proper steeple chase if the next snag wouldn't show up immediately: The interface isn't active yet :(

My other board is set up continuously trying to send a string of bytes to this slave but obviously can't get past the SLA-W command (I am watching this parallel on an Oscilloscope). In the 1308 exercise it was slightly simpler, since you had only one file and loop to deal with. In the display-demo, the main.c launches the desktop app and that in turn launches my little display routine.

I have put the complete code in the main.c file within the main() loop, this should keep it alive, shouldn't it?

Still, no joy yet with this little gem.

Am I barking up the wrong tree here?