CortexM3 and gcc port

I am using Cortex-M3 port for STM32 and GCC.
I found that macros: portCLEAR_INTERRUPT_MASK_FROM_ISR
and
portCLEAR_INTERRUPT_MASK() are not fully implemented. It is shame because I need such macros to create function what call FreeRTOS API and could be used from interrupts and tasks. In my example: ===========================================================
      uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
      {
        // <- proper BASE priority
        queueSendStatus = xQueueSendFromISR(xQue_PRINT_SERVER,
                                                    &print_mes, &pxTaskWoken);
        // UNSAFE LINE HERE and below
        //<- due not fully implemented portCLEAR_INTERRUPT_MASK_FROM_ISR() base priority back to 0
         if ( pdTRUE == queueSendStatus )
                             (print_mes->something)++;
       
         queueSendStatus = xQueueSendFromISR(xQue_PRINT_SERVER,
                                                    &print_mes, &pxTaskWoken);
      }
      portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup); // in fact not needed, xQueueSendFromISR()

                                                                                                          // clear base priority to 0!

See line with comment: UNSAFE LINE HERE. Interrupts back to zero, not to configMAX_SYSCALL_INTERRUPT_PRIORITY.
But there is no big issue to implement such macros. What I did: based on core_cm3.c and core_cm3.h (CMSIS 1.20) from http://www.onarm.com/download/download389.asp created functions to put in to portmacro.h ===============================================================================
static inline void __cortexM3__enable_irq()               { __asm volatile (”cpsie i”); }
static inline void __cortexM3__disable_irq()              { __asm volatile (”cpsid i”); } static inline void __cortexM3__set_BASEPRI(unsigned portBASE_TYPE value)
{
  __asm volatile (”MSR basepri, %0″ : : “r” (value) );
}// static inline unsigned portBASE_TYPE __cortexM3__get_BASEPRI(void)
{
  unsigned portBASE_TYPE result = 0U;   __asm volatile (”MRS %0, basepri_max” : “=r” (result) );
  return(result);
}// static inline unsigned portBASE_TYPE portSET_INTERRUPT_MASK(void)
{
  unsigned portBASE_TYPE uxSavedInterruptStatus;
  __cortexM3__disable_irq();                        /* need atomic execution !*/
  {
    uxSavedInterruptStatus = __cortexM3__get_BASEPRI();
    __cortexM3__set_BASEPRI(configMAX_SYSCALL_INTERRUPT_PRIORITY);
  }
  __cortexM3__enable_irq();
  return uxSavedInterruptStatus;
}// static inline void portCLEAR_INTERRUPT_MASK(unsigned portBASE_TYPE uxSavedStatus)
{
  __cortexM3__set_BASEPRI(uxSavedStatus);
}// #define portSET_INTERRUPT_MASK_FROM_ISR()     portSET_INTERRUPT_MASK()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)  portCLEAR_INTERRUPT_MASK(x) #define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()

#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK(0U)

GCC 4.4.1
With flag -O1 portSET_INTERRUPT_MASK() evaluate to only 5 instructions: ================================================================
0x080002bc <print_server_Message+164>: cpsid i
0x080002be <print_server_Message+166>: mrs   r4, BASEPRI_MASK
0x080002c2 <print_server_Message+170>: mov.w r3, #191 ; 0xbf
0x080002c6 <print_server_Message+174>: msr   BASEPRI, r3

0x080002ca <print_server_Message+178>: cpsie i

With flag -O1 portCLEAR_INTERRUPT_MASK_FROM_ISR() only one instruction 0x080002f0 <print_server_Message+216>: msr   BASEPRI, r4 Obviously optimization O1 or higher need to be used.
1. Is it correct?
2. Any chance to implement this or similar solution for this macros? Regards

CortexM3 and gcc port

I’m having difficulty reading this, maybe you could repost using the
 tags.
However - the portCLEAR_INTERRUPT_MASK_FROM_ISR and portCLEAR_INTERRUPT_MASK() *are*, as far as I am aware, fully implemented.  The code has also be reviewed in tiny detail by an ARM Cortex M3 expert.
When you enter an interrupt the priority level is held in the NVIC itself, and putting the BASEPRI value down below the priority of the currently executing interrupt will not allow the CPU to accept interrupts that are below the priority of the currently executing interrupt.  Therefore the fastest/most efficient thing to do is simply set it down to zero.  The effect on the running system is the same as if you had set it back to its previous value.
Or am I missing your point?
Regards.

CortexM3 and gcc port

