Wednesday, December 2, 2015

AT91SAM7 Code Development

I recently had to develop code for the AT91SAM7 microcontroller.  AT91SAM7 has an ARM7TDMI processor core, an architecture that has been superseded by Cortex-M3.

The first thing was how to program the on-chip flash memory.  The board was an old existing board which has the JTAG connection.  OpenOCD could be an option if I could make use of an JTAG dongle (I had a Stellaris eval board).  But AT91SAM7 had other ways of in-system flash programming.  Atmel supplied the SAM Boot Assistant (SAM-BA) for ISP through the COM or USB port; it was available for both Windows and Linux.  There was also an open source SAM-BA application, BOSSA.  I installed Atmel's SAM-BA and connected the device and installed the device driver (CDC).  The device showed as a COM port.  I started the SAM-BA application and specified the port and hit Connect, but nothing happened.  After a little search and reading the device manual, I realized that I needed to restore the SAM-BA boot, which is done pulling TST, PA0, PA1 and PA2 high for 10 seconds at the power up.  Unfortunately, none of these pins had been brought out.  So I had to solder a few hay wires to a LQFP-64 device.  Once the SAM-BA Boot was restored to the first two sectors of the on-chip flash, the SAM-BA application then worked and displayed the memory.  Later I realized that PA0-2 were pulled up internally, so only TST needed to be pulled up.

The second thing was to get the compiler toolchain.  GCC was the obvious choice.  ARM GCC could be downloaded from either launchpad.net/gcc-arm-embedded or Atmel.  The current version was 4.9.3.   I installed the version from launchpad.  I took the simplest example from at91sam7s-ek and modified slight to just blink one LED.  The compilation went smoothly and a binary file  was generated.  I used SAM-BA to write it to flash and verified it was written correctly.  After power cycling, nothing happened and the USB device was no longer recognized, which was understandable since the SAM Boot was overwritten.  There was no indication the code was being executed.  I suspected the compiler, perhaps it was not the right version to support the older device.  I tried the Atmel distributed GCC, which was also 4.9.3, but no luck.  I was also ready to go through my stash to find the Stellaris JTAG board.  I downloaded WinARM, the last version was 20060606, GCC 4.1.1.  I compiled with that, but still did not work.  The desperation started to set in.  Then I decided to try Keil MDK-Lite 4.50, that I had used before.  I tried the Blinky project with slight modification and downloaded with SAM-BA; it worked.  That was a relief; but MDK-Lite had the 32KB code/data limitation, so now I had to find out how to make GCC work.  I went back to try various versions of GCC, but same result.   I recalled that Atmel stated that their code was compiled by the yagarto.  I installed yagarto-20121222 (GCC 4.7.2) and it worked.  I would like to figure out what the problems with the other distributions, but now it was the time to move on.

The UART serial port was the next thing.  It just worked, no Herculean struggle here.  It worked to 230400 baud.  I needed 460800 baud, but the integer divisor caused too much error.  So I first tried 8x oversampling instead of the usual 16x, but no effect.  Then I tried the fractional divisor, also no effect.  It started getting puzzling.   Reading the manual again, I realized that I was using the debugging serial port instead of the regular USART and it appeared that both the 8x oversampling and the fractional disivor were not supported by DBGU.  I used it because it was had a connector and the USART0 and USART1 pins were not brought out.  I had to solder some haywires again.  I chose USART1.  It did not work initially until I realized that the DBGU library code was interfering with the printf that I tried to use.  After I left out the DBGU code, USART1 worked to 460KBaud.

I could finally get to interface the external device on the SPI bus.  After reading the data sheet, I set up the timing, polarity and other options.  I figured that I'd better check the timing on the scope before I connected the external device.  I saw the SCK and MOSI signals on the scope when I run the code,  but CS did not assert..  After chasing around a little, I realized it was mapped to the wrong pin by using Atmel's board definition.  I hooked up the external device and got zeros initially.  I tweaked the code for reading and it worked.

Now all pieces were in place to complete the application.  And I would optimize with using interrupts and DMA later.



No comments:

Post a Comment