QP is an event-driven, RTOS-like, active object framework for microcontrollers, such as mbed. The QP framework provides thread-safe execution of active objects (concurrent state machines) and support both manual and automatic coding of UML statecharts in readable, production-quality C or C++. Automatic code generation of QP code is supported by the free QM modeling tool.

Dependents:   qp_hangman qp_dpp qp_blinky

QP/C++ (Quantum Platform in C++) is a lightweight, open source active object (actor) framework for building responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C++ framework is a member of a larger family consisting of QP/C++, QP/C, and QP-nano frameworks, which are all strictly quality controlled, thoroughly documented, and available under GPLv3 with a special Exception for mbed (see http://www.state-machine.com/licensing/QP-mbed_GPL_Exception.txt).

The behavior of active objects is specified in QP/C++ by means of hierarchical state machines (UML statecharts). The framework supports manual coding of UML state machines in C++ as well as automatic code generation by means of the free QM modeling tool (http://www.state-machine.com/qm).

Please see the "QP/C++ Reference Manual" (http://www.state-machine.com/qpcpp) for more information.

qk_port.s

Committer:
QL
Date:
2012-09-04
Revision:
9:ca2e6010d9e2
Parent:
5:949864ba515c

File content as of revision 9:ca2e6010d9e2:

;*****************************************************************************
; Product: QK port to ARM Cortex-M0/M3, mbed ARM assembler, CMSIS-compliant
; Last Updated for Version: 4.5.02
; Date of the Last Update:  Sep 04, 2012
;
;                    Q u a n t u m     L e a P s
;                    ---------------------------
;                    innovating embedded systems
;
; Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
;
; This program is open source software: you can redistribute it and/or
; modify it under the terms of the GNU General Public License as published
; by the Free Software Foundation, either version 2 of the License, or
; (at your option) any later version.
;
; Alternatively, this program may be distributed and modified under the
; terms of Quantum Leaps commercial licenses, which expressly supersede
; the GNU General Public License and are specifically designed for
; licensees interested in retaining the proprietary status of their code.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
; Contact information:
; Quantum Leaps Web sites: http://www.quantum-leaps.com
;                          http://www.state-machine.com
; e-mail:                  info@quantum-leaps.com
;*****************************************************************************
    AREA QK, CODE, READONLY
    PRESERVE8

    EXPORT  QK_init
    EXPORT  PendSV_Handler    ; CMSIS-compliant PendSV exception name
    EXPORT  SVC_Handler       ; CMSIS-compliant SVC exception name

    EXTERN  QK_schedPrio_     ; external reference
    EXTERN  QK_sched_         ; external reference


;*****************************************************************************
;
; The QK_init function sets the priorities of PendSV and SVCall exceptions
; to 0xFF and 0x00, respectively. The function internally disables
; interrupts, but restores the original interrupt lock before exit.
;
;*****************************************************************************
QK_init
    MRS     r0,PRIMASK        ; store the state of the PRIMASK in r0
    CPSID   i                 ; disable interrupts (set PRIMASK)

    LDR     r1,=0xE000ED18    ; System Handler Priority Register
    LDR     r2,[r1,#8]        ; load the System 12-15 Priority Register
    MOVS    r3,#0xFF
    LSLS    r3,r3,#16
    ORRS    r2,r3             ; set PRI_14 (PendSV) to 0xFF
    STR     r2,[r1,#8]        ; write the System 12-15 Priority Register
    LDR     r2,[r1,#4]        ; load the System 8-11 Priority Register
    LSLS    r3,r3,#8
    BICS    r2,r3             ; set PRI_11 (SVCall) to 0x00
    STR     r2,[r1,#4]        ; write the System 8-11 Priority Register

    MSR     PRIMASK,r0        ; restore the original PRIMASK
    BX      lr                ; return to the caller


;*****************************************************************************
;
; The PendSV_Handler exception hanlder is used for handling asynchronous
; preemptions in QK. The use of the PendSV exception is the recommended
; and most efficient method for performing context switches with ARM Cortex.
;
; The PendSV exception should have the lowest priority in the whole system
; (0xFF, see QK_init). All other exeptions and interrupts should have higher
; priority. For example, for NVIC with 2 priority bits all interrupts and
; exceptions must have numerical value of priority lower than 0xC0. In this
; case the interrupt priority levels available to your applications are (in
; the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00.
;
; Also, *all* ISRs in the QK application must trigger the PendSV exception
; by calling the QK_ISR_EXIT() macro.
;
; Due to tail-chaining and its lowest priority, the PendSV exception will be
; entered immediately after the exit from the *last* nested interrupt (or
; exception). In QK, this is exactly the time when the QK scheduler needs to
; check for the asynchronous preemptions.
;
;*****************************************************************************
PendSV_Handler
    CPSID   i                 ; disable interrupts at processor level
    BL      QK_schedPrio_     ; check if we have preemption
    CMP     r0,#0             ; is prio == 0 ?
    BNE.N   scheduler         ; if prio != 0, branch to scheduler

    CPSIE   i                 ; enable interrupts at processor level
    MOVS    r0,#0x6
    MVNS    r0,r0             ; r0:=~0x6=0xFFFFFFF9
    BX      r0                ; exception-return to the task

scheduler
    MOVS    r3,#1
    LSLS    r3,r3,#24         ; r3:=(1 << 24), set the T bit  (new xpsr)
    LDR     r2,=QK_sched_     ; address of the QK scheduler   (new pc)
    LDR     r1,=svc_ret       ; return address after the call (new lr)
    PUSH    {r1-r3}           ; push xpsr,pc,lr
    SUB     sp,sp,#(4*4)      ; don't care for r12,r3,r2,r1
    PUSH    {r0}              ; push the prio argument        (new r0)
    MOVS    r0,#0x6
    MVNS    r0,r0             ; r0:=~0x6=0xFFFFFFF9
    BX      r0                ; exception-return to the scheduler

svc_ret
    CPSIE   i                 ; enable interrupts to allow SVCall exception
    SVC     0                 ; SV exception returns to the preempted task


;*****************************************************************************
;
; The SVC_Handler exception handler is used for returning back to the
; interrupted task. The SVCall exception simply removes its own interrupt
; stack frame from the stack and returns to the preempted task using the
; interrupt stack frame that must be at the top of the stack.
;
;*****************************************************************************
SVC_Handler
    ADD     sp,sp,#(8*4)      ; remove one interrupt frame from the stack
    BX      lr                ; return to the preempted task

    ALIGN                     ; make sure the END is properly aligned
    END