Try again: I’m having difficulty reading this, maybe you could repost using the code tags. However – the portCLEAR_INTERRUPT_MASK_FROM_ISR and portCLEAR_INTERRUPT_MASK() *are*, as far as I am aware, fully implemented. The code has also be reviewed in tiny detail by an ARM Cortex M3 expert. When you enter an interrupt the priority level is held in the NVIC itself, and putting the BASEPRI value down below the priority of the currently executing interrupt will not allow the CPU to accept interrupts that are below the priority of the currently executing interrupt. Therefore the fastest/most efficient thing to do is simply set it down to zero. The effect on the running system is the same as if you had set it back to its previous value. Or am I missing your point? Regards p.s. also, there is no point where interrupts are globally disabled, as would be the case in your code.

CortexM3 and gcc port

Hi Yes, I think you are missing my point.
First I am not claiming that current FreeRTOS implementation is wrong from technically point of view. It is just not full (not full for me).
Sorry for not clear post, Once again, I hope now will be clear. just pseudocode Lets image function what is used from ISR and task routine and use FreeRTOS API. In order to secure reentrancy I use
portSET_INTERRUPT_MASK_FROM_ISR() macros, (is any other way to do this?? ). =========================================================
/* FUN used from ISR and task routine*/
void FUN()
{
                unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
                {
                 xQueueSendFromISR();
                }
                portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup);
}
========================================================= Is it correct model? If not than I missed something and my post not make sense, if yes please read below. Now, last statement before return from xQueueSendFromISR() is:
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); /* line 814 in queue.c */
This macro discard actually uxSavedInterruptStatus value and set BASEPRI to 0, what is not what I intend to get. My assumption is “push” and “pop” priority. What current implementation of macros are doing is set priority to configMAX_SYSCALL_INTERRUPT_PRIORITY and then set to 0 as you mention. I know it is easy and simply.

But if my function looks like this:

/* FUN2 used from ISR and task routine*/
void FUN2()
{
                unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
                { 
                 /* assums no preemptuion in inner block*/
                 xQueueReceiveFromISR(&data);                  
                  data = global_data +1; /* could preempt here */
                  xQueueSendFromISR(&data);                 
                }
                portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup);
}
========================================================= Apart of sense of FUN2(), because xQueueReceiveFromISR() set BASEPRI to 0 just before return, now
line: data = global_data+1;
is not safe because could be pre-empted if used from task routine.
Assumption is no preemption inside inner block. However my implementation do not introduce big overhead, it probably need to map to assembler macro due to not depend on compiler optimalization. What you think? Regards

CortexM3 and gcc port

(once again, I do not have preview before I post) Hi Yes, I think you are missing my point.
First I am not claiming that current FreeRTOS implementation is wrong from technically point of view. It is just not full (not full for me).
Sorry for not clear post, Once again, I hope now will be clear. just pseudocode Lets image function what is used from ISR and task routine and use FreeRTOS API. In order to secure reentrancy I use
portSET_INTERRUPT_MASK_FROM_ISR() macros, (is any other way to do this?? ). =========================================================
/* FUN used from ISR and task routine*/
void FUN()
 {
                          unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
                          {
                            xQueueSendFromISR(); 
                          } 
                          portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup); 
}
========================================================= Is it correct model? If not than I missed something and my post not make sense, if yes please read below. Now, last statement before return from xQueueSendFromISR() is:
Code:
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); /* line 814 in queue.c */ This macro discard actually uxSavedInterruptStatus value and set BASEPRI to 0, what is not what I intend to get. My assumption is “push” and “pop” priority. What current implementation of macros are doing is set priority to configMAX_SYSCALL_INTERRUPT_PRIORITY and then set to 0 as you mention. I know it is easy and simply.

But if my function looks like this:

/* FUN2 used from ISR and task routine*/ void FUN2() { unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR(); { /* assums no preemptuion in inner block*/ xQueueReceiveFromISR(&data); data = global_data +1; /* could preempt here */ xQueueSendFromISR(&data); }
/* FUN2 used from ISR and task routine*/
void FUN2()
{
unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* assums no preemptuion in inner block*/
xQueueReceiveFromISR(&data);
data = global_data +1; /* could preempt here */
xQueueSendFromISR(&data);
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup);
}
========================================================= Apart of sense of FUN2(), because xQueueReceiveFromISR() set BASEPRI to 0 just before return, now
line: data = global_data+1;
is not safe because could be pre-empted if used from task routine.
Assumption is no preemption inside inner block. However my implementation do not introduce big overhead, it probably need to map to assembler macro due to not depend on compiler optimalization. What you think? Regards

