| Details |
Message |
|
Read-Only
Author Mark Bush
Posted 31-Jan-2007 16:24 GMT
Toolset ARM
|
 Semaphore problem
Mark Bush
Has anyone experienced problems using semaphores in interrupt
routines? I have a UART ISR that places a received character into a
FIFO buffer and sets a semaphore using isr_sem_send().
void SerialIsr(void) __irq
{
volatile uint8_t Temp;
switch( COMIID0 & 0x0fU )
{
case MSI:
Temp = COMSTA1;
break ;
case THRE:
break;
case RDA:
Temp = (char_t)COMRX;
if(BufferCount < BUFFER_SIZE)
{
BufferCount++;
isr_sem_send(SerialSemaphor);
}
break;
case RLS:
Temp = COMSTA0;
break ;
default:
case NO_PENDING_INTERUPT:
break;
}
}
The GetByte routine waits on this semaphore for a specified
timeout period. If the semaphore is set, the next available char in
the buffer is returned, otherwise a user defined timeout character is
returned. The problem I am getting is that it appears that the
semaphore is becoming corrupted and generating a lot of tokens. I
test this by trapping the condition where os_sem_wait(sem) !=
OS_R_TMO and the buffer is empty. I.e. a semaphore token has been
returned but the buffer is empty.
note that I have replaced the buffers with a counter for
simplicity.
char_t GetByte (uint16_t File, uint32_t Timeout)
{
OS_RESULT Result;
char_t RetValue;
uint32_t Copy;
DISABLE_UART_INT();
Copy = SerialSemaphor[0];
Result = os_sem_wait(SerialSemaphor,Timeout);
if(Result != OS_R_TMO && BufferCount == 0U)
{
Result = 1;
}
if(BufferCount == 0)
{
RetValue = ( (char_t)GETC_TIMEOUT_CHAR );
}
else
{
BufferCount--;
}
ENABLE_UART_INT();
return RetValue;
}
If I then look at the semaphore object I can see that the most
significant 16 bits of the first 32 bit word in the semaphore object
is 0xFFFF (I am assuming this is the token counter). Subsequent calls
os_sem_wait() return OS_R_OK, decrementing the token counter each
time. This has the result that the thread is not released until the
os_sem_wait() has been called sufficient times to decrement the token
counter to zero (The os_sem_wait() is the only function to release
the thread).
The target is an ADuC7021 and I am using the RTL-ARM.
|
|
|
Read-Only
Author Thomas Brandl
Posted 2-Feb-2007 09:40 GMT
Toolset ARM
|
 RE: Semaphore problem
Thomas Brandl
I'm not sure, but as far as understand your code, you're disabling
the IR so that isr_sem_send() is never really called:
DISABLE_UART_INT(); // disable SerialIsr?!
Copy = SerialSemaphor[0];
Result = os_sem_wait(SerialSemaphor,Timeout);
...
// will only be reached when timed out but never
// when char is received
|
|
|
Read-Only
Author Mark Bush
Posted 19-Feb-2007 08:46 GMT
Toolset ARM
|
 RE: Semaphore problem
Mark Bush
That is true and my code is incorrect, but that's not the
problem.
I am finding that periodically the semaphore count is decrementing to
0xFFFF (-1) when os_sem_wait() is called. When this occurs, the
thread will not release until the semaphore count returns to
zero.
This only happens when the serial ISR is being fired.
|
|
|
Read-Only
Author Mark Bush
Posted 20-Feb-2007 11:04 GMT
Toolset ARM
|
 RE: Semaphore problem
Mark Bush
I have ported this code to the lpc2131 and it works fine.
The problem seems to be specific to the aduc7021 - could it be to
do with the different interrupt controllers?
|
|
|
Read-Only
Author Franc Urbanc
Posted 26-Feb-2007 13:05 GMT
Toolset ARM
|
 RE: Semaphore problem
Franc Urbanc
Yes there is a problem with aduc7021 devices interrupt controller.
The problem is in a device inability to mask forced-programming
software interrupts. We have implemented a workaround in RL-ARM
version 3.00. The latest update for aduc7021 RTOS configuration has
been done in version 3.03a.
What version of RL-ARM are you using?
|
|
|
Read-Only
Author Mark Bush
Posted 26-Feb-2007 13:58 GMT
Toolset ARM
|
 RE: Semaphore problem
