STR912 ARM 9 Webpage
Updated Aug 7, 2007


August 7, 2007

VIC Bug in STR91x ARM 9 Microcontroller

    Well, if this isn't a kick in the teeth... :-)

    If you were to run the demo below, and used the RS232 port, you would find that eventually, the processor would crash.  I knew that when I posted the code.  But hey...it is free.

    Well, here all along I thought it was a problem with my RTOS, but, as it turns out, it was a problem with the ST Microsystems ARM 9 Vector Interrupt Controller.  It seems that there is a problem with how VIC0 and VIC1 talk to each other, and under certain circumstances, when the interrupt service routine reads VIC0 to find out what vector it should jump to, well instead, we get a NULL pointer back instead.  This causes the control to jump through the reset vector, and just causing a real mess all around.

    The original code in the isr (this is just a snippet that deals with the VIC) looked like this:

       LDR    r0, = VectorAddress
       LDR    r0, [r0]                   ; Read the routine address
       LDR    r1, = VectorAddressDaisy
       LDR    r1, [r1]
       ; Padding between the acknowledge and re-enable of interrupts
       ; For more details, please refer to the following URL
       ; http://www.arm.com/support/faqip/3682.html
       NOP
       NOP
       LDR    lr, = IRQ_ReturnAddress ; Read the return address.
       BX     r0                      ; Branch to the IRQ handler.
IRQ_ReturnAddress
       LDR    r0, = VectorAddress     ; Write to the VectorAddress to clear the
       STR    r0, [r0]                ; respective interrupt in the internal interrupt
       LDR    r1, = VectorAddressDaisy  ; Write to the VectorAddressDaisy to clear the
       STR    r1,[r1]                   ; respective interrupt in the internal interrupt

    I modified it like so:

       LDR    r0, = VectorAddress
       LDR    r0, [r0]                   ; Read the routine address
       LDR    r1, = VectorAddressDaisy
       LDR    r1, [r1]
       ; Padding between the acknowledge and re-enable of interrupts
       ; For more details, please refer to the following URL
       ; http://www.arm.com/support/faqip/3682.html
       NOP
       NOP
       LDR    lr, = IRQ_ReturnAddress ; Read the return address.
       CMP    r0,#0               ;is the VIC0 VAR zero?
       BEQ    skipvic0
       BX     r0                      ; Branch to the IRQ handler.
                                          ; We don't need a jump here because
                                           ; The return address is set to IRQ_ReturnAddress
skipvic0
       CMP     r1,#0              ;is the VIC1 VAR zero
       BEQ    IRQ_ReturnAddress
       BX    r1
IRQ_ReturnAddress
       LDR    r0, = VectorAddress     ; Write to the VectorAddress to clear the
       STR    r0, [r0]                ; respective interrupt in the internal interrupt
       LDR    r1, = VectorAddressDaisy  ; Write to the VectorAddressDaisy to clear the
       STR    r1,[r1]                   ; respective interrupt in the internal interrupt

    This seems to work 100% reliable.  I have run a torture test for about 12 hours, did over 5 million transfers of 32 bytes to the ST arm9, without a single failure.

    Anyway, I hope this helps someone.

    It should also be  noted that there is a rumor that new silicon does not have this problem.  However, there is some debate over that, and documentation from ST has not indicated to me at least that the problem has been solved.  So, until I get new parts, I won't be able to report on if this problem has been fixed or not.



Real Time Operating System

        For a lack of a better name, I will call this JpRtOS :-)

    I think you will like some of the features...best feature of all...it is totally FREE!

    It is a very small RTOS with very few features.  But, it has basically everything you need.  I have only tried it on an ARM9.  The context switcher uses instructions that are found on the ARM7, so, it may be that it will work on the ARM7 as well.


    Here are a list of functions:

Task Functions:

extern void CreateTask(TCB *t, void (*task)(void *),long *stack, int stacksize,int priority,char *name,void *arg);
extern void IrqSwap(void);
extern void InitTask(void);
extern void Yeild(void);
extern ECB *NewSemaphore(int InitCount,int Mode,char *name);
extern void CreateSemaphore(ECB *e,int InitCount,int Mode,char *n);
extern int PendSemaphore(ECB *e, int Timeout);    //wait for semaphore availiable
extern int PostSemaphore(ECB *e, int Value);    //signal semaphore availiable
extern void TimerTicker(void);
extern void vPortYieldProcessor(void);
extern void vPortStartFirstTask(void);
extern int TimeDelay(int mSec);

Priority Queue Functions:

extern int Insert(PQ* q,void *item);
extern int Delete(PQ* q,void **target);
extern void *Get(PQ* q);    //return pointer to highest priority item
extern int NumElem(PQ* q);    //get total number of items
extern int Replace(PQ* q,void **target,void *item);
extern int Remove(PQ* q,void **target,int (*cmp)(void **,void **),void *item);
extern void *GetI(PQ* q,int i);    //return pointer to indexed item

I/O functions:

extern int CioAddHandler(char * devname,H_JVEC *t);
extern IOCB *CioOpen(char *devname,int mode);
extern int CioClose(IOCB *I);
extern int CioGetC(IOCB *I);
extern int CioRead(IOCB *I,char *b,int n);
extern int CioPutC(IOCB *I,int c);
extern int CioWrite(IOCB *I,char *b,int n);
extern int CioStatus(IOCB *I,int mode);
extern int CioXIO(IOCB *I,int cmd,...);
extern void CioInit(void);

Here is the source code for the operating system.

Here is a demo program for the ST Microsystems 912 Eval Board.  Now, this is basically the demo that they supply with the board, however, I modified the code to use the RTOS.  The project is for the IAR compiler.  There are also three tasks that talk to the three RS232 ports on the board.  You will need to monkey with the jumpers on the board to make the RS232 ports function correctly.