CortexM3 and gcc port

(Apologise!) Hi Yes, I think you are missing my point.
First I am not claiming that current FreeRTOS implementation is wrong from technically point of view. It is just not full (not full for me).
Sorry for not clear post, Once again, I hope now will be clear. just pseudocode Lets image function what is used from ISR and task routine and use FreeRTOS API. In order to secure reentrancy I use
portSET_INTERRUPT_MASK_FROM_ISR() macros, (is any other way to do this?? ). =========================================================
/* FUN used from ISR and task routine*/
void FUN() {
                     unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR(); 
                     {
                        xQueueSendFromISR(); 
                      } portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup); 
}
========================================================= Is it correct model? If not than I missed something and my post not make sense, if yes please read below. Now, last statement before return from xQueueSendFromISR() is:
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); /* line 814 in queue.c */
This macro discard actually uxSavedInterruptStatus value and set BASEPRI to 0, what is not what I intend to get. My assumption is “push” and “pop” priority. What current implementation of macros are doing is set priority to configMAX_SYSCALL_INTERRUPT_PRIORITY and then set to 0 as you mention. I know it is easy and simply.

But if my function looks like this:

/* FUN2 used from ISR and task routine*/
void FUN2()
{
unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* assums no preemptuion in inner block*/
xQueueReceiveFromISR(&data);
data = global_data +1; /* could preempt here */
xQueueSendFromISR(&data);
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup);
}
========================================================= Apart of sense of FUN2(), because xQueueReceiveFromISR() set BASEPRI to 0 just before return, now
line: data = global_data+1;
is not safe because could be pre-empted if used from task routine.
Assumption is no preemption inside inner block. However my implementation do not introduce big overhead, it probably need to map to assembler macro due to not depend on compiler optimalization. What you think? Regards

CortexM3 and gcc port

Just addition if still not clear, see comments in code:
/* FUN2 used from ISR and task routine*/
void FUN2(void)
{
  /* assuming current priority if called from task is 0
   * and configMAX_SYSCALL_INTERRUPT_PRIORITY 11
   */
  
  // PRI 0
   unsigned uxSavedInterrup = portSET_INTERRUPT_MASK_FROM_ISR();
   //PRI 11 correct
   { /* Assume no preemptuion in inner block*/
     xQueueReceiveFromISR(&data);
     //PRI 0 !!! not correct
    data = global_data +1;
    /* could preempt here */
    xQueueSendFromISR(&data);
    //PRI 0 not correct
  } portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterrup);
  //PRI 0
}

CortexM3 and gcc port

The macros portSET_INTERRUPT_MASK_FROM_ISR() and portCLEAR_INTERRUPT_MASK_FROM_ISR() are only designed for use from and ISR – for the reason already stated.  They are not intended for use at the task level, although this *might* work if the calls did not nest.  In the example you give you use the macros around a call to xQueueSendFromISR().  As xQueueSendFromISR() also uses the macros internally then + first the outer critical section is not necessary, and + second you are going to have problems for the reasons you are pointing out yourself.  You are simply using the macros out of scope.  Stick to using them how they are supposed to be used and you will be ok. Functions called from the task level should use taskENTER_CRITICAL() and taskEXIT_CRITICAL().  Functions called from an interrupt should used portSET_INTERRUPT_MASK_FROM_ISR() and portCLEAR_INTERRUPT_MASK_FROM_ISR().  If you want to call a function from both, and it is necessary that the function uses a critical section, then you are going to either have to modify the code or provide your own critical section implementation. Regards.

CortexM3 and gcc port

+ first the outer critical section is not necessary, and
I am not sure what you mean, probably you mean that is not necessary because it’s not make sense in current implementation of macros. Because in my example it is crucial since switch context can not occurs between xQueueReceiveFromISR() and xQueueSendFromISR().
However I understand prom your last post this is not supported officially, due of implementation of macros.
Functions called from the task level should use taskENTER_CRITICAL() and taskEXIT_CRITICAL(). Functions called from an interrupt should used portSET_INTERRUPT_MASK_FROM_ISR() and portCLEAR_INTERRUPT_MASK_FROM_ISR(). If you want to call a function from both, and it is necessary that the function uses a critical section, then you are going to either have to modify the code or provide your own critical section implementation.
Thanks.
This is what I am doing, I provide my own implementation of portSET_INTERRUPT_MASK_FROM_ISR() and portCLEAR_INTERRUPT_MASK_FROM_ISR(). Regards