Monday, January 26, 2009

How to install a bootloader on a STR912 without CAPS or Raisonance

ST recommends CAPS (their GUI) to install the STR912. However, that requires a Raisonance JTAG adapter. You can do it with just IAR EWARM and Segger tools.

  1. Download the JLINK software from Segger.com
  2. Run "J-LINK STR9 Commander" tool (it's under Segger-> JLink ARM 3.95a -> Processor Specific Utilities).
  3. Type "?" to get a list of commands
  4. Type "erase all" to fully erase the chip.
  5. Type "setb 1" to set the boot bit to bank 1.
  6. Type "q" to quit.
  7. Now you can use the flash loader of EWARM to install the code.
You can also use the "secure" command to secure the JTAG port, but that makes debugging via JTAG impossible. :)

Adding an external file to a perl module

Let's say you want a perl module to scream "argh" on failure. You find a argh.wav file and want to bundle it with the perl pm file. The problem is loading the wav file without knowing the full path. Perl's current working directory can be any where, and the location of the wav file or module file may not be in the same location as the starting pl file. To find the starting pl file, you can use the FindBin::Bin module, but this doesn't work for modules. If you want to know the location of the module (pm) file instead, you can use the %INC hash to get it. This hash value gets set when you "use" the pm file. Once you know where the pm file is, you can use the dirname() function to get the directory name, then add the name of the wav file.

Here is an example (in a perl module called "Scream.pm"):


use File::Basename;
use Win32::Sound;

my $wavfile = dirname($INC{"Scream.pm"})."/argh.wav";
Win32::Sound::Play($wavfile);

Thursday, January 15, 2009

Tools for mocking-up C++ classes

I haven't played with this yet, but it seems to have its heart in the right place.

http://code.google.com/p/googlemock/wiki/ForDummies

Neat source of icons


I stumbled upon this cache of free icons if you follow the LGPL.


http://commons.wikimedia.org/wiki/Crystal_Clear

Don't use a virtual function in a constructor

Virtual functions should be used until an object is fully constructed. That is because the constructor builds the virtual function table in pieces. When it is constructing the base class, the derived class virtual function table is not yet constructed. So if you call a virtual function, you are calling the virtual function of the base class not the derived class. This is worse if the base class is a pure interface, ie the virtual functions are declared as pure (ie " =0;"), because you can't call a pure function -- the pointer points to NULL and your program crashes.

Sunday, December 21, 2008

STR91x bootloader trouble, PFQ/BC

Most start-up code (91x_init.s for example) writes 0x191 to the SCU->SCR0 register, which among other things enables the PFQ/BC (Pre-Fetch Queue/Branch Cache). This is normally a good thing. Of the 16 entries in the Branch Cache, 15 are used for generic branches while the 16th one is used only for the special IRQ branch at address 0x18. It appears that this branch cache value is initialized when the PFQ/BC is turned on AND read-only after that. That means if the jump at 0x18 changes, the BC entry will be wrong.

Why would the jump at 0x18 ever change? It changes if you remap the banks, i.e. use BANK1 as the bootloader boot bank, and then switch to BANK0 as the main application. Of course, you shouldn't even do this if you are not using at least rev H of the STR912FAW, but that is a different story (the chip reset circuit has a bug that makes this impossible).

What happens if you don't do something special a programmer's worst nightmare: jumps are random when you let the program run, but if you step through the ASM code, it works fine (because the cache is turned off if you are doing single steps). And the random jumps are not a software bug that you can fix.

But there is a fix. Change the boot code to disable the PFQ/BC, then reenable it later in your code.


; --- Enable 96K of RAM & Enable DTCM & AHB wait-states, disable PFQ/BC until it is flushed. The bootloader has cached the IRQ already and that is BAD!
LDR R0, = SCU_BASE_Address
LDR R1, = 0x0196 ; not 0x0191 as in other boot code!
STR R1, [R0, #SCU_SCR0_OFST]


Later you can reenable using the 91x_lib call (inside __low_level_init() if you are using IAR EWARM):


SCU_PFQBCCmd(ENABLE); // Enabled Branch Cache feature of STR91x.

Friday, December 19, 2008

Anatomy of STR912 boot sequence in EWARM

Power-on: waits til voltages rise above Low-Voltage Detect, then sets PC to 0x00000000

First instruction jumps to Reset Handler. The jump is usually a LD PC,[PC+xxx] command that loads the PC from a table just past the end of the vector handlers.

Reset Handler is always written in ASM because it needs to do things that are unsafe in C, like initializing flash memory interfaces, RAM interfaces and needs access to the CPSR register, which you don't have from C. This usually sets the flash memory interface, sets up stack space for each of the system modes, then jumps to ?main. In EWARM, the Reset Handler is installed at 0x180, and is given the symbol __iar_program_start. If you do not write your own, EWARM will pick one for you.

?main - This does basically 3 things:
  1. Call __low_level_init(). You can write this in C, as long as you are careful not to use global variables. This is useful for setting the clock speed and other things that don't need to be done in ASM. EWARM has a default dummy __low_level_init().
  2. Call __iar_init_memory. Not something the user should deal with. This is where the C global variables are initialized, and global C++ objects are constructed.
  3. Call main. This is the traditional C entry point.
main - Your plain old C function where the real fun begins.

I've seen several examples (the code from ST) that does the low level init in main() and not earlier. This is not a big deal, but it means that the clock will be running much slower on power-up, so if you are doing a lot of C++ initialization, it will boot slower (perhaps 4x slower if you are using a 25 MHz crystal and can run the PLL at 96 MHz).