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.