portDISABLE_INTERRUPTS and portENABLE_INTERRUPTS

zhuchunxia wrote on Monday, June 13, 2016:

Hi :

I have a trouble on portENABLE_INTERRUPTS and portDISABLE_INTERRUPTS. before I put the question out, I want to describe my CPU profile on interrupt. my CPU has no NVIC as similar as Cortex M3. it has a PSR register to disable interrupt and enable interrupt by set IE bit and clear IE bit

// default PSR value 
portLONG cpu_psr = 0x80000100;
// x = 1, disable interrupt
// x = 0, enable interrupt
portLONG ulPortSetIPL( portLONG x)
{
	if (x)
	{
		cpu_psr = GetCPUPSR();
	}
	else
	{
		SetCPUPSR(cpu_psr); 
	}
	
	return cpu_psr;
}
/*
get PSR value and clear IE bit to disable interrupt
*/
static inline portLONG GetCPUPSR (void)
{
	portLONG flags;
	
	 __asm__ __volatile__(
		"mfcr   %0, psr \n"
		"psrclr ie\n"
		:"=r"(flags)
		:
		:
		);

	return flags;
}
/*
set PSR value
*/
static inline void SetCPUPSR (portLONG newMask)
{
		__asm__ __volatile__(
		"mtcr   %0, psr \n"
		:
		:"r" (newMask)
		:"memory"
		);	
}
// enable interrupt by set IE bit in PSR
static inline void vPortEnableInterrupt(void)
{
	__asm__ __volatile__(
		"psrset ie\n"
		"rts	\n"
		);

}
// disable interrupt by clear IE bit in PSR
static inline void vPortDisableInterrupt(void)
{
	__asm__ __volatile__(
		"psrclr ie\n"
		"rts	\n"
		);

}

case 1
define portDISABLE_INTERRUPTS() ulPortSetIPL(1)
define portENABLE_INTERRUPTS() ulPortSetIPL(0)
define portSET_INTERRUPT_MASK_FROM_ISR() GetCPUPSR()
define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) SetCPUPSR(x)

result: all task can work correctly…

case 2
define portDISABLE_INTERRUPTS() vPortDisableInterrupt()
define portENABLE_INTERRUPTS() vPortEnableInterrupt()
define portSET_INTERRUPT_MASK_FROM_ISR() GetCPUPSR()
define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) SetCPUPSR(x)

result: first task can’t run and no task switch…

what I understand is portDISABLE_INTERRUPTS() and portENABLE_INTERRUPTS() is only used to disable all interrupts and enable interrupts purlly… but in case 1, ulPortSetIPL save PSR value in cpu_psr variable. and case 2 doesn’t save it …

is there other reason to cause it ?

davedoors wrote on Monday, June 13, 2016:

Dont know about your code but these macros always have to work the same way.

portDISABLE_INTERRUPTS() -> leave interrupts disabled
portENABLE_INTERRUPTS() -> leave interrupts enabled
portSET_INTERRUPT_MASK_FROM_ISR() -> leave interrupts disabled and return prior interrupt state, only needed when interrupt nesting is supported otherwise leave undefined
portCLEAR_INTERRUPT_MASK_FROM_ISR(x) -> set interrupt state to x, only needed when interrupt nesting is supported otherwise leave undefined

zhuchunxia wrote on Monday, June 13, 2016:

if interrupt nesting is not support, no need define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) and portSET_INTERRUPT_MASK_FROM_ISR() macro ?

zhuchunxia wrote on Monday, June 13, 2016:

I use a soft trap as pendSV trap to switch task… but the cpu has no NVIC to set the trap in lower priority… does it bring the result ?