Those of you with long memories will remember the first blog about this board:
Ultra cheap and Tiny FPGA Board
I've built up a couple of boards and got them running some very simple start up software and VHDL.
The good news is that there are only two small bugs on the board, neither is too grim to fix.
Other E14 members (notably Jan Cumps ) have been Roadtesting the MAX32660 which provides one half of the good stuff on this board.
My approach to coding the processor is very different so I've hit a different stream of snags and I'll talk a little about one of them and it solution.
But first the building !
The MAX32660 variant I used comes in a 0.4mm pitch QFN package which is too tricky for pure hand soldering. I used a bought in metal stencil for solder paste printing, hand placed the parts using microscope and tweezers and re-flowed in a CIF drawer type re-flow oven.
The results were quite good, no shorts on either the 0.4mm pitch or 0.5mm pitch QFNs. It's not quite a home process, the screen printer and the oven are a bit pricey for unpaid work - cheaper Chinese alternatives exist.
PCB with solder paste
PCB with components before re-flow
PCB after re-flow and hand soldered parts fitted
Debugging on Veroboard breakout board with ARM Ulink and logic analyser attached
PCB Bugs - C10 fouls J2 and wire link on U3
Test Code
The test code on the FPGA just sets up the PLL to turn the 25MHz clock signal from the oscillator chip into a 50MHz signal output on one pin.
The C code on the MAX32660 sets up some IO pins and uses SPI to load the FPGA withe its 100k byte bit pattern. I used bit banged SPI which saves me the trouble of getting the MAX32660 SPI hardware going (I'll do that later.)
But to bit bang you need need to be able to set output pins high and low and you would like to be able to do it reasonably quickly.
To test the speed of pin toggling I wrote this into Maxim's GPIO example project:
while(1)
{
GPIO_OutSet(&gpio_out); //official Maxim way of setting pin
GPIO_OutClr(&gpio_out);
}
this is pretty grim in that you need to define gpio_out and set it up like this:
gpio_cfg_t gpio_out;
gpio_out.port = GPIO_PORT_OUT;
gpio_out.mask = GPIO_PIN_OUT;
It's a bit bonkers because the chip only has ONE port - so it must be set to zero but every pin will need you to set its port to zero. I assume this is an attempt to make the code general across the chip family but it is really ugly.
But it gets much, much worse:
When we run it the toggle rate is 0.86MHz, on a processor with 96MHz core clock and a 48MHz peripheral clock - ugh !
There's a quick gain by turning the instruction cache on (why provide example code that doesn't do this ?)
So add
ICC_Enable();
at the beginning of your c code and the toggle rate improves to 2.347MHz, which is better but still dreadful.
The problem is GPIO_OutSet() which is a full on function call, if we replace the calss to the official functions with
gpio->out_set = (1u << 4);
gpio->out_clr = (1u << 4);
the toggle rate gets up to a more respectable 7.97Mhz.
gpio is the single gpio port and is defined in one of the Maxim header files which is how I know about the out_set and out_clr registers, which are NOT documented in the chip's User Manual.
It's not very pretty to do it quite like this so I've defined some macros to make it nicer:
first we define our pins like this:
#define LED GPIO0,4 // I've kept up with allowing more than one port, although it is a bit daft on this processor
then (in a header file where we only have to look at it once) we define the macros:
#define GPIO(g, p) GPIO_(g, p)
#define GPIO_(g, p) g
#define PIN(g, p) PIN_(g, p)
#define PIN_(g, p) p
#define GPIO0 ((mxc_gpio_regs_t*)MXC_BASE_GPIO0)
#define PIN_SET(p) (GPIO(p)->out_set = 1 << PIN(p))
#define PIN_CLR(p) (GPIO(p)->out_clr = 1 << PIN(p))
and now we can toggle the pins with:
PIN_SET(LED);
PIN_CLR(LED);
(In the spirit of full disclosure - I did not write the original version of those macros, that honour belongs to my son, Edward, who did them originally for STM32Fxx IO)
The first person who can explain simply why the macros must be defined in two steps (or suggest an alternative that works) can have a board of their very own !
Of course the macros PIN_SET and PIN_CLR go at the same speed as gpio->out_set = (1u << 4);
It's 9.25x faster than Maxim's demo code.
I'm thinking I'll make a breakout board next - any suggestions as to what to put on it are welcome - I want something simple that you can't easily do without the FPGA.
MK
Top Comments