Changeset 3e782743 in rtems


Ignore:
Timestamp:
Jul 4, 2017, 12:15:03 PM (2 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
4cd52cc4
Parents:
550616e5
git-author:
Sebastian Huber <sebastian.huber@…> (07/04/17 12:15:03)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/04/17 13:15:37)
Message:

arm: Fix ARMv7-M interrupt processing

Right after a "msr basepri_max, %[basepri]" instruction an interrupt
service may still take place (observed at least on Cortex-M7). However,
pendable service calls that are activated during this interrupt service
may be delayed until interrupts are enable again. The
_ARMV7M_Pendable_service_call() did not check that a thread dispatch is
allowed. Move this test from _ARMV7M_Interrupt_service_leave() to
_ARMV7M_Pendable_service_call().

Update #3060.

Location:
cpukit/score/cpu/arm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/cpu/arm/armv7m-isr-dispatch.c

    r550616e5 r3e782743  
    66
    77/*
    8  * Copyright (c) 2011-2014 Sebastian Huber.  All rights reserved.
     8 * Copyright (c) 2011, 2017 Sebastian Huber.  All rights reserved.
    99 *
    1010 *  embedded brains GmbH
    11  *  Obere Lagerstr. 30
     11 *  Dornierstr. 4
    1212 *  82178 Puchheim
    1313 *  Germany
     
    4949void _ARMV7M_Pendable_service_call( void )
    5050{
    51   ARMV7M_Exception_frame *ef;
    52 
    53   _ISR_Nest_level = 1;
    54 
    55   _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR;
    56   _ARMV7M_Trigger_lazy_floating_point_context_save();
    57 
    58   ef = (ARMV7M_Exception_frame *) _ARMV7M_Get_PSP();
    59   --ef;
    60   _ARMV7M_Set_PSP( (uint32_t) ef );
     51  Per_CPU_Control *cpu_self = _Per_CPU_Get();
    6152
    6253  /*
    63    * According to "ARMv7-M Architecture Reference Manual" section B1.5.6
    64    * "Exception entry behavior" the return address is half-word aligned.
     54   * We must check here if a thread dispatch is allowed.  Right after a
     55   * "msr basepri_max, %[basepri]" instruction an interrupt service may still
     56   * take place.  However, pendable service calls that are activated during
     57   * this interrupt service may be delayed until interrupts are enable again.
    6558   */
    66   ef->register_pc = (void *)
    67     ((uintptr_t) _ARMV7M_Thread_dispatch & ~((uintptr_t) 1));
     59  if (
     60    ( cpu_self->isr_nest_level | cpu_self->thread_dispatch_disable_level ) == 0
     61  ) {
     62    ARMV7M_Exception_frame *ef;
    6863
    69   ef->register_xpsr = 0x01000000U;
     64    cpu_self->isr_nest_level = 1;
     65
     66    _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR;
     67    _ARMV7M_Trigger_lazy_floating_point_context_save();
     68
     69    ef = (ARMV7M_Exception_frame *) _ARMV7M_Get_PSP();
     70    --ef;
     71    _ARMV7M_Set_PSP( (uint32_t) ef );
     72
     73    /*
     74     * According to "ARMv7-M Architecture Reference Manual" section B1.5.6
     75     * "Exception entry behavior" the return address is half-word aligned.
     76     */
     77    ef->register_pc = (void *)
     78      ((uintptr_t) _ARMV7M_Thread_dispatch & ~((uintptr_t) 1));
     79
     80    ef->register_xpsr = 0x01000000U;
     81  }
    7082}
    7183
    7284void _ARMV7M_Supervisor_call( void )
    7385{
     86  Per_CPU_Control *cpu_self = _Per_CPU_Get();
    7487  ARMV7M_Exception_frame *ef;
    7588
     
    8093  _ARMV7M_Set_PSP( (uint32_t) ef );
    8194
    82   _ISR_Nest_level = 0;
    83   RTEMS_COMPILER_MEMORY_BARRIER();
     95  cpu_self->isr_nest_level = 0;
    8496
    85   if ( _Thread_Dispatch_necessary ) {
     97  if ( cpu_self->dispatch_necessary ) {
    8698    _ARMV7M_Pendable_service_call();
    8799  }
  • cpukit/score/cpu/arm/armv7m-isr-enter-leave.c

    r550616e5 r3e782743  
    66
    77/*
    8  * Copyright (c) 2011 Sebastian Huber.  All rights reserved.
     8 * Copyright (c) 2011, 2017 Sebastian Huber.  All rights reserved.
    99 *
    1010 *  embedded brains GmbH
    11  *  Obere Lagerstr. 30
     11 *  Dornierstr. 4
    1212 *  82178 Puchheim
    1313 *  Germany
     
    3131void _ARMV7M_Interrupt_service_enter( void )
    3232{
    33   ++_Thread_Dispatch_disable_level;
    34   ++_ISR_Nest_level;
     33  Per_CPU_Control *cpu_self = _Per_CPU_Get();
     34
     35  ++cpu_self->thread_dispatch_disable_level;
     36  ++cpu_self->isr_nest_level;
    3537}
    3638
    3739void _ARMV7M_Interrupt_service_leave( void )
    3840{
    39   --_ISR_Nest_level;
    40   --_Thread_Dispatch_disable_level;
    41   if (
    42     _ISR_Nest_level == 0
    43       && _Thread_Dispatch_disable_level == 0
    44       && _Thread_Dispatch_necessary
    45   ) {
     41  Per_CPU_Control *cpu_self = _Per_CPU_Get();
     42
     43  --cpu_self->thread_dispatch_disable_level;
     44  --cpu_self->isr_nest_level;
     45
     46  /*
     47   * Optimistically activate a pendable service call if a thread dispatch is
     48   * necessary.  The _ARMV7M_Pendable_service_call() will check that a thread
     49   * dispatch is allowed.
     50   */
     51  if ( cpu_self->dispatch_necessary ) {
    4652    _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVSET;
    4753  }
Note: See TracChangeset for help on using the changeset viewer.