Mark Bush
I've got everything that came with uVision v3.5. I'm not sure how
to find the version of the RL-ARM, but is located in a directory
\rv30 in the installation directory.
The config file is V3.04 / 10-jan-2007. The only mod I have done
to this file is to comment out the interrupt vectors as these are
handled in another file.
here is my interrupt vectors code
IRQSTA_ADR EQU 0xFFFF0000 ; IRQSTA Address
IMPORT SerialIsr ; User serial interrupt Function
mSer_IRQ EQU (1<<14) ; User serial interrupt Mask ( UART )
; OS Interrupt Functions
IMPORT os_clock_interrupt
IMPORT os_def_interrupt
mIRQ_OS EQU ((1<<2) | (1<<1)) ; OS IRQ Mask (SWI + Timer )
AREA IRQ, CODE, READONLY
ARM
PRESERVE8
ALIGN
EXPORT IRQ_Handler
IRQ_Handler
STMDB SP!,{R0} ; Save R0
LDR R0,=IRQSTA_ADR ; Load IRQSTA Address
LDR R0,[R0] ; Load IRQSTA Value
TST R0,#mIRQ_OS ; Check OS IRQ Flag
LDMNEIA SP!,{R0} ; Restore R0
LDRNE PC,=os_clock_interrupt ; OS Clock IRQ Function
TST R0,#mSer_IRQ ; Check serial IRQ Flag
LDMNEIA SP!,{R0} ; Restore R0
LDRNE PC,=SerialIsr ; UART interrupt
LDMIA SP!,{R0} ; Restore R0
LDR PC,=os_def_interrupt ; OS Default IRQ Function
AREA FIQ, CODE, READONLY
ARM
PRESERVE8
ALIGN
EXPORT Undef_Handler
EXPORT PAbt_Handler
EXPORT DAbt_Handler
EXPORT FIQ_Handler
Undef_Handler B Undef_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
FIQ_Handler B FIQ_Handler
END
|
|
|
Read-Only
Author Franc Urbanc
Posted 27-Feb-2007 06:32 GMT
Toolset ARM
|
 RE: Semaphore problem
Franc Urbanc
Try to put the OS IRQ handler the last in the chain as you see in
the RTX_Config.c configuration. It should have the lowest
priority.
LDR R0,=IRQSTA_ADR ; Load IRQSTA Address
LDR R0,[R0] ; Load IRQSTA Value
TST R0,#mSer_IRQ ; Check serial IRQ Flag
LDMNEIA SP!,{R0} ; Restore R0
LDRNE PC,=SerialIsr ; UART interrupt
TST R0,#mIRQ_OS ; Check OS IRQ Flag
LDMNEIA SP!,{R0} ; Restore R0
LDRNE PC,=os_clock_interrupt ; OS Clock IRQ Function
LDMIA SP!,{R0} ; Restore R0
LDR PC,=os_def_interrupt ; OS Default IRQ Function
Did you declare your UART handler with attribute __irq?
__irq void SerialIsr (void);
Do you acknowledge correctly UART serial interrupts?
|
|
|
Read-Only
Author Mark Bush
Posted 27-Feb-2007 11:16 GMT
Toolset ARM
|
 RE: Semaphore problem
Mark Bush
I've changed the interrupt chain to put the IRQ_OS at the end, but
the problem still occurs.
SerialIsr() is declared using attribute __irq.
I have changed the ISR to insure as far as I can tell from the
data sheet that the interrupt is acknowledged properly as follows
#define ENABLE_UART_INT() IRQEN |= (1<<14)
#define DISABLE_UART_INT() IRQCLR = (1<<14)
__irq void SerialIsr(void)
{
volatile uint8_t Temp;
uint8_t IntSource;
DISABLE_UART_INT();
Temp = COMSTA1; /* Clear any modem status interrupts as these are not serviced */
Temp = COMIID0; /* Clear Transmit buffer empty interrupt */
IntSource = COMSTA0;
if(IntSource & (1<<SLR_THRE))
{
}
if(IntSource & (1<<SLR_RDR))
{
Temp = (char_t)COMRX;
if(BufferCount < BUFFER_SIZE)
{
BufferCount++;
isr_sem_send(SerialSemaphor);
}
}
ENABLE_UART_INT();
}
If you want I can send you the full source code.
Your help is much appreciated.
|
|
|
Read-Only
Author Franc Urbanc
Posted 28-Feb-2007 06:07 GMT
Toolset ARM
|
 RE: Semaphore problem
Franc Urbanc
Yes please, send your code to: support@keil.com
|
|