Close

Announcing BeagleBone Black Support!

A project log for VGA Graphics Over SPI and Serial - VGATonic

640x480 (and 848x480!) Color VGA Video Card for Microcontrollers and Single Board Computers

pkPK 07/18/2015 at 01:360 Comments

Hey everyone, I'm very happy to announce support for the BeagleBone Black today!

As per custom, here is the BBB rev 3 displaying itself with VGATonic!

Difficulties

Unfortunately, we had a few difficulties in getting VGATonic to run on the BBB (an initially frustrating yet ultimately successful experience!).

First, SPI DMA seems to be broken, which is a major issue with the BBB since the SPI driver in the kernel automatically does DMA when over 160 bytes are sent (we send 307,200 for 640x480x8bpp mode...). I'm using a 3.8.xx kernel and had some issues upgrading due to missing scripts, however it does appear this bug cropped up again even in recent kernels. I'll revisit it when there is a fix, though, since I would like to squeeze out maximum performance on the popular BBB, and I think it was working at some point in the 3.14.* kernels. (Please ping me if you see an update or know more!)

It was an easy enough workaround, though: write 159 bytes at a time, maximum. VGATonic's main driver needed an update to support this, but it does seem a useful feature (it looks like the Edison will need something similar). Here are the gory details of how that function works now. It should be relatively self-explanatory, but let me know if you would like more explanation:

static int vgatonic_write_data_buf(struct vgatonicfb_par *par, u8 *txbuf, int size)
{
	/* Chip Select low to warn VGATonic something is coming */
	gpio_set_value(par->cs, 0);

	int bytesLeft = size;
	int retval = 0;
	while (bytesLeft > 0) {

	  if (bytesLeft > par->maxSPIBytes) {
	
	    /* Full Speed SPI */
	    struct spi_message	m;
	    struct spi_transfer	t = {
	      .tx_buf		= txbuf+(size-bytesLeft),
	      .len		= par->maxSPIBytes,
	      .speed_hz         = par->spiSpeed,
	    };
	    spi_message_init(&m);
	    spi_message_add_tail(&t, &m);
	    int retval = spi_sync(par->spi, &m);
	    bytesLeft -= par->maxSPIBytes;
	  } else {
	    	    /* Full Speed SPI */
	    struct spi_message	m;
	    struct spi_transfer	t = {
	      .tx_buf		= txbuf+(size-bytesLeft),
	      .len		= bytesLeft,
	      .speed_hz         = par->spiSpeed,
	    };
	    spi_message_init(&m);
	    spi_message_add_tail(&t, &m);
	    int retval = spi_sync(par->spi, &m);
	    bytesLeft = 0;
	  }
	  
	  
	}
	
	/* Chip Select high to warn VGATonic something is done */
	gpio_set_value(par->cs, 1);


	return retval;
}

So, we keep doing 159 byte chunks until we have sent 307,200. And, yes, this does hurt performance.

Performance

In theory, the BBB is an excellent candidate for VGATonic since it can support 48 MHz SPI. That's a nice 19.5 Frames Per Second worst case for 640x480x8bpp (and over 60 for most other modes!). Unfortunately, due to SPI overhead due to the small transfers and not using DMA, most functions are closer to 7-10 FPS (Dropping to 320x240 on the BBB looks excellent though, and often maxes out the 60Hz refresh!). Here's an example of what I mean, where mouse movements can drive SPI to take up 50% of the CPU:

I will say this, though - it's very usable even with the 159 Byte sends - a credit to a nice platform! I'm happy to update the driver when the SPI issue is fixed - or if I can find a kernel where it is patched already. But, for now, this is a great start - let me know if you get it working!

Discussions