This commit is contained in:
Quantum Leaps 2017-06-06 15:13:52 -04:00
parent f8459420f5
commit b2d669391a
156 changed files with 60305 additions and 21338 deletions

View File

@ -0,0 +1,198 @@
/*============================================================================
* Modified for GNU-ARM from the original port to IAR-ARM as follows:
* - renamed OS_CPU_PendSVHandler to CMSIS-compatible name PendSV_Handler
* - renamed OS_CPU_SysTickHandler to CMSIS-compatible name SysTick_Handler
* - renamed __ARMVFP__ to __FPU_PRESENT
*
* Quantum Leaps, LLC. www.state-machine.com
* 2015-03-23
*===========================================================================*/
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
*
* (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* ARM Cortex-M4 Port
*
* File : OS_CPU.H
* Version : V2.92.09
* By : JJL
* JBL
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or
* for peaceful research. If you plan or intend to use uC/OS-II in a commercial application/
* product then, you need to contact Micrium to properly license uC/OS-II for its use in your
* application/product. We provide ALL the source code for your convenience and to help you
* experience uC/OS-II. The fact that the source is provided does NOT mean that you can use
* it commercially without paying a licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the embedded community with the finest software available.
* Your honesty is greatly appreciated.
*
* You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
*
* For : ARMv7 Cortex-M4
* Mode : Thumb-2 ISA
* Toolchain : IAR EWARM
*********************************************************************************************************
*/
#ifndef OS_CPU_H
#define OS_CPU_H
#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT extern
#endif
#ifndef OS_CPU_EXCEPT_STK_SIZE
#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */
#endif
/*
*********************************************************************************************************
* DEFINES
*********************************************************************************************************
*/
#ifdef __FPU_PRESENT
#define OS_CPU_ARM_FP_EN 1u
#else
#define OS_CPU_ARM_FP_EN 0u
#endif
/*
*********************************************************************************************************
* OS TICK INTERRUPT PRIORITY CONFIGURATION
*
* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt
* should be configured as the highest priority interrupt but won't adversely affect system
* operations.
*
* (2) For systems that need one or more high, real-time interrupts; these should be configured
* higher than the tick interrupt which MAY delay execution of the tick interrupt.
*
* (a) If the higher priority interrupts do NOT continually consume CPU cycles but only
* occasionally delay tick interrupts, then the real-time interrupts can successfully
* handle their intermittent/periodic events with the system not losing tick interrupts
* but only increasing the jitter.
*
* (b) If the higher priority interrupts consume enough CPU cycles to continually delay the
* tick interrupt, then the CPU/system is most likely over-burdened & can't be expected
* to handle all its interrupts/tasks. The system time reference gets compromised as a
* result of losing tick interrupts.
*********************************************************************************************************
*/
#define OS_CPU_CFG_SYSTICK_PRIO 0u
/*
*********************************************************************************************************
* DATA TYPES
* (Compiler Specific)
*********************************************************************************************************
*/
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
typedef signed char INT8S; /* Signed 8 bit quantity */
typedef unsigned short INT16U; /* Unsigned 16 bit quantity */
typedef signed short INT16S; /* Signed 16 bit quantity */
typedef unsigned int INT32U; /* Unsigned 32 bit quantity */
typedef signed int INT32S; /* Signed 32 bit quantity */
typedef float FP32; /* Single precision floating point */
typedef double FP64; /* Double precision floating point */
typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */
typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */
/*
*********************************************************************************************************
* Cortex-M4
* Critical Section Management
*
* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts
* will be enabled even if they were disabled before entering the critical section.
* NOT IMPLEMENTED
*
* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if
* interrupts were disabled before entering the critical section, they will be disabled when
* leaving the critical section.
* NOT IMPLEMENTED
*
* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to
* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
* into the CPU's status register.
*********************************************************************************************************
*/
#define OS_CRITICAL_METHOD 3u
#if OS_CRITICAL_METHOD == 3u
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
#endif
/*
*********************************************************************************************************
* Cortex-M4 Miscellaneous
*********************************************************************************************************
*/
#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */
#define OS_TASK_SW() OSCtxSw()
/*
*********************************************************************************************************
* GLOBAL VARIABLES
*********************************************************************************************************
*/
OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase;
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */
OS_CPU_SR OS_CPU_SR_Save (void);
void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr);
#endif
void OSCtxSw (void);
void OSIntCtxSw (void);
void OSStartHighRdy (void);
void PendSV_Handler (void); /* QL was: void OS_CPU_PendSVHandler (void); */
/* See OS_CPU_C.C */
void SysTick_Handler (void); /* QL was: void OS_CPU_SysTickHandler (void); */
void OS_CPU_SysTickInit (INT32U cnts);
#if (OS_CPU_ARM_FP_EN > 0u)
void OS_CPU_FP_Reg_Push (OS_STK *stkPtr);
void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr);
#endif
#endif

View File

@ -0,0 +1,321 @@
/*===========================================================================
* Modified from the original as follows:
* - changed to the GNU-AS syntax
* - renamed OS_CPU_PendSVHandler to CMSIS-compatible name PendSV_Handler
* - changed the conditional compilation for the FPU to the new syntax
* #ifdef __ARMVFP__/#endif
*
* Quantum Leaps, LLC. https://state-machine.com
* 2017-06-05
*============================================================================
*/
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
*
* (c) Copyright 2009-2013; Micrium, Inc.* Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* ARM Cortex-M4 Port
*
* File : OS_CPU_A.ASM
* Version : V2.92.09
* By : JJL
* BAN
* JBL
*
* For : ARMv7 Cortex-M4
* Mode : Thumb-2 ISA
* Toolchain : IAR EWARM
*********************************************************************************************************
*/
/********************************************************************************************************
* CODE GENERATION DIRECTIVES
********************************************************************************************************/
.syntax unified
.thumb
/********************************************************************************************************
* EQUATES
********************************************************************************************************/
.equ NVIC_INT_CTRL,0xE000ED04 /* Interrupt control state register. */
.equ NVIC_SYSPRI14,0xE000ED22 /* System priority register (priority 14) */
.equ NVIC_PENDSV_PRI,0xFF /* PendSV priority value (lowest). */
.equ NVIC_PENDSVSET,0x10000000 /* Value to trigger PendSV exception. */
/********************************************************************************************************
* FLOATING POINT REGISTERS PUSH
* void OS_CPU_FP_Reg_Push (OS_STK *stkPtr)
*
* Note(s) : 1) This function saves S0-S31, and FPSCR registers of the Floating Point Unit.
*
* 2) Pseudo-code is:
* a) Get FPSCR register value;
* b) Push value on process stack;
* c) Push remaining regs S0-S31 on process stack;
* d) Update OSTCBCur->OSTCBStkPtr;
********************************************************************************************************/
.ifdef __FPU_PRESENT /* QL was: IF {FPU} != "SoftVFP" */
.section .text.OS_CPU_FP_Reg_Push
.global OS_CPU_FP_Reg_Push
.type OS_CPU_FP_Reg_Push, %function
OS_CPU_FP_Reg_Push:
MRS R1, PSP /* PSP is process stack pointer */
CBZ R1, OS_CPU_FP_nosave /* Skip FP register save the first time */
VMRS R1, FPSCR
STR R1, [R0, #-4]!
VSTMDB R0!, {S0-S31}
LDR R1, =OSTCBCur
LDR R2, [R1]
STR R0, [R2]
OS_CPU_FP_nosave:
BX LR
.size OS_CPU_FP_Reg_Push, . - OS_CPU_FP_Reg_Push
.endif /* QL was: ENDIF */
/********************************************************************************************************
* FLOATING POINT REGISTERS POP
* void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr)
*
* Note(s) : 1) This function restores S0-S31, and FPSCR registers of the Floating Point Unit.
*
* 2) Pseudo-code is:
* a) Restore regs S0-S31 of new process stack;
* b) Restore FPSCR reg value
* c) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack;
********************************************************************************************************/
.ifdef __FPU_PRESENT /* QL was: IF {FPU} != "SoftVFP" */
.section .text.OS_CPU_FP_Reg_Pop
.global OS_CPU_FP_Reg_Pop
.type OS_CPU_FP_Reg_Pop, %function
OS_CPU_FP_Reg_Pop:
VLDMIA R0!, {S0-S31}
LDMIA R0!, {R1}
VMSR FPSCR, R1
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R0, [R2]
BX LR
.size OS_CPU_FP_Reg_Pop, . - OS_CPU_FP_Reg_Pop
.endif /* QL was: ENDIF */
/********************************************************************************************************
* CRITICAL SECTION METHOD 3 FUNCTIONS
*
* Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to
* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
* into the CPU's status register.
*
* Prototypes : OS_CPU_SR OS_CPU_SR_Save(void);
* void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
*
*
* Note(s) : 1) These functions are used in general like this:
*
* void Task (void *p_arg)
* {
* #if OS_CRITICAL_METHOD == 3 // Allocate storage for CPU status register
* OS_CPU_SR cpu_sr;
* #endif
*
* :
* :
* OS_ENTER_CRITICAL(); // cpu_sr = OS_CPU_SaveSR();
* :
* :
* OS_EXIT_CRITICAL(); // OS_CPU_RestoreSR(cpu_sr);
* :
* :
* }
********************************************************************************************************/
.section .text.OS_CPU_SR_Save
.global OS_CPU_SR_Save
.type OS_CPU_SR_Save, %function
OS_CPU_SR_Save:
MRS R0, PRIMASK /* Set prio int mask to mask all (except faults) */
CPSID I
BX LR
.size OS_CPU_SR_Save, . - OS_CPU_SR_Save
.section .text.OS_CPU_SR_Restore
.global OS_CPU_SR_Restore
.type OS_CPU_SR_Restore, %function
OS_CPU_SR_Restore:
MSR PRIMASK, R0
BX LR
.size OS_CPU_SR_Restore, . - OS_CPU_SR_Restore
/********************************************************************************************************
* START MULTITASKING
* void OSStartHighRdy(void)
*
* Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause
* the first task to start.
*
* 2) OSStartHighRdy() MUST:
* a) Setup PendSV exception priority to lowest;
* b) Set initial PSP to 0, to tell context switcher this is first run;
* c) Set the main stack to OS_CPU_ExceptStkBase
* d) Set OSRunning to TRUE;
* e) Trigger PendSV exception;
* f) Enable interrupts (tasks will run with interrupts enabled).
********************************************************************************************************/
.section .text.OSStartHighRdy
.global OSStartHighRdy
.type OSStartHighRdy, %function
OSStartHighRdy:
LDR R0, =NVIC_SYSPRI14 /* Set the PendSV exception priority */
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0]
MOVS R0, #0 /* Set the PSP to 0 for initial context switch call */
MSR PSP, R0
LDR R0, =OS_CPU_ExceptStkBase /* Initialize the MSP to the OS_CPU_ExceptStkBase */
LDR R1, [R0]
MSR MSP, R1
LDR R0, =OSRunning /* OSRunning = TRUE */
MOVS R1, #1
STRB R1, [R0]
LDR R0, =NVIC_INT_CTRL /* Trigger the PendSV exception (causes context switch) */
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
CPSIE I /* Enable interrupts at processor level */
OSStartHang:
B OSStartHang /* Should never get here */
.size OSStartHighRdy, . - OSStartHighRdy
/********************************************************************************************************
* PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
*
* Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function
* triggers the PendSV exception which is where the real work is done.
********************************************************************************************************/
.section .text.OSCtxSw
.global OSCtxSw
.type OSCtxSw, %function
OSCtxSw:
LDR R0, =NVIC_INT_CTRL /* Trigger the PendSV exception (causes context switch) */
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
.size OSCtxSw, . - OSCtxSw
/********************************************************************************************************
* PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
*
* Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
* the result of an interrupt. This function simply triggers a PendSV exception which will
* be handled when there are no more interrupts active and interrupts are enabled.
********************************************************************************************************/
.section .text.OSIntCtxSw
.global OSIntCtxSw
.type OSIntCtxSw, %function
OSIntCtxSw:
LDR R0, =NVIC_INT_CTRL /* Trigger the PendSV exception (causes context switch) */
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
.size OSIntCtxSw, . - OSIntCtxSw
/********************************************************************************************************
* HANDLE PendSV EXCEPTION
* void OS_CPU_PendSVHandler(void)
*
* Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing
* context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the
* processor context on any exception, and restores same on return from exception. So only
* saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception
* this way means that context saving and restoring is identical whether it is initiated from
* a thread or occurs due to an interrupt or exception.
*
* 2) Pseudo-code is:
* a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
* b) Save remaining regs r4-r11 on process stack;
* c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
* d) Call OSTaskSwHook();
* e) Get current high priority, OSPrioCur = OSPrioHighRdy;
* f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
* g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
* h) Restore R4-R11 from new process stack;
* i) Perform exception return which will restore remaining context.
*
* 3) On entry into PendSV handler:
* a) The following have been saved on the process stack (by processor):
* xPSR, PC, LR, R12, R0-R3
* b) Processor mode is switched to Handler mode (from Thread mode)
* c) Stack is Main stack (switched from Process stack)
* d) OSTCBCur points to the OS_TCB of the task to suspend
* OSTCBHighRdy points to the OS_TCB of the task to resume
*
* 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
* know that it will only be run when no other exception or interrupt is active, and
* therefore safe to assume that context being switched out was using the process stack (PSP).
********************************************************************************************************/
.section .text.PendSV_Handler
.global PendSV_Handler
.type PendSV_Handler, %function
PendSV_Handler: /* QL was: OS_CPU_PendSVHandler */
CPSID I /* Prevent interruption during context switch */
MRS R0, PSP /* PSP is process stack pointer */
CBZ R0, OS_CPU_PendSVHandler_nosave /* Skip register save the first time */
SUBS R0, R0, #0x20 /* Save remaining regs r4-11 on process stack */
STM R0, {R4-R11}
LDR R1, =OSTCBCur /* OSTCBCur->OSTCBStkPtr = SP; */
LDR R1, [R1]
STR R0, [R1] /* R0 is SP of process being switched out */
/* At this point, entire context of process has been saved */
OS_CPU_PendSVHandler_nosave:
PUSH {R14} /* Save LR exc_return value */
LDR R0, =OSTaskSwHook /* OSTaskSwHook(); */
BLX R0
POP {R14}
LDR R0, =OSPrioCur /* OSPrioCur = OSPrioHighRdy; */
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur /* OSTCBCur = OSTCBHighRdy; */
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2] /* R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; */
LDM R0, {R4-R11} /* Restore r4-11 from new process stack */
ADDS R0, R0, #0x20
MSR PSP, R0 /* Load PSP with new process SP */
ORR LR, LR, #0xF4 /* Ensure exception return uses process stack */
CPSIE I
BX LR /* Exception return will restore remaining context */
.size PendSV_Handler, . - PendSV_Handler
.end

View File

@ -0,0 +1,649 @@
/*============================================================================
* Modified from the original to interoperate with CMSIS standard as follows:
* - renamed OS_CPU_SysTickHandler to CMSIS-compatible name SysTick_Handler
* - added expected configuration of the Cortex-M4F FPU to OSInitHookEnd()
* - removed dependency on "lib_def.h"
* - added definition of CPU_STK typdef
* - added definitions of DEF_DISABLED and DEF_ENABLED
* - replaced the use of macros DEF_BIT_FIELD() and DEF_BIT_MASK()
* with the simple code equivalents
*
* Quantum Leaps, LLC. www.state-machine.com
* 2015-03-24
*===========================================================================*/
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
*
* (c) Copyright 2009-2013; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* ARM Cortex-M4 Port
*
* File : OS_CPU_C.C
* Version : V2.92.09
* By : JJL
* BAN
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE short-term evaluation, for educational use or
* for peaceful research. If you plan or intend to use uC/OS-II in a commercial application/
* product then, you need to contact Micrium to properly license uC/OS-II for its use in your
* experience uC/OS-II. The fact that the source is provided does NOT mean that you can use
* it commercially without paying a licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the embedded community with the finest software available.
* Your honesty is greatly appreciated.
*
* You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
*
* For : ARMv7 Cortex-M4
* Mode : Thumb-2 ISA
* Toolchain : IAR EWARM
*********************************************************************************************************
*/
#define OS_CPU_GLOBALS
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define DEF_DISABLED 0u
#define DEF_ENABLED 1u
#include <ucos_ii.h>
#include <os_cpu.h> /* QL was: #include <lib_def.h> */
typedef INT32U CPU_STK; /* QL added: Defines CPU stack data type. */
/*
*********************************************************************************************************
* LOCAL VARIABLES
*********************************************************************************************************
*/
#if OS_TMR_EN > 0u
static INT16U OSTmrCtr;
#endif
/*
*********************************************************************************************************
* SYS TICK DEFINES
*********************************************************************************************************
*/
#define OS_CPU_CM4_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */
#define OS_CPU_CM4_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload Value Reg. */
#define OS_CPU_CM4_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */
#define OS_CPU_CM4_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal Value Reg. */
#define OS_CPU_CM4_NVIC_SHPRI1 (*((volatile INT32U *)0xE000ED18uL)) /* System Handlers 4 to 7 Prio. */
#define OS_CPU_CM4_NVIC_SHPRI2 (*((volatile INT32U *)0xE000ED1CuL)) /* System Handlers 8 to 11 Prio. */
#define OS_CPU_CM4_NVIC_SHPRI3 (*((volatile INT32U *)0xE000ED20uL)) /* System Handlers 12 to 15 Prio. */
#define OS_CPU_CM4_NVIC_CPACR (*((volatile INT32U *)0xE000ED88uL)) /* Coprocessor Access Control Reg. */
#define OS_CPU_CM4_SCB_FPCCR (*((volatile INT32U *)0xE000EF34uL)) /* Floating-Point Context Control Reg. */
#define OS_CPU_CM4_NVIC_ST_CTRL_COUNT 0x00010000uL /* Count flag. */
#define OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC 0x00000004uL /* Clock Source. */
#define OS_CPU_CM4_NVIC_ST_CTRL_INTEN 0x00000002uL /* Interrupt enable. */
#define OS_CPU_CM4_NVIC_ST_CTRL_ENABLE 0x00000001uL /* Counter mode. */
#define OS_CPU_CM4_NVIC_PRIO_MIN 0xFFu /* Min handler prio. */
/*
*********************************************************************************************************
* OS INITIALIZATION HOOK
* (BEGINNING)
*
* Description: This function is called by OSInit() at the beginning of OSInit().
*
* Arguments : none
*
* Note(s) : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSInitHookBegin (void)
{
INT32U size;
OS_STK *pstk;
/* Clear exception stack for stack checking. */
pstk = &OS_CPU_ExceptStk[0];
size = OS_CPU_EXCEPT_STK_SIZE;
while (size > 0u) {
size--;
*pstk++ = (OS_STK)0;
}
/* Align the ISR stack to 8-bytes */
OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE];
OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8);
#if OS_TMR_EN > 0u
OSTmrCtr = 0u;
#endif
}
#endif
/*
*********************************************************************************************************
* OS INITIALIZATION HOOK
* (END)
*
* Description: This function is called by OSInit() at the end of OSInit().
*
* Arguments : none
*
* Note(s) : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSInitHookEnd (void)
{
#if (OS_CPU_ARM_FP_EN > 0u)
/* Enable access to Floating-point coprocessor. */
OS_CPU_CM4_NVIC_CPACR |= ((3UL << 10*2) | (3UL << 11*2));
/* Explictily Disable the automatic FPU state preservation as well as the FPU lazy stacking */
OS_CPU_CM4_SCB_FPCCR &= ~((1U << 31) | (1U << 30));
#endif
}
#endif
/*
*********************************************************************************************************
* TASK CREATION HOOK
*
* Description: This function is called when a task is created.
*
* Arguments : ptcb is a pointer to the task control block of the task being created.
*
* Note(s) : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSTaskCreateHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0u
App_TaskCreateHook(ptcb);
#else
(void)ptcb; /* Prevent compiler warning */
#endif
}
#endif
/*
*********************************************************************************************************
* TASK DELETION HOOK
*
* Description: This function is called when a task is deleted.
*
* Arguments : ptcb is a pointer to the task control block of the task being deleted.
*
* Note(s) : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSTaskDelHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0u
App_TaskDelHook(ptcb);
#else
(void)ptcb; /* Prevent compiler warning */
#endif
}
#endif
/*
*********************************************************************************************************
* IDLE TASK HOOK
*
* Description: This function is called by the idle task. This hook has been added to allow you to do
* such things as STOP the CPU to conserve power.
*
* Arguments : none
*
* Note(s) : 1) Interrupts are enabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSTaskIdleHook (void)
{
#if OS_APP_HOOKS_EN > 0u
App_TaskIdleHook();
#endif
}
#endif
/*
*********************************************************************************************************
* TASK RETURN HOOK
*
* Description: This function is called if a task accidentally returns. In other words, a task should
* either be an infinite loop or delete itself when done.
*
* Arguments : ptcb is a pointer to the task control block of the task that is returning.
*
* Note(s) : none
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSTaskReturnHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0u
App_TaskReturnHook(ptcb);
#else
(void)ptcb;
#endif
}
#endif
/*
*********************************************************************************************************
* STATISTIC TASK HOOK
*
* Description: This function is called every second by uC/OS-II's statistics task. This allows your
* application to add functionality to the statistics task.
*
* Arguments : none
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSTaskStatHook (void)
{
#if OS_APP_HOOKS_EN > 0u
App_TaskStatHook();
#endif
}
#endif
/*
*********************************************************************************************************
* INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
* stack frame of the task being created. This function is highly processor specific.
*
* Arguments : task is a pointer to the task code
*
* p_arg is a pointer to a user supplied data area that will be passed to the task
* when the task first executes.
*
* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
* of the stack.
*
* opt specifies options that can be used to alter the behavior of OSTaskStkInit().
* (see uCOS_II.H for OS_TASK_OPT_xxx).
*
* Returns : Always returns the location of the new top-of-stack once the processor registers have
* been placed on the stack in the proper order.
*
* Note(s) : (1) Interrupts are enabled when task starts executing.
*
* (2) All tasks run in Thread mode, using process stack.
*
* (3) There are two different stack frames depending on whether the Floating-Point(FP)
* co-processor is enabled or not.
*
* (a) The stack frame shown in the diagram is used when the FP co-processor is not present and
* OS_TASK_OPT_SAVE_FP is disabled. In this case, the FP registers and FP Status Control
* register are not saved in the stack frame.
*
* (b) If the FP co-processor is present but the OS_TASK_OPT_SAVE_FP is not set, then the stack
* frame is saved as shown in diagram (a). Moreover, if OS_TASK_OPT_SAVE_FP is set, then the
* FP registers and FP Status Control register are saved in the stack frame.
*
* (1) When enabling the FP co-processor, make sure to clear bits ASPEN and LSPEN in the
* Floating-Point Context Control Register (FPCCR).
*
* +------------+ +------------+
* | | | |
* +------------+ +------------+
* | xPSR | | xPSR |
* +------------+ +------------+
* |Return Addr | |Return Addr |
* +------------+ +------------+
* | LR(R14) | | LR(R14) |
* +------------+ +------------+
* | R12 | | R12 |
* +------------+ +------------+
* | R3 | | R3 |
* +------------+ +------------+
* | R2 | | R0 |
* +------------+ +------------+
* | R1 | | R1 |
* +------------+ +------------+
* | R0 | | R0 |
* +------------+ +------------+
* | R11 | | R11 |
* +------------+ +------------+
* | R10 | | R10 |
* +------------+ +------------+
* | R9 | | R9 |
* +------------+ +------------+
* | R8 | | R8 |
* +------------+ +------------+
* | R7 | | R7 |
* +------------+ +------------+
* | R6 | | R6 |
* +------------+ +------------+
* | R5 | | R5 |
* +------------+ +------------+
* | R4 | | R4 |
* +------------+ +------------+
* (a) | FPSCR |
* +------------+
* | S31 |
* +------------+
* .
* .
* .
* +------------+
* | S1 |
+------------+
* | S0 |
* +------------+
* (b)
*
* (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture
*
* (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned
* on entry to AAPCS-Conforming functions states :
*
* The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive
* data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes).
* Doing otherwise creates more problems than it solves.
*
* In return for preserving the natural alignment of data, conforming code is permitted
* to rely on that alignment. To support aligning data allocated on the stack, the stack
* pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In
* practice this requirement is met if:
*
* (1) At each call site, the current size of the calling function<EFBFBD>s stack frame is a multiple of 8 bytes.
* This places an obligation on compilers and assembly language programmers.
*
* (2) SP is a multiple of 8 when control first enters a program.
* This places an obligation on authors of low level OS, RTOS, and runtime library
* code to align SP at all points at which control first enters
* a body of (AAPCS-conforming) code.
*
* In turn, this requires the value of SP to be aligned to 0 modulo 8:
*
* (3) By exception handlers, before calling AAPCS-conforming code.
*
* (4) By OS/RTOS/run-time system code, before giving control to an application.
*
* (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry
* to AAPCS-conforming functions advisory note also states.
*
* " This requirement extends to operating systems and run-time code for all architecture versions
* prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations
* associated with ARMV7M are discussed in <EFBFBD>2.3.3"
*
* (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned
* to 8-byte boundaries to support legacy execution enviroments.
*
* (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM
* architecture states : "The stack must also conform to the following
* constraint at a public interface:
*
* (1) SP mod 8 = 0. The stack must be double-word aligned"
*
* (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment.
*
* "8 byte stack alignment is a requirement of the ARM Architecture Procedure
* Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte
* aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external
* interfaces. In practice this requirement is met if:
*
* (1) At each external interface, the current stack pointer
* is a multiple of 8 bytes.
*
* (2) Your OS maintains 8 byte stack alignment on its external interfaces
* e.g. on task switches"
*
**********************************************************************************************************
*/
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
OS_STK *p_stk;
p_stk = ptos + 1u; /* Load stack pointer */
/* Align the stack to 8-bytes. */
p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u);
/* Registers stacked as if auto-saved on exception */
*(--p_stk) = (OS_STK)0x01000000uL; /* xPSR */
*(--p_stk) = (OS_STK)task; /* Entry Point */
*(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR) */
*(--p_stk) = (OS_STK)0x12121212uL; /* R12 */
*(--p_stk) = (OS_STK)0x03030303uL; /* R3 */
*(--p_stk) = (OS_STK)0x02020202uL; /* R2 */
*(--p_stk) = (OS_STK)0x01010101uL; /* R1 */
*(--p_stk) = (OS_STK)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*(--p_stk) = (OS_STK)0x11111111uL; /* R11 */
*(--p_stk) = (OS_STK)0x10101010uL; /* R10 */
*(--p_stk) = (OS_STK)0x09090909uL; /* R9 */
*(--p_stk) = (OS_STK)0x08080808uL; /* R8 */
*(--p_stk) = (OS_STK)0x07070707uL; /* R7 */
*(--p_stk) = (OS_STK)0x06060606uL; /* R6 */
*(--p_stk) = (OS_STK)0x05050505uL; /* R5 */
*(--p_stk) = (OS_STK)0x04040404uL; /* R4 */
#if (OS_CPU_ARM_FP_EN > 0u)
if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
*--p_stk = (OS_STK)0x02000000u; /* FPSCR */
/* Initialize S0-S31 floating point registers */
*--p_stk = (OS_STK)0x41F80000u; /* S31 */
*--p_stk = (OS_STK)0x41F00000u; /* S30 */
*--p_stk = (OS_STK)0x41E80000u; /* S29 */
*--p_stk = (OS_STK)0x41E00000u; /* S28 */
*--p_stk = (OS_STK)0x41D80000u; /* S27 */
*--p_stk = (OS_STK)0x41D00000u; /* S26 */
*--p_stk = (OS_STK)0x41C80000u; /* S25 */
*--p_stk = (OS_STK)0x41C00000u; /* S24 */
*--p_stk = (OS_STK)0x41B80000u; /* S23 */
*--p_stk = (OS_STK)0x41B00000u; /* S22 */
*--p_stk = (OS_STK)0x41A80000u; /* S21 */
*--p_stk = (OS_STK)0x41A00000u; /* S20 */
*--p_stk = (OS_STK)0x41980000u; /* S19 */
*--p_stk = (OS_STK)0x41900000u; /* S18 */
*--p_stk = (OS_STK)0x41880000u; /* S17 */
*--p_stk = (OS_STK)0x41800000u; /* S16 */
*--p_stk = (OS_STK)0x41700000u; /* S15 */
*--p_stk = (OS_STK)0x41600000u; /* S14 */
*--p_stk = (OS_STK)0x41500000u; /* S13 */
*--p_stk = (OS_STK)0x41400000u; /* S12 */
*--p_stk = (OS_STK)0x41300000u; /* S11 */
*--p_stk = (OS_STK)0x41200000u; /* S10 */
*--p_stk = (OS_STK)0x41100000u; /* S9 */
*--p_stk = (OS_STK)0x41000000u; /* S8 */
*--p_stk = (OS_STK)0x40E00000u; /* S7 */
*--p_stk = (OS_STK)0x40C00000u; /* S6 */
*--p_stk = (OS_STK)0x40A00000u; /* S5 */
*--p_stk = (OS_STK)0x40800000u; /* S4 */
*--p_stk = (OS_STK)0x40400000u; /* S3 */
*--p_stk = (OS_STK)0x40000000u; /* S2 */
*--p_stk = (OS_STK)0x3F800000u; /* S1 */
*--p_stk = (OS_STK)0x00000000u; /* S0 */
}
#endif
return (p_stk);
}
/*
*********************************************************************************************************
* TASK SWITCH HOOK
*
* Description: This function is called when a task switch is performed. This allows you to perform other
* operations during a context switch.
*
* Arguments : none
*
* Note(s) : 1) Interrupts are disabled during this call.
* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
* task being switched out (i.e. the preempted task).
*********************************************************************************************************
*/
#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
void OSTaskSwHook (void)
{
#if (OS_CPU_ARM_FP_EN > 0u)
if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr);
}
if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);
}
#endif
#if OS_APP_HOOKS_EN > 0u
App_TaskSwHook();
#endif
}
#endif
/*
*********************************************************************************************************
* OS_TCBInit() HOOK
*
* Description: This function is called by OS_TCBInit() after setting up most of the TCB.
*
* Arguments : ptcb is a pointer to the TCB of the task being created.
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0u
void OSTCBInitHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0u
App_TCBInitHook(ptcb);
#else
(void)ptcb; /* Prevent compiler warning */
#endif
}
#endif
/*
*********************************************************************************************************
* TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments : none
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u)
void OSTimeTickHook (void)
{
#if OS_APP_HOOKS_EN > 0u
App_TimeTickHook();
#endif
#if OS_TMR_EN > 0u
OSTmrCtr++;
if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) {
OSTmrCtr = 0;
OSTmrSignal();
}
#endif
}
#endif
/*
*********************************************************************************************************
* SYS TICK HANDLER
*
* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
* interrupt.
*
* Arguments : None.
*
* Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table.
*********************************************************************************************************
*/
void SysTick_Handler (void) /* QL was: void OS_CPU_SysTickHandler (void) */
{
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
OSIntNesting++;
OS_EXIT_CRITICAL();
OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */
OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */
}
/*
*********************************************************************************************************
* INITIALIZE SYS TICK
*
* Description: Initialize the SysTick.
*
* Arguments : cnts Number of SysTick counts between two OS tick interrupts.
*
* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization.
*********************************************************************************************************
*/
void OS_CPU_SysTickInit (INT32U cnts)
{
INT32U prio;
OS_CPU_CM4_NVIC_ST_RELOAD = cnts - 1u;
/* Set SysTick handler prio. */
prio = OS_CPU_CM4_NVIC_SHPRI3;
prio &= 0x00FFFFFF; /* QL was: DEF_BIT_FIELD(24, 0); */
prio |= OS_CPU_CFG_SYSTICK_PRIO << 24; /* QL was: DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24); */
OS_CPU_CM4_NVIC_SHPRI3 = prio;
/* Enable timer. */
OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_CLK_SRC |
OS_CPU_CM4_NVIC_ST_CTRL_ENABLE;
/* Enable timer interrupt. */
OS_CPU_CM4_NVIC_ST_CTRL |= OS_CPU_CM4_NVIC_ST_CTRL_INTEN;
}

View File

@ -0,0 +1,315 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* DEBUGGER CONSTANTS
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_DBG.C
* By : Jean J. Labrosse
* Version : V2.92.09
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<EFBFBD>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#include <ucos_ii.h>
#define OS_COMPILER_OPT __root
/*
*********************************************************************************************************
* DEBUG DATA
*********************************************************************************************************
*/
OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */
#if OS_DEBUG_EN > 0u
OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */
OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN;
OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */
OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN;
#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */
OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */
#else
OS_COMPILER_OPT INT16U const OSEventSize = 0u;
OS_COMPILER_OPT INT16U const OSEventTblSize = 0u;
#endif
OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN;
OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN;
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */
OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */
OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */
#else
OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u;
OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u;
OS_COMPILER_OPT INT16U const OSFlagWidth = 0u;
#endif
OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS;
OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN;
OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO;
OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN;
OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN;
OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */
OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN;
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */
OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl);
#else
OS_COMPILER_OPT INT16U const OSMemSize = 0u;
OS_COMPILER_OPT INT16U const OSMemTblSize = 0u;
#endif
OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN;
OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */
OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN;
OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */
#else
OS_COMPILER_OPT INT16U const OSQSize = 0u;
#endif
OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */
OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN;
OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */
OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN;
OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN;
OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN;
OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE;
OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN;
OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */
OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN;
OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN;
OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE;
OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN;
OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN;
OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE;
OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */
OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */
OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC;
OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN;
OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION;
OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN;
OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX;
OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN;
OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE;
OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC;
#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR);
OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl);
OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL);
OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl);
#else
OS_COMPILER_OPT INT16U const OSTmrSize = 0u;
OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u;
OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u;
OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u;
#endif
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* DEBUG DATA
* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II
*********************************************************************************************************
*/
#if OS_DEBUG_EN > 0u
OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr)
#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u)
+ sizeof(OSEventFreeList)
+ sizeof(OSEventTbl)
#endif
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+ sizeof(OSFlagTbl)
+ sizeof(OSFlagFreeList)
#endif
#if OS_TASK_STAT_EN > 0u
+ sizeof(OSCPUUsage)
+ sizeof(OSIdleCtrMax)
+ sizeof(OSIdleCtrRun)
+ sizeof(OSStatRdy)
+ sizeof(OSTaskStatStk)
#endif
#if OS_TICK_STEP_EN > 0u
+ sizeof(OSTickStepState)
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+ sizeof(OSMemFreeList)
+ sizeof(OSMemTbl)
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+ sizeof(OSQFreeList)
+ sizeof(OSQTbl)
#endif
#if OS_TIME_GET_SET_EN > 0u
+ sizeof(OSTime)
#endif
#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+ sizeof(OSTmrFree)
+ sizeof(OSTmrUsed)
+ sizeof(OSTmrTime)
+ sizeof(OSTmrSem)
+ sizeof(OSTmrSemSignal)
+ sizeof(OSTmrTbl)
+ sizeof(OSTmrFreeList)
+ sizeof(OSTmrTaskStk)
+ sizeof(OSTmrWheelTbl)
#endif
+ sizeof(OSIntNesting)
+ sizeof(OSLockNesting)
+ sizeof(OSPrioCur)
+ sizeof(OSPrioHighRdy)
+ sizeof(OSRdyGrp)
+ sizeof(OSRdyTbl)
+ sizeof(OSRunning)
+ sizeof(OSTaskCtr)
+ sizeof(OSIdleCtr)
+ sizeof(OSTaskIdleStk)
+ sizeof(OSTCBCur)
+ sizeof(OSTCBFreeList)
+ sizeof(OSTCBHighRdy)
+ sizeof(OSTCBList)
+ sizeof(OSTCBPrioTbl)
+ sizeof(OSTCBTbl);
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* OS DEBUG INITIALIZATION
*
* Description: This function is used to make sure that debug variables that are unused in the application
* are not optimized away. This function might not be necessary for all compilers. In this
* case, you should simply DELETE the code in this function while still leaving the declaration
* of the function itself.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out
* the 'const' variables which are declared in this file.
* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function
* if your compiler DOES NOT optimize out the 'const' variables above.
*********************************************************************************************************
*/
#if OS_DEBUG_EN > 0u
void OSDebugInit (void)
{
void *ptemp;
ptemp = (void *)&OSDebugEn;
ptemp = (void *)&OSEndiannessTest;
ptemp = (void *)&OSEventMax;
ptemp = (void *)&OSEventNameEn;
ptemp = (void *)&OSEventEn;
ptemp = (void *)&OSEventSize;
ptemp = (void *)&OSEventTblSize;
ptemp = (void *)&OSEventMultiEn;
ptemp = (void *)&OSFlagEn;
ptemp = (void *)&OSFlagGrpSize;
ptemp = (void *)&OSFlagNodeSize;
ptemp = (void *)&OSFlagWidth;
ptemp = (void *)&OSFlagMax;
ptemp = (void *)&OSFlagNameEn;
ptemp = (void *)&OSLowestPrio;
ptemp = (void *)&OSMboxEn;
ptemp = (void *)&OSMemEn;
ptemp = (void *)&OSMemMax;
ptemp = (void *)&OSMemNameEn;
ptemp = (void *)&OSMemSize;
ptemp = (void *)&OSMemTblSize;
ptemp = (void *)&OSMutexEn;
ptemp = (void *)&OSPtrSize;
ptemp = (void *)&OSQEn;
ptemp = (void *)&OSQMax;
ptemp = (void *)&OSQSize;
ptemp = (void *)&OSRdyTblSize;
ptemp = (void *)&OSSemEn;
ptemp = (void *)&OSStkWidth;
ptemp = (void *)&OSTaskCreateEn;
ptemp = (void *)&OSTaskCreateExtEn;
ptemp = (void *)&OSTaskDelEn;
ptemp = (void *)&OSTaskIdleStkSize;
ptemp = (void *)&OSTaskProfileEn;
ptemp = (void *)&OSTaskMax;
ptemp = (void *)&OSTaskNameEn;
ptemp = (void *)&OSTaskStatEn;
ptemp = (void *)&OSTaskStatStkSize;
ptemp = (void *)&OSTaskStatStkChkEn;
ptemp = (void *)&OSTaskSwHookEn;
ptemp = (void *)&OSTCBPrioTblMax;
ptemp = (void *)&OSTCBSize;
ptemp = (void *)&OSTicksPerSec;
ptemp = (void *)&OSTimeTickHookEn;
#if OS_TMR_EN > 0u
ptemp = (void *)&OSTmrTbl[0];
ptemp = (void *)&OSTmrWheelTbl[0];
ptemp = (void *)&OSTmrEn;
ptemp = (void *)&OSTmrCfgMax;
ptemp = (void *)&OSTmrCfgNameEn;
ptemp = (void *)&OSTmrCfgWheelSize;
ptemp = (void *)&OSTmrCfgTicksPerSec;
ptemp = (void *)&OSTmrSize;
ptemp = (void *)&OSTmrTblSize;
ptemp = (void *)&OSTmrWheelSize;
ptemp = (void *)&OSTmrWheelTblSize;
#endif
ptemp = (void *)&OSVersionNbr;
ptemp = (void *)&OSDataSize;
ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */
}
#endif

View File

@ -42,6 +42,34 @@ mailto:info@state-machine.com
####################################################################### #######################################################################
##################### QP/C Revision History ########################### ##################### QP/C Revision History ###########################
QP/C Version 5.9.2 (05-Jun-2017)
--------------------------------
This release adapts the Makefiles for GNU-ARM to the new location of the
GNU-ARM toolset, which is now included in the QTools Collection (v 5.9.1)
for Windows.
Also, this release improves the flash loading scripts for the JLink
hardware debugger (for GNU-ARM projects for the EFM32-SLSTK3401A board).
Specifically, the JLink configuration file for flash download is
generated by the flash batch script based on the command-line paramter
(the binary file to load into the flash). This eliminates the need to
manually maintain JLink configuration files.
Also, this release adds bi-directional QP/Spy to the embOS example
project for the STM32F4-Discovery board.
Also, this release adds GNU-ARM port to uC/OS-II and adds GNU-ARM example
project for the EK-TM4C123GXL board.
Finally, this release implements the feature request #125 "Include QPC
Demo application for STM32F4 processor without RTOS" (see
https://sourceforge.net/p/qpc/feature-requests/125/ ). The DPP demo for
the STM32F4-Discovery board has been added in the directory:
qpc\examples\arm-cm\dpp_stm32f4-discovery . This demo includes QV, QK and
QXK kernels and ARM-Keil, GNU-ARM, and IAR-ARM toolsets. The demos support
bi-directional QP/Spy.
QP/C Version 5.9.1 (26-May-2017) QP/C Version 5.9.1 (26-May-2017)
-------------------------------- --------------------------------
This release fixes the following bug: This release fixes the following bug:

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "QP/C" PROJECT_NAME = "QP/C"
PROJECT_NUMBER = "5.9.1" PROJECT_NUMBER = "5.9.2"
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = images/header_logo_ql.png PROJECT_LOGO = images/header_logo_ql.png
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "QP/C" PROJECT_NAME = "QP/C"
PROJECT_NUMBER = "5.9.1" PROJECT_NUMBER = "5.9.2"
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = images/header_logo_ql.png PROJECT_LOGO = images/header_logo_ql.png
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "QP/C" PROJECT_NAME = "QP/C"
PROJECT_NUMBER = "5.9.1" PROJECT_NUMBER = "5.9.2"
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = images/header_logo_ql.png PROJECT_LOGO = images/header_logo_ql.png
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY =

View File

@ -1,6 +1,26 @@
/** /**
@page history Revision History @page history Revision History
@section qpc_5_9_2 Version 5.9.2, 2017-06-05
This release adapts the Makefiles for GNU-ARM to the new location of the
GNU-ARM toolset, which is now included in the QTools Collection (v 5.9.1)
for Windows.
Also, this release improves the flash loading scripts for the JLink
hardware debugger. Specifically, the JLink configuration file for flash
download is generated by the flash batch script based on the command-line
paramter (the binary file to load into the flash). This eliminates the
need to manually maintain JLink configuration files.
Finally, this release implements the feature request #125 "Include QPC
Demo application for STM32F4 processor without RTOS" (see https://sourceforge.net/p/qpc/feature-requests/125/ ). The DPP demo for
the STM32F4-Discovery board has been added in the directory:
qpc\examples\arm-cm\dpp_stm32f4-discovery . This demo includes QV, QK and
QXK kernels and ARM-Keil, GNU-ARM, and IAR-ARM toolsets. The demos support
bi-directional QP/Spy.
------------------------------------------------------------------------------
@section qpc_5_9_1 Version 5.9.1, 2017-05-26 @section qpc_5_9_1 Version 5.9.1, 2017-05-26
This release fixes the following bug: This release fixes the following bug:
- <a href="https://sourceforge.net/p/qpc/bugs/169/" target="_blank" class="extern">bug#169 "Submachine-state eXit Point does not work correctly"</a> - <a href="https://sourceforge.net/p/qpc/bugs/169/" target="_blank" class="extern">bug#169 "Submachine-state eXit Point does not work correctly"</a>

View File

@ -1,8 +1,8 @@
@echo off @echo off
:: ========================================================================== :: ==========================================================================
:: Product: QP/C script for generating Doxygen documentation :: Product: QP/C script for generating Doxygen documentation
:: Last Updated for Version: 5.9.1 :: Last Updated for Version: 5.9.2
:: Date of the Last Update: 2017-05-23 :: Date of the Last Update: 2017-06-05
:: ::
:: Q u a n t u m L e a P s :: Q u a n t u m L e a P s
:: --------------------------- :: ---------------------------
@ -38,7 +38,7 @@ echo usage:
echo make echo make
echo make -CHM echo make -CHM
set VERSION=5.9.1 set VERSION=5.9.2
:: Generate Resource Standard Metrics for QP/C ............................... :: Generate Resource Standard Metrics for QP/C ...............................
set DOXHOME="C:\tools\doxygen\bin" set DOXHOME="C:\tools\doxygen\bin"

View File

@ -1,7 +1,7 @@
/** @page metrics Code Metrics /** @page metrics Code Metrics
@code @code
Standard Code Metrics for QP/C 5.9.1 Standard Code Metrics for QP/C 5.9.2
Resource Standard Metrics (TM) for C, C++, C# and Java Resource Standard Metrics (TM) for C, C++, C# and Java
Version 7.75 - mSquaredTechnologies.com Version 7.75 - mSquaredTechnologies.com
@ -9,7 +9,7 @@
License Type: Windows Single User License License Type: Windows Single User License
Licensed To : Quantum Leaps, LLC Licensed To : Quantum Leaps, LLC
License No. : WS2975 License Date: Dec 15, 2013 License No. : WS2975 License Date: Dec 15, 2013
Build Date : Sep 2 2009 Run Date: May 27, 2017 Build Date : Sep 2 2009 Run Date: Jun 05, 2017
(C)1996-2009 M Squared Technologies LLC (C)1996-2009 M Squared Technologies LLC
________________________________________________________________________ ________________________________________________________________________

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for Blinky on EMF32-SLSTK3401A, QK kernel, GNU-ARM # Product: Makefile for Blinky on EMF32-SLSTK3401A, QK kernel, GNU-ARM
# Last Updated for Version: 5.6.4 # Last Updated for Version: 5.9.1
# Date of the Last Update: 2016-05-08 # Date of the Last Update: 2017-06-03
# #
# Q u a n t u m L e a P s # Q u a n t u m L e a P s
# --------------------------- # ---------------------------
@ -153,7 +153,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -7,22 +7,42 @@
setlocal setlocal
@echo off @echo off
@echo Load the program to the flash of EFM32-SLSTK3401A @echo Load a given binary file to the flash of EFM32-SLSTK3401A
@echo usage: flash @echo usage: flash bin-file
@echo usage: flash rel
@echo usage: flash spy
::---------------------------------------------------------------------------- ::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: JLink utility on your machine :: JLink utility on your machine
:: ::
set JLINK=C:\tools\SEGGER\JLink\Jlink.exe if [%JLINK%] EQU [] set JLINK=%QTOOLS%\..\JLink
if NOT exist "%JLINK%\JLink.exe" (
@echo The JLink tool not found. Please adjust flash.bat
@goto end
)
if [%1] EQU [] (
@echo binary file missing
@goto end
)
if NOT exist "%1" (
@echo The binary file '%1' does not exist
@goto end
)
:: generate the Jlink command file depending on the first parameter %1
@echo si 1 >flash.jlink
@echo speed 4000 >>flash.jlink
@echo r >>flash.jlink
@echo h >>flash.jlink
@echo loadbin %1, 0 >>flash.jlink
@echo exit >>flash.jlink
:: set the Jlink command file depending on the first parameter %1
set CMD_FILE=flash_dbg.jlink
if [%1] NEQ [] set CMD_FILE=flash_%1.jlink
@echo on @echo on
%JLINK%\JLink.exe -device EFM32PG1B200F256GM48 flash.jlink
@echo off
%JLINK% -device EFM32PG1B200F256GM48 %CMD_FILE% @del flash.jlink
:end
endlocal endlocal

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin dbg\blinky-qk.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin rel\blinky-qk.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin spy\blinky-qk.bin, 0
exit

View File

@ -1,70 +0,0 @@
dbg\qf_act.o: file format elf32-littlearm
Disassembly of section .text.QF_add_:
00000000 <QF_add_>:
0: b538 push {r3, r4, r5, lr}
2: 4605 mov r5, r0
4: 6a84 ldr r4, [r0, #40] ; 0x28
6: 1e63 subs r3, r4, #1
8: 2b1f cmp r3, #31
a: d803 bhi.n 14 <QF_add_+0x14>
c: 4b0a ldr r3, [pc, #40] ; (38 <QF_add_+0x38>)
e: f853 3024 ldr.w r3, [r3, r4, lsl #2]
12: b11b cbz r3, 1c <QF_add_+0x1c>
14: 2164 movs r1, #100 ; 0x64
16: 4809 ldr r0, [pc, #36] ; (3c <QF_add_+0x3c>)
18: f7ff fffe bl 0 <Q_onAssert>
1c: f3ef 8311 mrs r3, BASEPRI
20: b672 cpsid i
22: 223f movs r2, #63 ; 0x3f
24: f382 8811 msr BASEPRI, r2
28: b662 cpsie i
2a: 4a03 ldr r2, [pc, #12] ; (38 <QF_add_+0x38>)
2c: f842 5024 str.w r5, [r2, r4, lsl #2]
30: f383 8811 msr BASEPRI, r3
34: bd38 pop {r3, r4, r5, pc}
36: bf00 nop
...
Disassembly of section .text.QF_remove_:
00000000 <QF_remove_>:
0: b538 push {r3, r4, r5, lr}
2: 4604 mov r4, r0
4: 6a85 ldr r5, [r0, #40] ; 0x28
6: 1e6b subs r3, r5, #1
8: 2b1f cmp r3, #31
a: d804 bhi.n 16 <QF_remove_+0x16>
c: 4b0b ldr r3, [pc, #44] ; (3c <QF_remove_+0x3c>)
e: f853 3025 ldr.w r3, [r3, r5, lsl #2]
12: 4298 cmp r0, r3
14: d003 beq.n 1e <QF_remove_+0x1e>
16: 21c8 movs r1, #200 ; 0xc8
18: 4809 ldr r0, [pc, #36] ; (40 <QF_remove_+0x40>)
1a: f7ff fffe bl 0 <Q_onAssert>
1e: f3ef 8311 mrs r3, BASEPRI
22: b672 cpsid i
24: 223f movs r2, #63 ; 0x3f
26: f382 8811 msr BASEPRI, r2
2a: b662 cpsie i
2c: 2200 movs r2, #0
2e: 4903 ldr r1, [pc, #12] ; (3c <QF_remove_+0x3c>)
30: f841 2025 str.w r2, [r1, r5, lsl #2]
34: 6062 str r2, [r4, #4]
36: f383 8811 msr BASEPRI, r3
3a: bd38 pop {r3, r4, r5, pc}
...
Disassembly of section .text.QF_bzero:
00000000 <QF_bzero>:
0: b129 cbz r1, e <QF_bzero+0xe>
2: 1841 adds r1, r0, r1
4: 2300 movs r3, #0
6: f800 3b01 strb.w r3, [r0], #1
a: 4281 cmp r1, r0
c: d1fb bne.n 6 <QF_bzero+0x6>
e: 4770 bx lr

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for Blinky on EMF32-SLSTK3401A, QV kernel, GNU-ARM # Product: Makefile for Blinky on EMF32-SLSTK3401A, QV kernel, GNU-ARM
# Last Updated for Version: 5.8.1 # Last Updated for Version: 5.9.2
# Date of the Last Update: 2016-12-15 # Date of the Last Update: 2017-06-03
# #
# Q u a n t u m L e a P s # Q u a n t u m L e a P s
# --------------------------- # ---------------------------
@ -152,7 +152,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -7,22 +7,42 @@
setlocal setlocal
@echo off @echo off
@echo Load the program to the flash of EFM32-SLSTK3401A @echo Load a given binary file to the flash of EFM32-SLSTK3401A
@echo usage: flash @echo usage: flash bin-file
@echo usage: flash rel
@echo usage: flash spy
::---------------------------------------------------------------------------- ::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: JLink utility on your machine :: JLink utility on your machine
:: ::
set JLINK=C:\tools\SEGGER\JLink\Jlink.exe if [%JLINK%] EQU [] set JLINK=%QTOOLS%\..\JLink
if NOT exist "%JLINK%\JLink.exe" (
@echo The JLink tool not found. Please adjust flash.bat
@goto end
)
if [%1] EQU [] (
@echo binary image missing
@goto end
)
if NOT exist "%1" (
@echo The binary file '%1' does not exist
@goto end
)
:: generate the Jlink command file depending on the first parameter %1
@echo si 1 >flash.jlink
@echo speed 4000 >>flash.jlink
@echo r >>flash.jlink
@echo h >>flash.jlink
@echo loadbin %1, 0 >>flash.jlink
@echo exit >>flash.jlink
:: set the Jlink command file depending on the first parameter %1
set CMD_FILE=flash_dbg.jlink
if [%1] NEQ [] set CMD_FILE=flash_%1.jlink
@echo on @echo on
%JLINK%\JLink.exe -device EFM32PG1B200F256GM48 flash.jlink
@echo off
%JLINK% -device EFM32PG1B200F256GM48 %CMD_FILE% @del flash.jlink
:end
endlocal endlocal

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin dbg\blinky-qv.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin rel\blinky-qv, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin spy\blinky-qv, 0
exit

View File

@ -150,7 +150,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -17,7 +17,7 @@ setlocal
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine :: LMFlash utility on your machine
:: ::
set LMFLASH=C:\tools\TI\LM_Flash_Programmer\LMFlash.exe set LMFLASH=%QTOOLS%\..\LM_Flash_Programmer\LMFlash.exe
:: set the build directory depending on the first parameter %1 :: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg set BUILD_DIR=dbg

View File

@ -149,7 +149,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -17,7 +17,7 @@ setlocal
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine :: LMFlash utility on your machine
:: ::
set LMFLASH=C:\tools\TI\LM_Flash_Programmer\LMFlash.exe set LMFLASH=%QTOOLS%\..\LM_Flash_Programmer\LMFlash.exe
:: set the build directory depending on the first parameter %1 :: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg set BUILD_DIR=dbg

View File

@ -171,7 +171,8 @@ void USART0_RX_IRQHandler(void) {
void USART0_RX_IRQHandler(void) {} void USART0_RX_IRQHandler(void) {}
#endif #endif
/*..........................................................................*/
/* BSP functions ===========================================================*/
void BSP_init(void) { void BSP_init(void) {
/* NOTE: SystemInit() already called from the startup code /* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated * but SystemCoreClock needs to be updated
@ -248,7 +249,7 @@ void BSP_displayPhilStat(uint8_t n, char const *stat) {
QS_BEGIN(PHILO_STAT, AO_Philo[n]) /* application-specific record begin */ QS_BEGIN(PHILO_STAT, AO_Philo[n]) /* application-specific record begin */
QS_U8(1, n); /* Philosopher number */ QS_U8(1, n); /* Philosopher number */
QS_STR(stat); /* Philosopher status */ QS_STR(stat); /* Philosopher status */
QS_END() QS_END() /* application-specific record end */
} }
/*..........................................................................*/ /*..........................................................................*/
void BSP_displayPaused(uint8_t paused) { void BSP_displayPaused(uint8_t paused) {
@ -287,7 +288,7 @@ void BSP_terminate(int16_t result) {
(void)result; (void)result;
} }
/*..........................................................................*/ /* QF callbacks ============================================================*/
void QF_onStartup(void) { void QF_onStartup(void) {
/* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */ /* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */
SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
@ -430,18 +431,9 @@ uint8_t QS_onStartup(void const *arg) {
QS_tickTime_ = QS_tickPeriod_; /* to start the timestamp at zero */ QS_tickTime_ = QS_tickPeriod_; /* to start the timestamp at zero */
/* setup the QS filters... */ /* setup the QS filters... */
QS_FILTER_ON(QS_QEP_STATE_ENTRY); QS_FILTER_ON(QS_SM_RECORDS); /* state machine records */
QS_FILTER_ON(QS_QEP_STATE_EXIT); //QS_FILTER_ON(QS_AO_RECORDS); /* active object records */
QS_FILTER_ON(QS_QEP_STATE_INIT); QS_FILTER_ON(QS_UA_RECORDS); /* all user records */
QS_FILTER_ON(QS_QEP_INIT_TRAN);
QS_FILTER_ON(QS_QEP_INTERN_TRAN);
QS_FILTER_ON(QS_QEP_TRAN);
QS_FILTER_ON(QS_QEP_IGNORED);
QS_FILTER_ON(QS_QEP_DISPATCH);
QS_FILTER_ON(QS_QEP_UNHANDLED);
QS_FILTER_ON(PHILO_STAT);
QS_FILTER_ON(COMMAND_STAT);
return (uint8_t)1; /* return success */ return (uint8_t)1; /* return success */
} }
@ -467,7 +459,7 @@ void QS_onFlush(void) {
/* while TXE not empty */ /* while TXE not empty */
while ((l_USART0->STATUS & USART_STATUS_TXBL) == 0U) { while ((l_USART0->STATUS & USART_STATUS_TXBL) == 0U) {
} }
l_USART0->TXDATA = (b & 0xFFU); /* put into the DR register */ l_USART0->TXDATA = (b & 0xFFU); /* put into the DR register */
QF_INT_DISABLE(); QF_INT_DISABLE();
} }
QF_INT_ENABLE(); QF_INT_ENABLE();

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for DPP on EMF32-SLSTK3401A, QK kernel, GNU-ARM # Product: Makefile for DPP on EMF32-SLSTK3401A, QK kernel, GNU-ARM
# Last Updated for Version: 5.6.4 # Last Updated for Version: 5.9.2
# Date of the Last Update: 2016-05-08 # Date of the Last Update: 2017-06-03
# #
# Q u a n t u m L e a P s # Q u a n t u m L e a P s
# --------------------------- # ---------------------------
@ -155,7 +155,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -7,22 +7,42 @@
setlocal setlocal
@echo off @echo off
@echo Load the program to the flash of EFM32-SLSTK3401A @echo Load a given binary file to the flash of EFM32-SLSTK3401A
@echo usage: flash @echo usage: flash bin-file
@echo usage: flash rel
@echo usage: flash spy
::---------------------------------------------------------------------------- ::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: JLink utility on your machine :: JLink utility on your machine
:: ::
set JLINK=C:\tools\SEGGER\JLink\Jlink.exe if [%JLINK%] EQU [] set JLINK=%QTOOLS%\..\JLink
if NOT exist "%JLINK%\JLink.exe" (
@echo The JLink tool not found. Please adjust flash.bat
@goto end
)
if [%1] EQU [] (
@echo binary image missing
@goto end
)
if NOT exist "%1" (
@echo The binary file '%1' does not exist
@goto end
)
:: generate the Jlink command file depending on the first parameter %1
@echo si 1 >flash.jlink
@echo speed 4000 >>flash.jlink
@echo r >>flash.jlink
@echo h >>flash.jlink
@echo loadbin %1, 0 >>flash.jlink
@echo exit >>flash.jlink
:: set the Jlink command file depending on the first parameter %1
set CMD_FILE=flash_dbg.jlink
if [%1] NEQ [] set CMD_FILE=flash_%1.jlink
@echo on @echo on
%JLINK%\JLink.exe -device EFM32PG1B200F256GM48 flash.jlink
@echo off
%JLINK% -device EFM32PG1B200F256GM48 %CMD_FILE% @del flash.jlink
:end
endlocal endlocal

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin dbg\dpp-qk.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin rel\dpp-qk.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin spy\dpp-qk.bin, 0
exit

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for DPP on EMF32-SLSTK3401A, QV kernel, GNU-ARM # Product: Makefile for DPP on EMF32-SLSTK3401A, QV kernel, GNU-ARM
# Last Updated for Version: 5.8.1 # Last Updated for Version: 5.9.2
# Date of the Last Update: 2016-12-15 # Date of the Last Update: 2017-06-03
# #
# Q u a n t u m L e a P s # Q u a n t u m L e a P s
# --------------------------- # ---------------------------
@ -154,7 +154,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -7,22 +7,42 @@
setlocal setlocal
@echo off @echo off
@echo Load the program to the flash of EFM32-SLSTK3401A @echo Load a given binary file to the flash of EFM32-SLSTK3401A
@echo usage: flash @echo usage: flash bin-file
@echo usage: flash rel
@echo usage: flash spy
::---------------------------------------------------------------------------- ::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: JLink utility on your machine :: JLink utility on your machine
:: ::
set JLINK=C:\tools\SEGGER\JLink\Jlink.exe if [%JLINK%] EQU [] set JLINK=%QTOOLS%\..\JLink
if NOT exist "%JLINK%\JLink.exe" (
@echo The JLink tool not found. Please adjust flash.bat
@goto end
)
if [%1] EQU [] (
@echo binary image missing
@goto end
)
if NOT exist "%1" (
@echo The binary file '%1' does not exist
@goto end
)
:: generate the Jlink command file depending on the first parameter %1
@echo si 1 >flash.jlink
@echo speed 4000 >>flash.jlink
@echo r >>flash.jlink
@echo h >>flash.jlink
@echo loadbin %1, 0 >>flash.jlink
@echo exit >>flash.jlink
:: set the Jlink command file depending on the first parameter %1
set CMD_FILE=flash_dbg.jlink
if [%1] NEQ [] set CMD_FILE=flash_%1.jlink
@echo on @echo on
%JLINK%\JLink.exe -device EFM32PG1B200F256GM48 flash.jlink
@echo off
%JLINK% -device EFM32PG1B200F256GM48 %CMD_FILE% @del flash.jlink
:end
endlocal endlocal

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin dbg\dpp-qv.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin rel\dpp-qv.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin spy\dpp-qv.bin, 0
exit

View File

@ -1,7 +1,7 @@
############################################################################## ##############################################################################
# Product: Makefile for DPP on EMF32-SLSTK3401A, QXK kernel, GNU-ARM # Product: Makefile for DPP on EMF32-SLSTK3401A, QXK kernel, GNU-ARM
# Last Updated for Version: 5.6.4 # Last Updated for Version: 5.9.2
# Date of the Last Update: 2016-05-08 # Date of the Last Update: 2017-06-03
# #
# Q u a n t u m L e a P s # Q u a n t u m L e a P s
# --------------------------- # ---------------------------
@ -158,7 +158,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -7,22 +7,42 @@
setlocal setlocal
@echo off @echo off
@echo Load the program to the flash of EFM32-SLSTK3401A @echo Load a given binary file to the flash of EFM32-SLSTK3401A
@echo usage: flash @echo usage: flash bin-file
@echo usage: flash rel
@echo usage: flash spy
::---------------------------------------------------------------------------- ::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: JLink utility on your machine :: JLink utility on your machine
:: ::
set JLINK=C:\tools\SEGGER\JLink\Jlink.exe if [%JLINK%] EQU [] set JLINK=%QTOOLS%\..\JLink
if NOT exist "%JLINK%\JLink.exe" (
@echo The JLink tool not found. Please adjust flash.bat
@goto end
)
if [%1] EQU [] (
@echo binary image missing
@goto end
)
if NOT exist "%1" (
@echo The binary file '%1' does not exist
@goto end
)
:: generate the Jlink command file depending on the first parameter %1
@echo si 1 >flash.jlink
@echo speed 4000 >>flash.jlink
@echo r >>flash.jlink
@echo h >>flash.jlink
@echo loadbin %1, 0 >>flash.jlink
@echo exit >>flash.jlink
:: set the Jlink command file depending on the first parameter %1
set CMD_FILE=flash_dbg.jlink
if [%1] NEQ [] set CMD_FILE=flash_%1.jlink
@echo on @echo on
%JLINK%\JLink.exe -device EFM32PG1B200F256GM48 flash.jlink
@echo off
%JLINK% -device EFM32PG1B200F256GM48 %CMD_FILE% @del flash.jlink
:end
endlocal endlocal

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin dbg\dpp-qxk.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin rel\dpp-qxk.bin, 0
exit

View File

@ -1,6 +0,0 @@
si 1
speed 4000
r
h
loadbin spy\dpp-qxk.bin, 0
exit

View File

@ -153,7 +153,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -17,7 +17,7 @@ setlocal
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine :: LMFlash utility on your machine
:: ::
set LMFLASH=C:\tools\TI\LM_Flash_Programmer\LMFlash.exe set LMFLASH=%QTOOLS%\..\LM_Flash_Programmer\LMFlash.exe
:: set the build directory depending on the first parameter %1 :: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg set BUILD_DIR=dbg

View File

@ -152,7 +152,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -17,7 +17,7 @@ setlocal
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine :: LMFlash utility on your machine
:: ::
set LMFLASH=C:\tools\TI\LM_Flash_Programmer\LMFlash.exe set LMFLASH=%QTOOLS%\..\LM_Flash_Programmer\LMFlash.exe
:: set the build directory depending on the first parameter %1 :: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg set BUILD_DIR=dbg

View File

@ -156,7 +156,7 @@ FLOAT_ABI := -mfloat-abi=softfp
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -17,7 +17,7 @@ setlocal
:: NOTE: Adjust the following symbol to the location of the :: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine :: LMFlash utility on your machine
:: ::
set LMFLASH=C:\tools\TI\LM_Flash_Programmer\LMFlash.exe set LMFLASH=%QTOOLS%\..\LM_Flash_Programmer\LMFlash.exe
:: set the build directory depending on the first parameter %1 :: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg set BUILD_DIR=dbg

View File

@ -151,7 +151,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -150,7 +150,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -151,7 +151,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -150,7 +150,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -154,7 +154,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -151,7 +151,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -150,7 +150,7 @@ FLOAT_ABI :=
# see http://gnutoolchains.com/arm-eabi/ # see http://gnutoolchains.com/arm-eabi/
# #
ifeq ($(GNU_ARM),) ifeq ($(GNU_ARM),)
GNU_ARM = C:/tools/gnu_arm-eabi GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif endif
# make sure that the GNU-ARM toolset exists... # make sure that the GNU-ARM toolset exists...

View File

@ -0,0 +1,54 @@
/*****************************************************************************
* Product: DPP example
* Last Updated for Version: 5.8.1
* Date of the Last Update: 2016-12-12
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#ifndef bsp_h
#define bsp_h
#define BSP_TICKS_PER_SEC 100U
void BSP_init(void);
void BSP_displayPaused(uint8_t paused);
void BSP_displayPhilStat(uint8_t n, char_t const *stat);
void BSP_terminate(int16_t result);
void BSP_randomSeed(uint32_t seed); /* random seed */
uint32_t BSP_random(void); /* pseudo-random generator */
/* for testing... */
void BSP_wait4PB1(void);
void BSP_ledOn(void);
void BSP_ledOff(void);
extern QActive *the_Ticker0;
#endif /* bsp_h */

View File

@ -0,0 +1,71 @@
/*****************************************************************************
* Model: dpp.qm
* File: ./dpp.h
*
* This code has been generated by QM tool (see state-machine.com/qm).
* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
*
* 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.
*
* 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.
*****************************************************************************/
/*${.::dpp.h} ..............................................................*/
#ifndef dpp_h
#define dpp_h
enum DPPSignals {
EAT_SIG = Q_USER_SIG, /* published by Table to let a philosopher eat */
DONE_SIG, /* published by Philosopher when done eating */
PAUSE_SIG, /* published by BSP to pause serving forks */
SERVE_SIG, /* published by BSP to serve re-start serving forks */
TEST_SIG, /* published by BSP to test the application */
MAX_PUB_SIG, /* the last published signal */
HUNGRY_SIG, /* posted direclty to Table from hungry Philo */
TIMEOUT_SIG, /* used by Philosophers for time events */
MAX_SIG /* the last signal */
};
#if ((QP_VERSION < 580) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8)))
#error qpc version 5.8.0 or higher required
#endif
/*${Events::TableEvt} ......................................................*/
typedef struct {
/* protected: */
QEvt super;
/* public: */
uint8_t philoNum;
} TableEvt;
/* number of philosophers */
#define N_PHILO ((uint8_t)5)
/*${AOs::Philo_ctor} .......................................................*/
void Philo_ctor(void);
extern QMActive * const AO_Philo[N_PHILO];
/*${AOs::Table_ctor} .......................................................*/
void Table_ctor(void);
extern QActive * const AO_Table;
#ifdef qxk_h
void Test1_ctor(void);
extern QXThread * const XT_Test1;
void Test2_ctor(void);
extern QXThread * const XT_Test2;
#endif /* qxk_h */
#endif /* dpp_h */

View File

@ -0,0 +1,445 @@
<?xml version="1.0" encoding="UTF-8"?>
<model version="4.0.0" links="0">
<documentation>Dining Philosopher Problem example
NOTE: Requries QP5.</documentation>
<framework name="qpc"/>
<package name="Events" stereotype="0x01">
<class name="TableEvt" superclass="qpc::QEvt">
<attribute name="philoNum" type="uint8_t" visibility="0x00" properties="0x00"/>
</class>
</package>
<package name="AOs" stereotype="0x02">
<class name="Philo" superclass="qpc::QActive">
<attribute name="timeEvt" type="QTimeEvt" visibility="0x02" properties="0x00"/>
<statechart>
<initial target="../1">
<action>static uint8_t registered = (uint8_t)0; /* starts off with 0, per C-standard */
(void)e; /* suppress the compiler warning about unused parameter */
if (registered == (uint8_t)0) {
registered = (uint8_t)1;
QS_OBJ_DICTIONARY(&amp;l_philo[0]);
QS_OBJ_DICTIONARY(&amp;l_philo[0].timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[1]);
QS_OBJ_DICTIONARY(&amp;l_philo[1].timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[2]);
QS_OBJ_DICTIONARY(&amp;l_philo[2].timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[3]);
QS_OBJ_DICTIONARY(&amp;l_philo[3].timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[4]);
QS_OBJ_DICTIONARY(&amp;l_philo[4].timeEvt);
QS_FUN_DICTIONARY(&amp;Philo_initial);
QS_FUN_DICTIONARY(&amp;Philo_thinking);
QS_FUN_DICTIONARY(&amp;Philo_hungry);
QS_FUN_DICTIONARY(&amp;Philo_eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal for each Philos */
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); /* signal for each Philos */
QActive_subscribe(&amp;me-&gt;super, EAT_SIG);
QActive_subscribe(&amp;me-&gt;super, TEST_SIG);</action>
<initial_glyph conn="2,3,5,1,20,5,-3">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<state name="thinking">
<entry>QTimeEvt_armX(&amp;me-&gt;timeEvt, THINK_TIME, 0U);</entry>
<exit>QTimeEvt_disarm(&amp;me-&gt;timeEvt);</exit>
<tran trig="TIMEOUT" target="../../2">
<tran_glyph conn="2,13,3,1,20,12,-3">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT, DONE">
<action>/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<tran_glyph conn="2,17,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<tran trig="TEST">
<tran_glyph conn="2,20,3,-1,13">
<action box="0,-2,11,4"/>
</tran_glyph>
</tran>
<state_glyph node="2,5,17,16">
<entry box="1,2,5,2"/>
<exit box="1,4,6,2"/>
</state_glyph>
</state>
<state name="hungry">
<entry>TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
pe-&gt;philoNum = PHILO_ID(me);
QACTIVE_POST(AO_Table, &amp;pe-&gt;super, me);</entry>
<tran trig="EAT">
<choice target="../../../3">
<guard>Q_EVT_CAST(TableEvt)-&gt;philoNum == PHILO_ID(me)</guard>
<choice_glyph conn="15,30,5,1,7,13,-3">
<action box="1,0,19,4"/>
</choice_glyph>
</choice>
<tran_glyph conn="2,30,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>/* DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<tran_glyph conn="2,36,3,-1,14">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,23,17,16">
<entry box="1,2,5,2"/>
</state_glyph>
</state>
<state name="eating">
<entry>QTimeEvt_armX(&amp;me-&gt;timeEvt, EAT_TIME, 0U);</entry>
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe-&gt;philoNum = PHILO_ID(me);
QF_PUBLISH(&amp;pe-&gt;super, me);</exit>
<tran trig="TIMEOUT" target="../../1">
<tran_glyph conn="2,51,3,1,22,-41,-5">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT, DONE">
<action>/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<tran_glyph conn="2,55,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,41,17,18">
<entry box="1,2,5,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state_diagram size="37,61"/>
</statechart>
</class>
<class name="Table" superclass="qpc::QActive">
<attribute name="fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="isHungry[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
<statechart>
<initial target="../1/2">
<action>uint8_t n;
(void)e; /* suppress the compiler warning about unused parameter */
QS_OBJ_DICTIONARY(&amp;l_table);
QS_FUN_DICTIONARY(&amp;QHsm_top);
QS_FUN_DICTIONARY(&amp;Table_initial);
QS_FUN_DICTIONARY(&amp;Table_active);
QS_FUN_DICTIONARY(&amp;Table_serving);
QS_FUN_DICTIONARY(&amp;Table_paused);
QS_SIG_DICTIONARY(DONE_SIG, (void *)0); /* global signals */
QS_SIG_DICTIONARY(EAT_SIG, (void *)0);
QS_SIG_DICTIONARY(PAUSE_SIG, (void *)0);
QS_SIG_DICTIONARY(SERVE_SIG, (void *)0);
QS_SIG_DICTIONARY(TEST_SIG, (void *)0);
QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal just for Table */
QActive_subscribe(&amp;me-&gt;super, DONE_SIG);
QActive_subscribe(&amp;me-&gt;super, PAUSE_SIG);
QActive_subscribe(&amp;me-&gt;super, SERVE_SIG);
QActive_subscribe(&amp;me-&gt;super, TEST_SIG);
for (n = 0U; n &lt; N_PHILO; ++n) {
me-&gt;fork[n] = FREE;
me-&gt;isHungry[n] = 0U;
BSP_displayPhilStat(n, &quot;thinking&quot;);
}</action>
<initial_glyph conn="3,3,5,1,44,18,-9">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<state name="active">
<tran trig="TEST">
<tran_glyph conn="2,11,3,-1,14">
<action box="0,-2,11,4"/>
</tran_glyph>
</tran>
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="2,15,3,-1,14">
<action box="0,-2,10,4"/>
</tran_glyph>
</tran>
<state name="serving">
<entry brief="give pending permissions to eat">uint8_t n;
for (n = 0U; n &lt; N_PHILO; ++n) { /* give permissions to eat... */
if ((me-&gt;isHungry[n] != 0U)
&amp;&amp; (me-&gt;fork[LEFT(n)] == FREE)
&amp;&amp; (me-&gt;fork[n] == FREE))
{
TableEvt *te;
me-&gt;fork[LEFT(n)] = USED;
me-&gt;fork[n] = USED;
te = Q_NEW(TableEvt, EAT_SIG);
te-&gt;philoNum = n;
QF_PUBLISH(&amp;te-&gt;super, me);
me-&gt;isHungry[n] = 0U;
BSP_displayPhilStat(n, &quot;eating &quot;);
}
}</entry>
<tran trig="HUNGRY">
<action>uint8_t n, m;
n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (me-&gt;isHungry[n] == 0U));
BSP_displayPhilStat(n, &quot;hungry &quot;);
m = LEFT(n);</action>
<choice>
<guard brief="both free">(me-&gt;fork[m] == FREE) &amp;&amp; (me-&gt;fork[n] == FREE)</guard>
<action>TableEvt *pe;
me-&gt;fork[m] = USED;
me-&gt;fork[n] = USED;
pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = n;
QF_PUBLISH(&amp;pe-&gt;super, me);
BSP_displayPhilStat(n, &quot;eating &quot;);</action>
<choice_glyph conn="19,26,5,-1,10">
<action box="1,0,10,2"/>
</choice_glyph>
</choice>
<choice>
<guard>else</guard>
<action>me-&gt;isHungry[n] = 1U;</action>
<choice_glyph conn="19,26,4,-1,5,10">
<action box="1,5,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,26,3,-1,15">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>uint8_t n, m;
TableEvt *pe;
n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (me-&gt;isHungry[n] == 0U));
BSP_displayPhilStat(n, &quot;thinking&quot;);
m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me-&gt;fork[n] == USED) &amp;&amp; (me-&gt;fork[m] == USED));
me-&gt;fork[m] = FREE;
me-&gt;fork[n] = FREE;
m = RIGHT(n); /* check the right neighbor */
if ((me-&gt;isHungry[m] != 0U) &amp;&amp; (me-&gt;fork[m] == FREE)) {
me-&gt;fork[n] = USED;
me-&gt;fork[m] = USED;
me-&gt;isHungry[m] = 0U;
pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = m;
QF_PUBLISH(&amp;pe-&gt;super, me);
BSP_displayPhilStat(m, &quot;eating &quot;);
}
m = LEFT(n); /* check the left neighbor */
n = LEFT(m); /* left fork of the left neighbor */
if ((me-&gt;isHungry[m] != 0U) &amp;&amp; (me-&gt;fork[n] == FREE)) {
me-&gt;fork[m] = USED;
me-&gt;fork[n] = USED;
me-&gt;isHungry[m] = 0U;
pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = m;
QF_PUBLISH(&amp;pe-&gt;super, me);
BSP_displayPhilStat(m, &quot;eating &quot;);
}</action>
<tran_glyph conn="4,34,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="4,37,3,-1,15">
<action box="0,-2,12,4"/>
</tran_glyph>
</tran>
<tran trig="PAUSE" target="../../3">
<tran_glyph conn="4,41,3,1,37,6,-3">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,19,34,24">
<entry box="1,2,27,2"/>
</state_glyph>
</state>
<state name="paused">
<entry>BSP_displayPaused(1U);</entry>
<exit>BSP_displayPaused(0U);</exit>
<tran trig="SERVE" target="../../2">
<tran_glyph conn="4,57,3,1,39,-20,-5">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<tran trig="HUNGRY">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
/* philo ID must be in range and he must be not hungry */
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (me-&gt;isHungry[n] == 0U));
me-&gt;isHungry[n] = 1U;
BSP_displayPhilStat(n, &quot;hungry &quot;);</action>
<tran_glyph conn="4,60,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="DONE">
<action>uint8_t n, m;
n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (me-&gt;isHungry[n] == 0U));
BSP_displayPhilStat(n, &quot;thinking&quot;);
m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me-&gt;fork[n] == USED) &amp;&amp; (me-&gt;fork[m] == USED));
me-&gt;fork[m] = FREE;
me-&gt;fork[n] = FREE;</action>
<tran_glyph conn="4,63,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,45,34,20">
<entry box="1,2,18,4"/>
<exit box="1,6,18,4"/>
</state_glyph>
</state>
<state_glyph node="2,5,43,62"/>
</state>
<state_diagram size="49,69"/>
</statechart>
</class>
<attribute name="AO_Philo[N_PHILO]" type="QMActive * const" visibility="0x00" properties="0x00"/>
<attribute name="AO_Table" type="QActive * const" visibility="0x00" properties="0x00"/>
<operation name="Philo_ctor" type="void" visibility="0x00" properties="0x00">
<code>uint8_t n;
Philo *me;
for (n = 0U; n &lt; N_PHILO; ++n) {
me = &amp;l_philo[n];
QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Philo_initial));
QTimeEvt_ctorX(&amp;me-&gt;timeEvt, &amp;me-&gt;super, TIMEOUT_SIG, 0U);
}</code>
</operation>
<operation name="Table_ctor" type="void" visibility="0x00" properties="0x00">
<code>uint8_t n;
Table *me = &amp;l_table;
QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Table_initial));
for (n = 0U; n &lt; N_PHILO; ++n) {
me-&gt;fork[n] = FREE;
me-&gt;isHungry[n] = 0U;
}</code>
</operation>
</package>
<directory name=".">
<file name="dpp.h">
<text>#ifndef dpp_h
#define dpp_h
enum DPPSignals {
EAT_SIG = Q_USER_SIG, /* published by Table to let a philosopher eat */
DONE_SIG, /* published by Philosopher when done eating */
PAUSE_SIG, /* published by BSP to pause serving forks */
SERVE_SIG, /* published by BSP to serve re-start serving forks */
TEST_SIG, /* published by BSP to test the application */
MAX_PUB_SIG, /* the last published signal */
HUNGRY_SIG, /* posted direclty to Table from hungry Philo */
TIMEOUT_SIG, /* used by Philosophers for time events */
MAX_SIG /* the last signal */
};
$declare(Events::TableEvt)
/* number of philosophers */
#define N_PHILO ((uint8_t)5)
$declare(AOs::Philo_ctor)
$declare(AOs::AO_Philo[N_PHILO])
$declare(AOs::Table_ctor)
$declare(AOs::AO_Table)
#ifdef qxk_h
void Test1_ctor(void);
extern QXThread * const XT_Test1;
void Test2_ctor(void);
extern QXThread * const XT_Test2;
#endif /* qxk_h */
#endif /* dpp_h */</text>
</file>
<file name="philo.c">
<text>#include &quot;qpc.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
Q_DEFINE_THIS_FILE
/* Active object class -----------------------------------------------------*/
$declare(AOs::Philo)
/* Local objects -----------------------------------------------------------*/
static Philo l_philo[N_PHILO]; /* storage for all Philos */
#define THINK_TIME \
(QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + (BSP_TICKS_PER_SEC/2U))
#define EAT_TIME \
(QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + BSP_TICKS_PER_SEC)
/* helper macro to provide the ID of Philo &quot;me_&quot; */
#define PHILO_ID(me_) ((uint8_t)((me_) - l_philo))
/* Global objects ----------------------------------------------------------*/
QMActive * const AO_Philo[N_PHILO] = { /* &quot;opaque&quot; pointers to Philo AO */
&amp;l_philo[0].super,
&amp;l_philo[1].super,
&amp;l_philo[2].super,
&amp;l_philo[3].super,
&amp;l_philo[4].super
};
/* Philo definition --------------------------------------------------------*/
$define(AOs::Philo_ctor)
$define(AOs::Philo)</text>
</file>
<file name="table.c">
<text>#include &quot;qpc.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
Q_DEFINE_THIS_FILE
/* Active object class -----------------------------------------------------*/
$declare(AOs::Table)
#define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1U)) % N_PHILO))
#define LEFT(n_) ((uint8_t)(((n_) + 1U) % N_PHILO))
#define FREE ((uint8_t)0)
#define USED ((uint8_t)1)
/* Local objects -----------------------------------------------------------*/
static Table l_table; /* the single instance of the Table active object */
/* Global-scope objects ----------------------------------------------------*/
QMActive * const AO_Table = &amp;l_table.super; /* &quot;opaque&quot; AO pointer */
/*..........................................................................*/
$define(AOs::Table_ctor)
$define(AOs::Table)</text>
</file>
</directory>
</model>

View File

@ -0,0 +1,225 @@
/*****************************************************************************
* Model: dpp.qm
* File: ./philo.c
*
* This code has been generated by QM tool (see state-machine.com/qm).
* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
*
* 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.
*
* 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.
*****************************************************************************/
/*${.::philo.c} ............................................................*/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
Q_DEFINE_THIS_FILE
/* Active object class -----------------------------------------------------*/
#if ((QP_VERSION < 580) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8)))
#error qpc version 5.8.0 or higher required
#endif
/*${AOs::Philo} ............................................................*/
typedef struct {
/* protected: */
QActive super;
/* private: */
QTimeEvt timeEvt;
} Philo;
/* protected: */
static QState Philo_initial(Philo * const me, QEvt const * const e);
static QState Philo_thinking(Philo * const me, QEvt const * const e);
static QState Philo_hungry(Philo * const me, QEvt const * const e);
static QState Philo_eating(Philo * const me, QEvt const * const e);
/* Local objects -----------------------------------------------------------*/
static Philo l_philo[N_PHILO]; /* storage for all Philos */
#define THINK_TIME \
(QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + (BSP_TICKS_PER_SEC/2U))
#define EAT_TIME \
(QTimeEvtCtr)((BSP_random() % BSP_TICKS_PER_SEC) + BSP_TICKS_PER_SEC)
/* helper macro to provide the ID of Philo "me_" */
#define PHILO_ID(me_) ((uint8_t)((me_) - l_philo))
/* Global objects ----------------------------------------------------------*/
QMActive * const AO_Philo[N_PHILO] = { /* "opaque" pointers to Philo AO */
&l_philo[0].super,
&l_philo[1].super,
&l_philo[2].super,
&l_philo[3].super,
&l_philo[4].super
};
/* Philo definition --------------------------------------------------------*/
/*${AOs::Philo_ctor} .......................................................*/
void Philo_ctor(void) {
uint8_t n;
Philo *me;
for (n = 0U; n < N_PHILO; ++n) {
me = &l_philo[n];
QActive_ctor(&me->super, Q_STATE_CAST(&Philo_initial));
QTimeEvt_ctorX(&me->timeEvt, &me->super, TIMEOUT_SIG, 0U);
}
}
/*${AOs::Philo} ............................................................*/
/*${AOs::Philo::SM} ........................................................*/
static QState Philo_initial(Philo * const me, QEvt const * const e) {
/* ${AOs::Philo::SM::initial} */
static uint8_t registered = (uint8_t)0; /* starts off with 0, per C-standard */
(void)e; /* suppress the compiler warning about unused parameter */
if (registered == (uint8_t)0) {
registered = (uint8_t)1;
QS_OBJ_DICTIONARY(&l_philo[0]);
QS_OBJ_DICTIONARY(&l_philo[0].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[1]);
QS_OBJ_DICTIONARY(&l_philo[1].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[2]);
QS_OBJ_DICTIONARY(&l_philo[2].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[3]);
QS_OBJ_DICTIONARY(&l_philo[3].timeEvt);
QS_OBJ_DICTIONARY(&l_philo[4]);
QS_OBJ_DICTIONARY(&l_philo[4].timeEvt);
QS_FUN_DICTIONARY(&Philo_initial);
QS_FUN_DICTIONARY(&Philo_thinking);
QS_FUN_DICTIONARY(&Philo_hungry);
QS_FUN_DICTIONARY(&Philo_eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal for each Philos */
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); /* signal for each Philos */
QActive_subscribe(&me->super, EAT_SIG);
QActive_subscribe(&me->super, TEST_SIG);
return Q_TRAN(&Philo_thinking);
}
/*${AOs::Philo::SM::thinking} ..............................................*/
static QState Philo_thinking(Philo * const me, QEvt const * const e) {
QState status_;
switch (e->sig) {
/* ${AOs::Philo::SM::thinking} */
case Q_ENTRY_SIG: {
QTimeEvt_armX(&me->timeEvt, THINK_TIME, 0U);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Philo::SM::thinking} */
case Q_EXIT_SIG: {
QTimeEvt_disarm(&me->timeEvt);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Philo::SM::thinking::TIMEOUT} */
case TIMEOUT_SIG: {
status_ = Q_TRAN(&Philo_hungry);
break;
}
/* ${AOs::Philo::SM::thinking::EAT, DONE} */
case EAT_SIG: /* intentionally fall through */
case DONE_SIG: {
/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
status_ = Q_HANDLED();
break;
}
/* ${AOs::Philo::SM::thinking::TEST} */
case TEST_SIG: {
status_ = Q_HANDLED();
break;
}
default: {
status_ = Q_SUPER(&QHsm_top);
break;
}
}
return status_;
}
/*${AOs::Philo::SM::hungry} ................................................*/
static QState Philo_hungry(Philo * const me, QEvt const * const e) {
QState status_;
switch (e->sig) {
/* ${AOs::Philo::SM::hungry} */
case Q_ENTRY_SIG: {
TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
pe->philoNum = PHILO_ID(me);
QACTIVE_POST(AO_Table, &pe->super, me);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Philo::SM::hungry::EAT} */
case EAT_SIG: {
/* ${AOs::Philo::SM::hungry::EAT::[Q_EVT_CAST(TableEvt)->philoNum=~} */
if (Q_EVT_CAST(TableEvt)->philoNum == PHILO_ID(me)) {
status_ = Q_TRAN(&Philo_eating);
}
else {
status_ = Q_UNHANDLED();
}
break;
}
/* ${AOs::Philo::SM::hungry::DONE} */
case DONE_SIG: {
/* DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
status_ = Q_HANDLED();
break;
}
default: {
status_ = Q_SUPER(&QHsm_top);
break;
}
}
return status_;
}
/*${AOs::Philo::SM::eating} ................................................*/
static QState Philo_eating(Philo * const me, QEvt const * const e) {
QState status_;
switch (e->sig) {
/* ${AOs::Philo::SM::eating} */
case Q_ENTRY_SIG: {
QTimeEvt_armX(&me->timeEvt, EAT_TIME, 0U);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Philo::SM::eating} */
case Q_EXIT_SIG: {
TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe->philoNum = PHILO_ID(me);
QF_PUBLISH(&pe->super, me);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Philo::SM::eating::TIMEOUT} */
case TIMEOUT_SIG: {
status_ = Q_TRAN(&Philo_thinking);
break;
}
/* ${AOs::Philo::SM::eating::EAT, DONE} */
case EAT_SIG: /* intentionally fall through */
case DONE_SIG: {
/* EAT or DONE must be for other Philos than this one */
Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));
status_ = Q_HANDLED();
break;
}
default: {
status_ = Q_SUPER(&QHsm_top);
break;
}
}
return status_;
}

View File

@ -0,0 +1,24 @@
About this Example
==================
This example demonstrates how to use the uVision IDE together with
the MDK-ARM toolchain.
uVision Project File
====================
The MDK-ARM uVision project file provided with this example uses
relative paths to the QP/C framework location (includes, port, and
libraries. These relative paths must be modified when the project
is moved to different relative location.
Adjusting Stack and Heap Sizes
==============================
The stack and heap sizes are determined in this project by the
command-line options for the ARM assembler (see the Asm tab in
the "Options for Target" dialog box in uVision). Specifically,
you should define symbols: Stack_Size=xxx Heap_Size=yyy, where
xxx represents a numerical value of stack size and yyy the
numberical value of the heap size (for most embedded projects
yyy should be 0, as the using the heap is not recommended).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,534 @@
/*****************************************************************************
* Product: "DPP" example on STM32F4-Discovery board, preemptive QK kernel
* Last Updated for Version: 5.9.1
* Date of the Last Update: 2017-06-01
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
#include "stm32f4xx.h" /* CMSIS-compliant header file for the MCU used */
#include "stm32f4xx_exti.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
/* add other drivers if necessary... */
Q_DEFINE_THIS_FILE
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
*/
enum KernelUnawareISRs { /* see NOTE00 */
USART2_PRIO,
/* ... */
MAX_KERNEL_UNAWARE_CMSIS_PRI /* keep always last */
};
/* "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts */
Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI);
enum KernelAwareISRs {
SYSTICK_PRIO = QF_AWARE_ISR_CMSIS_PRI, /* see NOTE00 */
/* ... */
MAX_KERNEL_AWARE_CMSIS_PRI /* keep always last */
};
/* "kernel-aware" interrupts should not overlap the PendSV priority */
Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
/* ISRs defined in this BSP ------------------------------------------------*/
void SysTick_Handler(void);
void USART2_IRQHandler(void);
/* Local-scope defines -----------------------------------------------------*/
#define LED_GPIO_PORT GPIOD
#define LED_GPIO_CLK RCC_AHB1Periph_GPIOD
#define LED4_PIN GPIO_Pin_12
#define LED3_PIN GPIO_Pin_13
#define LED5_PIN GPIO_Pin_14
#define LED6_PIN GPIO_Pin_15
#define BTN_GPIO_PORT GPIOA
#define BTN_GPIO_CLK RCC_AHB1Periph_GPIOA
#define BTN_B1 GPIO_Pin_0
static uint32_t l_rnd; /* random seed */
static QMutex l_rndMutex; /* mutex to protect the random seed */
#ifdef Q_SPY
static QSTimeCtr QS_tickTime_;
static QSTimeCtr QS_tickPeriod_;
/* event-source identifiers used for tracing */
static uint8_t const l_SysTick;
enum AppRecords { /* application-specific trace records */
PHILO_STAT = QS_USER,
COMMAND_STAT
};
#endif
/* ISRs used in this project ===============================================*/
void SysTick_Handler(void) {
/* state of the button debouncing, see below */
static struct ButtonsDebouncing {
uint32_t depressed;
uint32_t previous;
} buttons = { 0U, 0U };
uint32_t current;
uint32_t tmp;
QK_ISR_ENTRY(); /* inform QK about entering an ISR */
#ifdef Q_SPY
{
tmp = SysTick->CTRL; /* clear SysTick_CTRL_COUNTFLAG */
QS_tickTime_ += QS_tickPeriod_; /* account for the clock rollover */
}
#endif
QF_TICK_X(0U, &l_SysTick);
/* Perform the debouncing of buttons. The algorithm for debouncing
* adapted from the book "Embedded Systems Dictionary" by Jack Ganssle
* and Michael Barr, page 71.
*/
current = BTN_GPIO_PORT->IDR; /* read BTN GPIO */
tmp = buttons.depressed; /* save the debounced depressed buttons */
buttons.depressed |= (buttons.previous & current); /* set depressed */
buttons.depressed &= (buttons.previous | current); /* clear released */
buttons.previous = current; /* update the history */
tmp ^= buttons.depressed; /* changed debounced depressed */
if ((tmp & BTN_B1) != 0U) { /* debounced B1 state changed? */
if ((buttons.depressed & BTN_B1) != 0U) { /* is B1 depressed? */
static QEvt const pauseEvt = { PAUSE_SIG, 0U, 0U};
QF_PUBLISH(&pauseEvt, &l_SysTick);
}
else { /* the button is released */
static QEvt const serveEvt = { SERVE_SIG, 0U, 0U};
QF_PUBLISH(&serveEvt, &l_SysTick);
}
}
QK_ISR_EXIT(); /* inform QK about exiting an ISR */
}
/*..........................................................................*/
#ifdef Q_SPY
/*
* ISR for receiving bytes from the QSPY Back-End
* NOTE: This ISR is "QF-unaware" meaning that it does not interact with
* the QF/QK and is not disabled. Such ISRs don't need to call QK_ISR_ENTRY/
* QK_ISR_EXIT and they cannot post or publish events.
*/
void USART2_IRQHandler(void) {
if ((USART2->SR & USART_SR_RXNE) != 0) {
uint32_t b = USART2->DR;
QS_RX_PUT(b);
}
}
#else
void USART2_IRQHandler(void) {}
#endif
/* BSP functions ===========================================================*/
void BSP_init(void) {
/* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* configure the FPU usage by choosing one of the options... */
#if 1
/* OPTION 1:
* Use the automatic FPU state preservation and the FPU lazy stacking.
*
* NOTE:
* Use the following setting when FPU is used in more than one task or
* in any ISRs. This setting is the safest and recommended, but requires
* extra stack space and CPU cycles.
*/
FPU->FPCCR |= (1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos);
#else
/* OPTION 2:
* Do NOT to use the automatic FPU state preservation and
* do NOT to use the FPU lazy stacking.
*
* NOTE:
* Use the following setting when FPU is used in ONE task only and not
* in any ISR. This setting is very efficient, but if more than one task
* (or ISR) start using the FPU, this can lead to corruption of the
* FPU registers. This option should be used with CAUTION.
*/
FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
#endif
GPIO_InitTypeDef GPIO_struct;
/* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* Explictily Disable the automatic FPU state preservation as well as
* the FPU lazy stacking
*/
FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
/* Initialize thr port for the LEDs */
RCC_AHB1PeriphClockCmd(LED_GPIO_CLK , ENABLE);
/* GPIO Configuration for the LEDs... */
GPIO_struct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_struct.GPIO_Pin = LED3_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED3_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED4_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED4_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED5_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED5_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED6_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */
/* Initialize thr port for Button */
RCC_AHB1PeriphClockCmd(BTN_GPIO_CLK , ENABLE);
/* GPIO Configuration for the Button... */
GPIO_struct.GPIO_Pin = BTN_B1;
GPIO_struct.GPIO_Mode = GPIO_Mode_IN;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BTN_GPIO_PORT, &GPIO_struct);
/* seed the random number generator */
BSP_randomSeed(1234U);
if (QS_INIT((void *)0) == 0U) { /* initialize the QS software tracing */
Q_ERROR();
}
QS_OBJ_DICTIONARY(&l_SysTick);
QS_USR_DICTIONARY(PHILO_STAT);
QS_USR_DICTIONARY(COMMAND_STAT);
}
/*..........................................................................*/
void BSP_displayPhilStat(uint8_t n, char const *stat) {
(void)n;
if (stat[0] == 'h') {
LED_GPIO_PORT->BSRRL = LED3_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED3_PIN; /* turn LED off */
}
if (stat[0] == 'e') {
LED_GPIO_PORT->BSRRL = LED5_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED5_PIN; /* turn LED on */
}
QS_BEGIN(PHILO_STAT, AO_Philo[n]) /* application-specific record begin */
QS_U8(1, n); /* Philosopher number */
QS_STR(stat); /* Philosopher status */
QS_END() /* application-specific record end */
}
/*..........................................................................*/
void BSP_displayPaused(uint8_t paused) {
if (paused) {
LED_GPIO_PORT->BSRRL = LED4_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED4_PIN; /* turn LED on */
}
}
/*..........................................................................*/
uint32_t BSP_random(void) { /* a very cheap pseudo-random-number generator */
uint32_t rnd;
/* exercise the FPU with some floating point computations */
/* NOTE: this code can be only called from a task that created with
* the option OS_TASK_OPT_SAVE_FP.
*/
float volatile x = 3.1415926F;
x = x + 2.7182818F;
QMutex_lock(&l_rndMutex); /* lock the random-seed mutex */
/* "Super-Duper" Linear Congruential Generator (LCG)
* LCG(2^32, 3*7*11*13*23, 0, seed)
*/
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; /* set for the next time */
QMutex_unlock(&l_rndMutex); /* unlock the random-seed mutex */
return (rnd >> 8);
}
/*..........................................................................*/
void BSP_randomSeed(uint32_t seed) {
l_rnd = seed;
QMutex_init(&l_rndMutex, N_PHILO); /* ceiling == max Philo priority */
}
/*..........................................................................*/
void BSP_terminate(int16_t result) {
(void)result;
}
/* QF callbacks ============================================================*/
void QF_onStartup(void) {
/* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */
SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
/* assing all priority bits for preemption-prio. and none to sub-prio. */
NVIC_SetPriorityGrouping(0U);
/* set priorities of ALL ISRs used in the system, see NOTE00
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
*/
NVIC_SetPriority(USART2_IRQn, USART2_PRIO);
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO);
/* ... */
/* enable IRQs... */
#ifdef Q_SPY
NVIC_EnableIRQ(USART2_IRQn); /* USART2 interrupt used for QS-RX */
#endif
}
/*..........................................................................*/
void QF_onCleanup(void) {
}
/*..........................................................................*/
void QK_onIdle(void) {
QF_INT_DISABLE();
LED_GPIO_PORT->BSRRL = LED6_PIN; /* turn LED on */
__NOP(); /* wait a little to actually see the LED glow */
__NOP();
__NOP();
__NOP();
LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */
QF_INT_ENABLE();
#ifdef Q_SPY
QS_rxParse(); /* parse all the received bytes */
if ((USART2->SR & USART_FLAG_TXE) != 0) { /* is TXE empty? */
uint16_t b;
QF_INT_DISABLE();
b = QS_getByte();
QF_INT_ENABLE();
if (b != QS_EOD) { /* not End-Of-Data? */
USART2->DR = (b & 0xFFU); /* put into the DR register */
}
}
#elif defined NDEBUG
/* Put the CPU and peripherals to the low-power mode.
* you might need to customize the clock management for your application,
* see the datasheet for your particular Cortex-M3 MCU.
*/
/* !!!CAUTION!!!
* The WFI instruction stops the CPU clock, which unfortunately disables
* the JTAG port, so the ST-Link debugger can no longer connect to the
* board. For that reason, the call to __WFI() has to be used with CAUTION.
*
* NOTE: If you find your board "frozen" like this, strap BOOT0 to VDD and
* reset the board, then connect with ST-Link Utilities and erase the part.
* The trick with BOOT(0) is it gets the part to run the System Loader
* instead of your broken code. When done disconnect BOOT0, and start over.
*/
//__WFI(); /* Wait-For-Interrupt */
#endif
}
/*..........................................................................*/
void Q_onAssert(char const *module, int loc) {
/*
* NOTE: add here your application-specific error handling
*/
(void)module;
(void)loc;
QS_ASSERTION(module, loc, (uint32_t)10000U); /* report assertion to QS */
NVIC_SystemReset();
}
/* QS callbacks ============================================================*/
#ifdef Q_SPY
/*..........................................................................*/
uint8_t QS_onStartup(void const *arg) {
static uint8_t qsBuf[2*1024]; /* buffer for QS-TX channel */
static uint8_t qsRxBuf[100]; /* buffer for QS-RX channel */
GPIO_InitTypeDef GPIO_struct;
USART_InitTypeDef USART_struct;
(void)arg; /* avoid the "unused parameter" compiler warning */
QS_initBuf(qsBuf, sizeof(qsBuf));
QS_rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
/* enable peripheral clock for USART2 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* GPIOA Configuration: USART2 TX on PA2 and RX on PA3 */
GPIO_struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_struct.GPIO_Mode = GPIO_Mode_AF;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_struct);
/* Connect USART2 pins to AF2 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); /* TX = PA2 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); /* RX = PA3 */
USART_struct.USART_BaudRate = 115200;
USART_struct.USART_WordLength = USART_WordLength_8b;
USART_struct.USART_StopBits = USART_StopBits_1;
USART_struct.USART_Parity = USART_Parity_No;
USART_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_struct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_struct);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); /* enable RX interrupt */
USART_Cmd(USART2, ENABLE); /* enable USART2 */
QS_tickPeriod_ = SystemCoreClock / BSP_TICKS_PER_SEC;
QS_tickTime_ = QS_tickPeriod_; /* to start the timestamp at zero */
/* setup the QS filters... */
QS_FILTER_ON(QS_SM_RECORDS); /* state machine records */
QS_FILTER_ON(QS_AO_RECORDS); /* active object records */
QS_FILTER_ON(QS_UA_RECORDS); /* all user records */
return (uint8_t)1; /* return success */
}
/*..........................................................................*/
void QS_onCleanup(void) {
}
/*..........................................................................*/
QSTimeCtr QS_onGetTime(void) { /* NOTE: invoked with interrupts DISABLED */
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) { /* not set? */
return QS_tickTime_ - (QSTimeCtr)SysTick->VAL;
}
else { /* the rollover occured, but the SysTick_ISR did not run yet */
return QS_tickTime_ + QS_tickPeriod_ - (QSTimeCtr)SysTick->VAL;
}
}
/*..........................................................................*/
void QS_onFlush(void) {
uint16_t b;
QF_INT_DISABLE();
while ((b = QS_getByte()) != QS_EOD) { /* while not End-Of-Data... */
QF_INT_ENABLE();
while ((USART2->SR & USART_FLAG_TXE) == 0) { /* while TXE not empty */
}
USART2->DR = (b & 0xFFU); /* put into the DR register */
QF_INT_DISABLE();
}
QF_INT_ENABLE();
}
/*..........................................................................*/
void QS_onReset(void) {
NVIC_SystemReset();
}
/*..........................................................................*/
void QS_onCommand(uint8_t cmdId,
uint32_t param1, uint32_t param2, uint32_t param3)
{
void assert_failed(char const *module, int loc);
(void)cmdId;
(void)param1;
(void)param2;
(void)param3;
QS_BEGIN(COMMAND_STAT, (void *)1) /* application-specific record begin */
QS_U8(2, cmdId);
QS_U32(8, param1);
QS_U32(8, param2);
QS_U32(8, param3);
QS_END()
if (cmdId == 10U) {
Q_ERROR();
}
else if (cmdId == 11U) {
assert_failed("QS_onCommand", 123);
}
}
#endif /* Q_SPY */
/*--------------------------------------------------------------------------*/
/*****************************************************************************
* NOTE00:
* The QF_AWARE_ISR_CMSIS_PRI constant from the QF port specifies the highest
* ISR priority that is disabled by the QF framework. The value is suitable
* for the NVIC_SetPriority() CMSIS function.
*
* Only ISRs prioritized at or below the QF_AWARE_ISR_CMSIS_PRI level (i.e.,
* with the numerical values of priorities equal or higher than
* QF_AWARE_ISR_CMSIS_PRI) are allowed to call any QF services. These ISRs
* are "QF-aware".
*
* Conversely, any ISRs prioritized above the QF_AWARE_ISR_CMSIS_PRI priority
* level (i.e., with the numerical values of priorities less than
* QF_AWARE_ISR_CMSIS_PRI) are never disabled and are not aware of the kernel.
* Such "QF-unaware" ISRs cannot call any QF services. The only mechanism
* by which a "QF-unaware" ISR can communicate with the QF framework is by
* triggering a "QF-aware" ISR, which can post/publish events.
*
* NOTE01:
* The QV_onIdle() callback is called with interrupts disabled, because the
* determination of the idle condition might change by any interrupt posting
* an event. QV_onIdle() must internally enable interrupts, ideally
* atomically with putting the CPU to the power-saving mode.
*
* NOTE02:
* One of the LEDs is used to visualize the idle loop activity. The brightness
* of the LED is proportional to the frequency of invcations of the idle loop.
* Please note that the LED is toggled with interrupts locked, so no interrupt
* execution time contributes to the brightness of the User LED.
*/

View File

@ -0,0 +1,328 @@
##############################################################################
# Product: DPP on STM32F4-Discovery, QK, GNU-ARM gnutoolchains.com/arm-eabi
# Last Updated for Version: 5.9.1
# Date of the Last Update: 2017-06-01
#
# Q u a n t u m L e a P s
# ---------------------------
# innovating embedded systems
#
# Copyright (C) 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 3 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:
# https://state-machine.com
# mailto:info@state-machine.com
##############################################################################
# examples of invoking this Makefile:
# building configurations: Debug (default), Release, and Spy
# make
# make CONF=rel
# make CONF=spy
#
# cleaning configurations: Debug (default), Release, and Spy
# make clean
# make CONF=rel clean
# make CONF=spy clean
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
# is included in the Qtools collection for Windows, see:
# http://sourceforge.net/projects/qpc/files/Qtools/
#
#-----------------------------------------------------------------------------
# project name
#
PROJECT := dpp-qk
#-----------------------------------------------------------------------------
# project directories
#
# location of the QP/C framework (if not provided in an environemnt var.)
ifeq ($(QPC),)
QPC := ../../../../..
endif
# QP port used in this project
QP_PORT_DIR := $(QPC)/ports/arm-cm/qk/gnu
# list of all source directories used by this project
VPATH = \
.. \
../.. \
$(QPC)/src/qf \
$(QPC)/src/qk \
$(QPC)/src/qs \
$(QP_PORT_DIR) \
$(QPC)/3rd_party/stm32f4-discovery \
$(QPC)/3rd_party/stm32f4-discovery/src \
$(QPC)/3rd_party/stm32f4-discovery/gnu
# list of all include directories needed by this project
INCLUDES = \
-I../.. \
-I$(QPC)/include \
-I$(QPC)/src \
-I$(QP_PORT_DIR) \
-I$(QPC)/3rd_party/CMSIS/Include \
-I$(QPC)/3rd_party/stm32f4-discovery \
-I$(QPC)/3rd_party/stm32f4-discovery/inc
#-----------------------------------------------------------------------------
# files
#
# assembler source files
ASM_SRCS :=
# C source files
C_SRCS := \
bsp.c \
main.c \
philo.c \
table.c \
system_stm32f4xx.c \
startup_stm32f4xx.c \
stm32f4xx_gpio.c \
stm32f4xx_rcc.c \
stm32f4xx_usart.c
# C++ source files
CPP_SRCS :=
OUTPUT := $(PROJECT)
LD_SCRIPT := $(PROJECT).ld
QP_SRCS := \
qep_hsm.c \
qep_msm.c \
qf_act.c \
qf_actq.c \
qf_defer.c \
qf_dyn.c \
qf_mem.c \
qf_ps.c \
qf_qact.c \
qf_qeq.c \
qf_qmact.c \
qf_time.c \
qk.c \
qk_mutex.c
QP_ASMS := \
qk_port.s
QS_SRCS := \
qs.c \
qs_rx.c \
qs_fp.c
LIB_DIRS :=
LIBS :=
# defines
DEFINES :=
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
# ARM_ARCH: [6 | 7] (NOTE: must match ARM_CPU!)
# ARM_FPU: [ | vfp]
# FLOAT_ABI: [ | soft | softfp | hard]
#
ARM_CPU := -mcpu=cortex-m4
ARM_ARCH := 7 # NOTE: must match the ARM_CPU!
ARM_FPU := -mfpu=vfp
FLOAT_ABI := -mfloat-abi=softfp
#-----------------------------------------------------------------------------
# GNU-ARM toolset (NOTE: You need to adjust to your machine)
# see http://gnutoolchains.com/arm-eabi/
#
ifeq ($(GNU_ARM),)
GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif
# make sure that the GNU-ARM toolset exists...
ifeq ("$(wildcard $(GNU_ARM))","")
$(error GNU_ARM toolset not found. Please adjust the Makefile)
endif
CC := $(GNU_ARM)/bin/arm-eabi-gcc
CPP := $(GNU_ARM)/bin/arm-eabi-g++
AS := $(GNU_ARM)/bin/arm-eabi-as
LINK := $(GNU_ARM)/bin/arm-eabi-gcc
BIN := $(GNU_ARM)/bin/arm-eabi-objcopy
##############################################################################
# Typically, you should not need to change anything below this line
# basic utilities (included in Qtools for Windows), see:
# http://sourceforge.net/projects/qpc/files/Qtools
MKDIR := mkdir
RM := rm
#-----------------------------------------------------------------------------
# build options for various configurations for ARM Cortex-M4F
#
# combine all the soruces...
C_SRCS += $(QP_SRCS)
ASM_SRCS += $(QP_ASMS)
# add the pre-defined symbol for ARM architecture
DEFINES += -D__ARM_ARCH=$(ARM_ARCH)
ASM_CPU += -defsym=__ARM_ARCH=$(ARM_ARCH)
# add the pre-defined symbol __FPU_PRESENT if needed...
ifneq (,$(ARM_FPU))
DEFINES += -D__FPU_PRESENT
ASM_FPU += -defsym=__FPU_PRESENT=1
endif
ifeq (rel, $(CONF)) # Release configuration ..................................
BIN_DIR := rel
ASFLAGS = $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O1 $(INCLUDES) $(DEFINES) -DNDEBUG
CPPFLAGS = $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O1 $(INCLUDES) $(DEFINES) -DNDEBUG
else ifeq (spy, $(CONF)) # Spy configuration ................................
BIN_DIR := spy
C_SRCS += $(QS_SRCS)
ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O $(INCLUDES) $(DEFINES) -DQ_SPY
CPPFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O $(INCLUDES) $(DEFINES) -DQ_SPY
else # default Debug configuration ..........................................
BIN_DIR := dbg
ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O $(INCLUDES) $(DEFINES)
CPPFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O $(INCLUDES) $(DEFINES)
endif # ......................................................................
LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) \
-mthumb -nostdlib \
-Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS)
ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS)))
C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS)))
CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS)))
TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin
TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf
ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS))
C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS))
C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT))
CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS))
CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT))
# create $(BIN_DIR) if it does not exist
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
#-----------------------------------------------------------------------------
# rules
#
all: $(TARGET_BIN)
#all: $(TARGET_ELF)
$(TARGET_BIN): $(TARGET_ELF)
$(BIN) -O binary $< $@
$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT)
$(CC) $(CFLAGS) -c $(QPC)/include/qstamp.c -o $(BIN_DIR)/qstamp.o
$(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS)
$(BIN_DIR)/%.d : %.c
$(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@
$(BIN_DIR)/%.d : %.cpp
$(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@
$(BIN_DIR)/%.o : %.s
$(AS) $(ASFLAGS) $< -o $@
$(BIN_DIR)/%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) -c $< -o $@
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif
endif
.PHONY : clean
clean:
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
$(BIN_DIR)/*.bin \
$(BIN_DIR)/*.elf \
$(BIN_DIR)/*.map
show:
@echo PROJECT = $(PROJECT)
@echo CONF = $(CONF)
@echo DEFINES = $(DEFINES)
@echo ASM_FPU = $(ASM_FPU)
@echo ASM_SRCS = $(ASM_SRCS)
@echo C_SRCS = $(C_SRCS)
@echo CPP_SRCS = $(CPP_SRCS)
@echo ASM_OBJS_EXT = $(ASM_OBJS_EXT)
@echo C_OBJS_EXT = $(C_OBJS_EXT)
@echo C_DEPS_EXT = $(C_DEPS_EXT)
@echo CPP_DEPS_EXT = $(CPP_DEPS_EXT)
@echo TARGET_ELF = $(TARGET_ELF)

View File

@ -0,0 +1,71 @@
About this Example
==================
This example can be built from the command prompt with the provided
Makefile. The example can also be imported as a Makefile-based
project into Eclipse-based IDEs.
The Makefile
============
The provided Makefile should be easy to adapt for your own projects.
It contains three build configurations: Debug (default), Release, and
Spy.
Also, the Makefile has been specifically designed to work as an external
Makefile with the Eclipse CDT.
The various build configurations are built as follows:
make
make CONF=rel
make CONF=spy
make clean
make CONF=rel clean
make CONF=spy clean
***
NOTE:
The installation folder of the GNU-ARM toolset on YOUR machine needs
to be adjusted in the provided Makefile, by editing the symbol: GNU_ARM.
As described in the comment for this symbol, the GNU-ARM toolset is taken
from: http://gnutoolchains.com/arm-eabi
It is highly recommened to use the same GNU-ARM distribution, especially
for ARM Cortex-M4F projects, due to the support for the hardware FPU
(float-abi=hard).
***
Adjusting Stack and Heap Sizes
==============================
The stack and heap sizes are determined in this project by the GCC linker
script (.ld file), which provides a template of the recommended GCC linker
script for QP applications.
Startup Code
============
The startup code used in this project is located in the "3rd_party" folder
in the following location:
3rd_party\<board>\gcc\startup_<mcu>.c
The file startup_<mcu>.c provides a template of the recommended
startup for QP applications and should be easily customizable for other
ARM Cortex-M microcontrollers.
The startup file typically does not need to be modified or adapted for
applications. It provides only weak definitions of all exception and
interrupt handlers, as well as the assert_failed() function.
The weak function assert_failed() defined in this file might be re-defined
in the application to customize it for the application-specific error-
handling policy.
***
NOTE: The function assert_failed() typically should NOT use the stack,
because stack might be corrupted by the time this function is called.
Also, assert_failed() is intended to handle catastrophic errors and
should NOT return.
***

View File

@ -0,0 +1,135 @@
/*****************************************************************************
* Product: Linker script for STM32F407VG, GNU-ARM linker
* Last Updated for Version: 5.9.1
* Date of the Last Update: 2017-06-01
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(Reset_Handler) /* entry Point */
MEMORY { /* memory map of Tiva TM4C123GH6PM */
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
/* The size of the stack used by the application. NOTE: you need to adjust */
STACK_SIZE = 1024;
/* The size of the heap used by the application. NOTE: you need to adjust */
HEAP_SIZE = 0;
SECTIONS {
.isr_vector : { /* the vector table goes FIRST into ROM */
KEEP(*(.isr_vector)) /* vector table */
. = ALIGN(4);
} >ROM
.text : { /* code and constants */
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} >ROM
.preinit_array : {
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ROM
.init_array : {
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >ROM
.fini_array : {
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ROM
_etext = .; /* global symbols at end of code */
.stack : {
__stack_start__ = .;
. = . + STACK_SIZE;
. = ALIGN(4);
__stack_end__ = .;
} >RAM
.data : AT (_etext) {
__data_load = LOADADDR (.data);
__data_start = .;
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
__data_end__ = .;
_edata = __data_end__;
} >RAM
.bss : {
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = .;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE ( __end__ = _ebss );
.heap : {
__heap_start__ = .;
. = . + HEAP_SIZE;
. = ALIGN(4);
__heap_end__ = .;
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ : {
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}

View File

@ -0,0 +1,33 @@
::============================================================================
:: Batch file to load the DPP program to the flash of STM32 boards
::
:: NOTE: requires the ST-LINK utlity from ST, see:
:: http://www.st.com/en/embedded-software/stsw-link004.html
::
@echo off
setlocal
@echo Load the program to the flash of STM32 board
@echo usage: flash
@echo usage: flash rel
@echo usage: flash spy
::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine
::
set STLINK="C:\tools\ST\ST-LINK\ST-LINK Utility\ST-LINK_CLI.exe"
:: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg
if [%1] NEQ [] set BUILD_DIR=%1
@echo on
%STLINK% -P %BUILD_DIR%\dpp-qk.bin 0x08000000
@echo.
@echo.
@echo Reset the target to start running your program!
@echo off
endlocal

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\dpp-qk.ewp</path>
</project>
<batchBuild/>
</workspace>

View File

@ -0,0 +1,35 @@
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 1024;
define symbol __ICFEDIT_size_heap__ = 0;
/**** End of ICF editor section. ###ICF###*/
define symbol __region_RAM1_start__ = 0x10000000;
define symbol __region_RAM1_end__ = 0x1000FFFF;
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
place in RAM1_region { section .sram };

View File

@ -0,0 +1,93 @@
/*****************************************************************************
* Product: DPP example
* Last Updated for Version: 5.9.0
* Date of the Last Update: 2017-03-13
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 2005-2017 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
static QTicker l_ticker0;
QActive *the_Ticker0 = &l_ticker0;
/*..........................................................................*/
int main() {
static QEvt const *tableQueueSto[N_PHILO];
static QEvt const *philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList subscrSto[MAX_PUB_SIG];
static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO]; /* small pool */
uint8_t n;
Philo_ctor(); /* instantiate all Philosopher active objects */
Table_ctor(); /* instantiate the Table active object */
QTicker_ctor(&l_ticker0, 0U); /* ticker AO for tick rate 0 */
QF_init(); /* initialize the framework and the underlying RT kernel */
BSP_init(); /* initialize the Board Support Package */
/* object dictionaries... */
QS_OBJ_DICTIONARY(smlPoolSto);
QS_OBJ_DICTIONARY(tableQueueSto);
QS_OBJ_DICTIONARY(philoQueueSto[0]);
QS_OBJ_DICTIONARY(philoQueueSto[1]);
QS_OBJ_DICTIONARY(philoQueueSto[2]);
QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]);
/* initialize publish-subscribe... */
QF_psInit(subscrSto, Q_DIM(subscrSto));
/* initialize event pools... */
QF_poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
QACTIVE_START(the_Ticker0, 1U, 0, 0, 0, 0, 0);
/* start the active objects... */
for (n = 0U; n < N_PHILO; ++n) {
QACTIVE_START(AO_Philo[n], /* AO to start */
(uint_fast8_t)(n + 2), /* QP priority of the AO */
philoQueueSto[n], /* event queue storage */
Q_DIM(philoQueueSto[n]), /* queue length [events] */
(void *)0, /* stack storage (not used) */
0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
}
QACTIVE_START(AO_Table, /* AO to start */
(uint_fast8_t)(N_PHILO + 2), /* QP priority of the AO */
tableQueueSto, /* event queue storage */
Q_DIM(tableQueueSto), /* queue length [events] */
(void *)0, /* stack storage (not used) */
0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
return QF_run(); /* run the QF application */
}

View File

@ -0,0 +1,24 @@
About this Example
==================
This example demonstrates how to use the uVision IDE together with
the MDK-ARM toolchain.
uVision Project File
====================
The MDK-ARM uVision project file provided with this example uses
relative paths to the QP/C framework location (includes, port, and
libraries. These relative paths must be modified when the project
is moved to different relative location.
Adjusting Stack and Heap Sizes
==============================
The stack and heap sizes are determined in this project by the
command-line options for the ARM assembler (see the Asm tab in
the "Options for Target" dialog box in uVision). Specifically,
you should define symbols: Stack_Size=xxx Heap_Size=yyy, where
xxx represents a numerical value of stack size and yyy the
numberical value of the heap size (for most embedded projects
yyy should be 0, as the using the heap is not recommended).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,524 @@
/*****************************************************************************
* Product: "DPP" example on STM32F4-Discovery board, cooperative QV kernel
* Last Updated for Version: 5.9.1
* Date of the Last Update: 2017-06-01
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
#include "stm32f4xx.h" /* CMSIS-compliant header file for the MCU used */
#include "stm32f4xx_exti.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
/* add other drivers if necessary... */
Q_DEFINE_THIS_FILE
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
*/
enum KernelUnawareISRs { /* see NOTE00 */
USART2_PRIO,
/* ... */
MAX_KERNEL_UNAWARE_CMSIS_PRI /* keep always last */
};
/* "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts */
Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI);
enum KernelAwareISRs {
SYSTICK_PRIO = QF_AWARE_ISR_CMSIS_PRI, /* see NOTE00 */
/* ... */
MAX_KERNEL_AWARE_CMSIS_PRI /* keep always last */
};
/* "kernel-aware" interrupts should not overlap the PendSV priority */
Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
/* ISRs defined in this BSP ------------------------------------------------*/
void SysTick_Handler(void);
void USART2_IRQHandler(void);
/* Local-scope defines -----------------------------------------------------*/
#define LED_GPIO_PORT GPIOD
#define LED_GPIO_CLK RCC_AHB1Periph_GPIOD
#define LED4_PIN GPIO_Pin_12
#define LED3_PIN GPIO_Pin_13
#define LED5_PIN GPIO_Pin_14
#define LED6_PIN GPIO_Pin_15
#define BTN_GPIO_PORT GPIOA
#define BTN_GPIO_CLK RCC_AHB1Periph_GPIOA
#define BTN_B1 GPIO_Pin_0
static uint32_t l_rnd; /* random seed */
#ifdef Q_SPY
static QSTimeCtr QS_tickTime_;
static QSTimeCtr QS_tickPeriod_;
/* event-source identifiers used for tracing */
static uint8_t const l_SysTick;
enum AppRecords { /* application-specific trace records */
PHILO_STAT = QS_USER,
COMMAND_STAT
};
#endif
/* ISRs used in this project ===============================================*/
void SysTick_Handler(void) {
/* state of the button debouncing, see below */
static struct ButtonsDebouncing {
uint32_t depressed;
uint32_t previous;
} buttons = { 0U, 0U };
uint32_t current;
uint32_t tmp;
#ifdef Q_SPY
{
tmp = SysTick->CTRL; /* clear SysTick_CTRL_COUNTFLAG */
QS_tickTime_ += QS_tickPeriod_; /* account for the clock rollover */
}
#endif
QF_TICK_X(0U, &l_SysTick);
/* Perform the debouncing of buttons. The algorithm for debouncing
* adapted from the book "Embedded Systems Dictionary" by Jack Ganssle
* and Michael Barr, page 71.
*/
current = BTN_GPIO_PORT->IDR; /* read BTN GPIO */
tmp = buttons.depressed; /* save the debounced depressed buttons */
buttons.depressed |= (buttons.previous & current); /* set depressed */
buttons.depressed &= (buttons.previous | current); /* clear released */
buttons.previous = current; /* update the history */
tmp ^= buttons.depressed; /* changed debounced depressed */
if ((tmp & BTN_B1) != 0U) { /* debounced B1 state changed? */
if ((buttons.depressed & BTN_B1) != 0U) { /* is B1 depressed? */
static QEvt const pauseEvt = { PAUSE_SIG, 0U, 0U};
QF_PUBLISH(&pauseEvt, &l_SysTick);
}
else { /* the button is released */
static QEvt const serveEvt = { SERVE_SIG, 0U, 0U};
QF_PUBLISH(&serveEvt, &l_SysTick);
}
}
}
/*..........................................................................*/
#ifdef Q_SPY
/*
* ISR for receiving bytes from the QSPY Back-End
* NOTE: This ISR is "QF-unaware" meaning that it does not interact with
* the QF/QK and is not disabled. Such ISRs don't need to call QK_ISR_ENTRY/
* QK_ISR_EXIT and they cannot post or publish events.
*/
void USART2_IRQHandler(void) {
if ((USART2->SR & USART_SR_RXNE) != 0) {
uint32_t b = USART2->DR;
QS_RX_PUT(b);
}
}
#else
void USART2_IRQHandler(void) {}
#endif
/* BSP functions ===========================================================*/
void BSP_init(void) {
/* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* configure the FPU usage by choosing one of the options... */
#if 1
/* OPTION 1:
* Use the automatic FPU state preservation and the FPU lazy stacking.
*
* NOTE:
* Use the following setting when FPU is used in more than one task or
* in any ISRs. This setting is the safest and recommended, but requires
* extra stack space and CPU cycles.
*/
FPU->FPCCR |= (1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos);
#else
/* OPTION 2:
* Do NOT to use the automatic FPU state preservation and
* do NOT to use the FPU lazy stacking.
*
* NOTE:
* Use the following setting when FPU is used in ONE task only and not
* in any ISR. This setting is very efficient, but if more than one task
* (or ISR) start using the FPU, this can lead to corruption of the
* FPU registers. This option should be used with CAUTION.
*/
FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
#endif
GPIO_InitTypeDef GPIO_struct;
/* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* Explictily Disable the automatic FPU state preservation as well as
* the FPU lazy stacking
*/
FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
/* Initialize thr port for the LEDs */
RCC_AHB1PeriphClockCmd(LED_GPIO_CLK , ENABLE);
/* GPIO Configuration for the LEDs... */
GPIO_struct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_struct.GPIO_Pin = LED3_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED3_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED4_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED4_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED5_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED5_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED6_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */
/* Initialize thr port for Button */
RCC_AHB1PeriphClockCmd(BTN_GPIO_CLK , ENABLE);
/* GPIO Configuration for the Button... */
GPIO_struct.GPIO_Pin = BTN_B1;
GPIO_struct.GPIO_Mode = GPIO_Mode_IN;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BTN_GPIO_PORT, &GPIO_struct);
/* seed the random number generator */
BSP_randomSeed(1234U);
if (QS_INIT((void *)0) == 0U) { /* initialize the QS software tracing */
Q_ERROR();
}
QS_OBJ_DICTIONARY(&l_SysTick);
QS_USR_DICTIONARY(PHILO_STAT);
QS_USR_DICTIONARY(COMMAND_STAT);
}
/*..........................................................................*/
void BSP_displayPhilStat(uint8_t n, char const *stat) {
(void)n;
if (stat[0] == 'h') {
LED_GPIO_PORT->BSRRL = LED3_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED3_PIN; /* turn LED off */
}
if (stat[0] == 'e') {
LED_GPIO_PORT->BSRRL = LED5_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED5_PIN; /* turn LED on */
}
QS_BEGIN(PHILO_STAT, AO_Philo[n]) /* application-specific record begin */
QS_U8(1, n); /* Philosopher number */
QS_STR(stat); /* Philosopher status */
QS_END() /* application-specific record end */
}
/*..........................................................................*/
void BSP_displayPaused(uint8_t paused) {
if (paused) {
LED_GPIO_PORT->BSRRL = LED4_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED4_PIN; /* turn LED on */
}
}
/*..........................................................................*/
uint32_t BSP_random(void) { /* a very cheap pseudo-random-number generator */
uint32_t rnd;
/* exercise the FPU with some floating point computations */
/* NOTE: this code can be only called from a task that created with
* the option OS_TASK_OPT_SAVE_FP.
*/
float volatile x = 3.1415926F;
x = x + 2.7182818F;
/* "Super-Duper" Linear Congruential Generator (LCG)
* LCG(2^32, 3*7*11*13*23, 0, seed)
*/
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; /* set for the next time */
return (rnd >> 8);
}
/*..........................................................................*/
void BSP_randomSeed(uint32_t seed) {
l_rnd = seed;
}
/*..........................................................................*/
void BSP_terminate(int16_t result) {
(void)result;
}
/* QF callbacks ============================================================*/
void QF_onStartup(void) {
/* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */
SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
/* assing all priority bits for preemption-prio. and none to sub-prio. */
NVIC_SetPriorityGrouping(0U);
/* set priorities of ALL ISRs used in the system, see NOTE00
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
*/
NVIC_SetPriority(USART2_IRQn, USART2_PRIO);
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO);
/* ... */
/* enable IRQs... */
#ifdef Q_SPY
NVIC_EnableIRQ(USART2_IRQn); /* USART2 interrupt used for QS-RX */
#endif
}
/*..........................................................................*/
void QF_onCleanup(void) {
}
/*..........................................................................*/
void QV_onIdle(void) { /* CATION: called with interrupts DISABLED, NOTE01 */
LED_GPIO_PORT->BSRRL = LED6_PIN; /* turn LED on */
__NOP(); /* wait a little to actually see the LED glow */
__NOP();
__NOP();
__NOP();
LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */
#ifdef Q_SPY
QF_INT_ENABLE();
QS_rxParse(); /* parse all the received bytes */
if ((USART2->SR & USART_FLAG_TXE) != 0) { /* is TXE empty? */
uint16_t b;
QF_INT_DISABLE();
b = QS_getByte();
QF_INT_ENABLE();
if (b != QS_EOD) { /* not End-Of-Data? */
USART2->DR = (b & 0xFFU); /* put into the DR register */
}
}
#elif defined NDEBUG
/* Put the CPU and peripherals to the low-power mode.
* you might need to customize the clock management for your application,
* see the datasheet for your particular Cortex-M3 MCU.
*/
/* !!!CAUTION!!!
* The WFI instruction stops the CPU clock, which unfortunately disables
* the JTAG port, so the ST-Link debugger can no longer connect to the
* board. For that reason, the call to __WFI() has to be used with CAUTION.
*
* NOTE: If you find your board "frozen" like this, strap BOOT0 to VDD and
* reset the board, then connect with ST-Link Utilities and erase the part.
* The trick with BOOT(0) is it gets the part to run the System Loader
* instead of your broken code. When done disconnect BOOT0, and start over.
*/
//QV_CPU_SLEEP(); /* atomically go to sleep and enable interrupts */
QF_INT_ENABLE(); /* just enable interrupts */
#else
QF_INT_ENABLE(); /* just enable interrupts */
#endif
}
/*..........................................................................*/
void Q_onAssert(char const *module, int loc) {
/*
* NOTE: add here your application-specific error handling
*/
(void)module;
(void)loc;
QS_ASSERTION(module, loc, (uint32_t)10000U); /* report assertion to QS */
NVIC_SystemReset();
}
/* QS callbacks ============================================================*/
#ifdef Q_SPY
/*..........................................................................*/
uint8_t QS_onStartup(void const *arg) {
static uint8_t qsBuf[2*1024]; /* buffer for QS-TX channel */
static uint8_t qsRxBuf[100]; /* buffer for QS-RX channel */
GPIO_InitTypeDef GPIO_struct;
USART_InitTypeDef USART_struct;
(void)arg; /* avoid the "unused parameter" compiler warning */
QS_initBuf(qsBuf, sizeof(qsBuf));
QS_rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
/* enable peripheral clock for USART2 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* GPIOA Configuration: USART2 TX on PA2 and RX on PA3 */
GPIO_struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_struct.GPIO_Mode = GPIO_Mode_AF;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_struct);
/* Connect USART2 pins to AF2 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); /* TX = PA2 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); /* RX = PA3 */
USART_struct.USART_BaudRate = 115200;
USART_struct.USART_WordLength = USART_WordLength_8b;
USART_struct.USART_StopBits = USART_StopBits_1;
USART_struct.USART_Parity = USART_Parity_No;
USART_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_struct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_struct);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); /* enable RX interrupt */
USART_Cmd(USART2, ENABLE); /* enable USART2 */
QS_tickPeriod_ = SystemCoreClock / BSP_TICKS_PER_SEC;
QS_tickTime_ = QS_tickPeriod_; /* to start the timestamp at zero */
/* setup the QS filters... */
QS_FILTER_ON(QS_SM_RECORDS); /* state machine records */
QS_FILTER_ON(QS_AO_RECORDS); /* active object records */
QS_FILTER_ON(QS_UA_RECORDS); /* all user records */
return (uint8_t)1; /* return success */
}
/*..........................................................................*/
void QS_onCleanup(void) {
}
/*..........................................................................*/
QSTimeCtr QS_onGetTime(void) { /* NOTE: invoked with interrupts DISABLED */
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) { /* not set? */
return QS_tickTime_ - (QSTimeCtr)SysTick->VAL;
}
else { /* the rollover occured, but the SysTick_ISR did not run yet */
return QS_tickTime_ + QS_tickPeriod_ - (QSTimeCtr)SysTick->VAL;
}
}
/*..........................................................................*/
void QS_onFlush(void) {
uint16_t b;
QF_INT_DISABLE();
while ((b = QS_getByte()) != QS_EOD) { /* while not End-Of-Data... */
QF_INT_ENABLE();
while ((USART2->SR & USART_FLAG_TXE) == 0) { /* while TXE not empty */
}
USART2->DR = (b & 0xFFU); /* put into the DR register */
QF_INT_DISABLE();
}
QF_INT_ENABLE();
}
/*..........................................................................*/
void QS_onReset(void) {
NVIC_SystemReset();
}
/*..........................................................................*/
void QS_onCommand(uint8_t cmdId,
uint32_t param1, uint32_t param2, uint32_t param3)
{
void assert_failed(char const *module, int loc);
(void)cmdId;
(void)param1;
(void)param2;
(void)param3;
QS_BEGIN(COMMAND_STAT, (void *)1) /* application-specific record begin */
QS_U8(2, cmdId);
QS_U32(8, param1);
QS_U32(8, param2);
QS_U32(8, param3);
QS_END()
if (cmdId == 10U) {
Q_ERROR();
}
else if (cmdId == 11U) {
assert_failed("QS_onCommand", 123);
}
}
#endif /* Q_SPY */
/*--------------------------------------------------------------------------*/
/*****************************************************************************
* NOTE00:
* The QF_AWARE_ISR_CMSIS_PRI constant from the QF port specifies the highest
* ISR priority that is disabled by the QF framework. The value is suitable
* for the NVIC_SetPriority() CMSIS function.
*
* Only ISRs prioritized at or below the QF_AWARE_ISR_CMSIS_PRI level (i.e.,
* with the numerical values of priorities equal or higher than
* QF_AWARE_ISR_CMSIS_PRI) are allowed to call any QF services. These ISRs
* are "QF-aware".
*
* Conversely, any ISRs prioritized above the QF_AWARE_ISR_CMSIS_PRI priority
* level (i.e., with the numerical values of priorities less than
* QF_AWARE_ISR_CMSIS_PRI) are never disabled and are not aware of the kernel.
* Such "QF-unaware" ISRs cannot call any QF services. The only mechanism
* by which a "QF-unaware" ISR can communicate with the QF framework is by
* triggering a "QF-aware" ISR, which can post/publish events.
*
* NOTE01:
* The QK_onIdle() callback is called with interrupts enabled.
*
* NOTE02:
* One of the LEDs is used to visualize the idle loop activity. The brightness
* of the LED is proportional to the frequency of invcations of the idle loop.
* Please note that the LED is toggled with interrupts locked, so no interrupt
* execution time contributes to the brightness of the User LED.
*/

View File

@ -0,0 +1,327 @@
##############################################################################
# Product: DPP on STM32F4-Discovery, QV, GNU-ARM gnutoolchains.com/arm-eabi
# Last Updated for Version: 5.9.1
# Date of the Last Update: 2017-06-01
#
# Q u a n t u m L e a P s
# ---------------------------
# innovating embedded systems
#
# Copyright (C) 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 3 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:
# https://state-machine.com
# mailto:info@state-machine.com
##############################################################################
# examples of invoking this Makefile:
# building configurations: Debug (default), Release, and Spy
# make
# make CONF=rel
# make CONF=spy
#
# cleaning configurations: Debug (default), Release, and Spy
# make clean
# make CONF=rel clean
# make CONF=spy clean
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
# is included in the Qtools collection for Windows, see:
# http://sourceforge.net/projects/qpc/files/Qtools/
#
#-----------------------------------------------------------------------------
# project name
#
PROJECT := dpp-qv
#-----------------------------------------------------------------------------
# project directories
#
# location of the QP/C framework (if not provided in an environemnt var.)
ifeq ($(QPC),)
QPC := ../../../../..
endif
# QP port used in this project
QP_PORT_DIR := $(QPC)/ports/arm-cm/qv/gnu
# list of all source directories used by this project
VPATH = \
.. \
../.. \
$(QPC)/src/qf \
$(QPC)/src/qv \
$(QPC)/src/qs \
$(QP_PORT_DIR) \
$(QPC)/3rd_party/stm32f4-discovery \
$(QPC)/3rd_party/stm32f4-discovery/src \
$(QPC)/3rd_party/stm32f4-discovery/gnu
# list of all include directories needed by this project
INCLUDES = \
-I../.. \
-I$(QPC)/include \
-I$(QPC)/src \
-I$(QP_PORT_DIR) \
-I$(QPC)/3rd_party/CMSIS/Include \
-I$(QPC)/3rd_party/stm32f4-discovery \
-I$(QPC)/3rd_party/stm32f4-discovery/inc
#-----------------------------------------------------------------------------
# files
#
# assembler source files
ASM_SRCS :=
# C source files
C_SRCS := \
bsp.c \
main.c \
philo.c \
table.c \
system_stm32f4xx.c \
startup_stm32f4xx.c \
stm32f4xx_gpio.c \
stm32f4xx_rcc.c \
stm32f4xx_usart.c
# C++ source files
CPP_SRCS :=
OUTPUT := $(PROJECT)
LD_SCRIPT := $(PROJECT).ld
QP_SRCS := \
qep_hsm.c \
qep_msm.c \
qf_act.c \
qf_actq.c \
qf_defer.c \
qf_dyn.c \
qf_mem.c \
qf_ps.c \
qf_qact.c \
qf_qeq.c \
qf_qmact.c \
qf_time.c \
qv.c \
qv_port.c
QP_ASMS :=
QS_SRCS := \
qs.c \
qs_rx.c \
qs_fp.c
LIB_DIRS :=
LIBS :=
# defines
DEFINES :=
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
# ARM_ARCH: [6 | 7] (NOTE: must match ARM_CPU!)
# ARM_FPU: [ | vfp]
# FLOAT_ABI: [ | soft | softfp | hard]
#
ARM_CPU := -mcpu=cortex-m4
ARM_ARCH := 7 # NOTE: must match the ARM_CPU!
ARM_FPU := -mfpu=vfp
FLOAT_ABI := -mfloat-abi=softfp
#-----------------------------------------------------------------------------
# GNU-ARM toolset (NOTE: You need to adjust to your machine)
# see http://gnutoolchains.com/arm-eabi/
#
ifeq ($(GNU_ARM),)
GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif
# make sure that the GNU-ARM toolset exists...
ifeq ("$(wildcard $(GNU_ARM))","")
$(error GNU_ARM toolset not found. Please adjust the Makefile)
endif
CC := $(GNU_ARM)/bin/arm-eabi-gcc
CPP := $(GNU_ARM)/bin/arm-eabi-g++
AS := $(GNU_ARM)/bin/arm-eabi-as
LINK := $(GNU_ARM)/bin/arm-eabi-gcc
BIN := $(GNU_ARM)/bin/arm-eabi-objcopy
##############################################################################
# Typically, you should not need to change anything below this line
# basic utilities (included in Qtools for Windows), see:
# http://sourceforge.net/projects/qpc/files/Qtools
MKDIR := mkdir
RM := rm
#-----------------------------------------------------------------------------
# build options for various configurations for ARM Cortex-M4F
#
# combine all the soruces...
C_SRCS += $(QP_SRCS)
ASM_SRCS += $(QP_ASMS)
# add the pre-defined symbol for ARM architecture
DEFINES += -D__ARM_ARCH=$(ARM_ARCH)
ASM_CPU += -defsym=__ARM_ARCH=$(ARM_ARCH)
# add the pre-defined symbol __FPU_PRESENT if needed...
ifneq (,$(ARM_FPU))
DEFINES += -D__FPU_PRESENT
ASM_FPU += -defsym=__FPU_PRESENT=1
endif
ifeq (rel, $(CONF)) # Release configuration ..................................
BIN_DIR := rel
ASFLAGS = $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O1 $(INCLUDES) $(DEFINES) -DNDEBUG
CPPFLAGS = $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O1 $(INCLUDES) $(DEFINES) -DNDEBUG
else ifeq (spy, $(CONF)) # Spy configuration ................................
BIN_DIR := spy
C_SRCS += $(QS_SRCS)
ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O $(INCLUDES) $(DEFINES) -DQ_SPY
CPPFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O $(INCLUDES) $(DEFINES) -DQ_SPY
else # default Debug configuration ..........................................
BIN_DIR := dbg
ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O $(INCLUDES) $(DEFINES)
CPPFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O $(INCLUDES) $(DEFINES)
endif # ......................................................................
LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) \
-mthumb -nostdlib \
-Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS)
ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS)))
C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS)))
CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS)))
TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin
TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf
ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS))
C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS))
C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT))
CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS))
CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT))
# create $(BIN_DIR) if it does not exist
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
#-----------------------------------------------------------------------------
# rules
#
all: $(TARGET_BIN)
#all: $(TARGET_ELF)
$(TARGET_BIN): $(TARGET_ELF)
$(BIN) -O binary $< $@
$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT)
$(CC) $(CFLAGS) -c $(QPC)/include/qstamp.c -o $(BIN_DIR)/qstamp.o
$(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS)
$(BIN_DIR)/%.d : %.c
$(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@
$(BIN_DIR)/%.d : %.cpp
$(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@
$(BIN_DIR)/%.o : %.s
$(AS) $(ASFLAGS) $< -o $@
$(BIN_DIR)/%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) -c $< -o $@
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif
endif
.PHONY : clean
clean:
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
$(BIN_DIR)/*.bin \
$(BIN_DIR)/*.elf \
$(BIN_DIR)/*.map
show:
@echo PROJECT = $(PROJECT)
@echo CONF = $(CONF)
@echo DEFINES = $(DEFINES)
@echo ASM_FPU = $(ASM_FPU)
@echo ASM_SRCS = $(ASM_SRCS)
@echo C_SRCS = $(C_SRCS)
@echo CPP_SRCS = $(CPP_SRCS)
@echo ASM_OBJS_EXT = $(ASM_OBJS_EXT)
@echo C_OBJS_EXT = $(C_OBJS_EXT)
@echo C_DEPS_EXT = $(C_DEPS_EXT)
@echo CPP_DEPS_EXT = $(CPP_DEPS_EXT)
@echo TARGET_ELF = $(TARGET_ELF)

View File

@ -0,0 +1,71 @@
About this Example
==================
This example can be built from the command prompt with the provided
Makefile. The example can also be imported as a Makefile-based
project into Eclipse-based IDEs.
The Makefile
============
The provided Makefile should be easy to adapt for your own projects.
It contains three build configurations: Debug (default), Release, and
Spy.
Also, the Makefile has been specifically designed to work as an external
Makefile with the Eclipse CDT.
The various build configurations are built as follows:
make
make CONF=rel
make CONF=spy
make clean
make CONF=rel clean
make CONF=spy clean
***
NOTE:
The installation folder of the GNU-ARM toolset on YOUR machine needs
to be adjusted in the provided Makefile, by editing the symbol: GNU_ARM.
As described in the comment for this symbol, the GNU-ARM toolset is taken
from: http://gnutoolchains.com/arm-eabi
It is highly recommened to use the same GNU-ARM distribution, especially
for ARM Cortex-M4F projects, due to the support for the hardware FPU
(float-abi=hard).
***
Adjusting Stack and Heap Sizes
==============================
The stack and heap sizes are determined in this project by the GCC linker
script (.ld file), which provides a template of the recommended GCC linker
script for QP applications.
Startup Code
============
The startup code used in this project is located in the "3rd_party" folder
in the following location:
3rd_party\<board>\gcc\startup_<mcu>.c
The file startup_<mcu>.c provides a template of the recommended
startup for QP applications and should be easily customizable for other
ARM Cortex-M microcontrollers.
The startup file typically does not need to be modified or adapted for
applications. It provides only weak definitions of all exception and
interrupt handlers, as well as the assert_failed() function.
The weak function assert_failed() defined in this file might be re-defined
in the application to customize it for the application-specific error-
handling policy.
***
NOTE: The function assert_failed() typically should NOT use the stack,
because stack might be corrupted by the time this function is called.
Also, assert_failed() is intended to handle catastrophic errors and
should NOT return.
***

View File

@ -0,0 +1,135 @@
/*****************************************************************************
* Product: Linker script for STM32F407VG, GNU-ARM linker
* Last Updated for Version: 5.9.1
* Date of the Last Update: 2017-06-01
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(Reset_Handler) /* entry Point */
MEMORY { /* memory map of Tiva TM4C123GH6PM */
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
/* The size of the stack used by the application. NOTE: you need to adjust */
STACK_SIZE = 1024;
/* The size of the heap used by the application. NOTE: you need to adjust */
HEAP_SIZE = 0;
SECTIONS {
.isr_vector : { /* the vector table goes FIRST into ROM */
KEEP(*(.isr_vector)) /* vector table */
. = ALIGN(4);
} >ROM
.text : { /* code and constants */
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} >ROM
.preinit_array : {
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ROM
.init_array : {
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >ROM
.fini_array : {
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ROM
_etext = .; /* global symbols at end of code */
.stack : {
__stack_start__ = .;
. = . + STACK_SIZE;
. = ALIGN(4);
__stack_end__ = .;
} >RAM
.data : AT (_etext) {
__data_load = LOADADDR (.data);
__data_start = .;
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
__data_end__ = .;
_edata = __data_end__;
} >RAM
.bss : {
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = .;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE ( __end__ = _ebss );
.heap : {
__heap_start__ = .;
. = . + HEAP_SIZE;
. = ALIGN(4);
__heap_end__ = .;
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ : {
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}

View File

@ -0,0 +1,33 @@
::============================================================================
:: Batch file to load the DPP program to the flash of STM32 boards
::
:: NOTE: requires the ST-LINK utlity from ST, see:
:: http://www.st.com/en/embedded-software/stsw-link004.html
::
@echo off
setlocal
@echo Load the program to the flash of STM32 board
@echo usage: flash
@echo usage: flash rel
@echo usage: flash spy
::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine
::
set STLINK="C:\tools\ST\ST-LINK\ST-LINK Utility\ST-LINK_CLI.exe"
:: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg
if [%1] NEQ [] set BUILD_DIR=%1
@echo on
%STLINK% -P %BUILD_DIR%\dpp-qv.bin 0x08000000
@echo.
@echo.
@echo Reset the target to start running your program!
@echo off
endlocal

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\dpp-qv.ewp</path>
</project>
<batchBuild/>
</workspace>

View File

@ -0,0 +1,35 @@
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 1024;
define symbol __ICFEDIT_size_heap__ = 0;
/**** End of ICF editor section. ###ICF###*/
define symbol __region_RAM1_start__ = 0x10000000;
define symbol __region_RAM1_end__ = 0x1000FFFF;
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
place in RAM1_region { section .sram };

View File

@ -0,0 +1,93 @@
/*****************************************************************************
* Product: DPP example
* Last Updated for Version: 5.9.0
* Date of the Last Update: 2017-03-13
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 2005-2017 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
static QTicker l_ticker0;
QActive *the_Ticker0 = &l_ticker0;
/*..........................................................................*/
int main() {
static QEvt const *tableQueueSto[N_PHILO];
static QEvt const *philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList subscrSto[MAX_PUB_SIG];
static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO]; /* small pool */
uint8_t n;
Philo_ctor(); /* instantiate all Philosopher active objects */
Table_ctor(); /* instantiate the Table active object */
QTicker_ctor(&l_ticker0, 0U); /* ticker AO for tick rate 0 */
QF_init(); /* initialize the framework and the underlying RT kernel */
BSP_init(); /* initialize the Board Support Package */
/* object dictionaries... */
QS_OBJ_DICTIONARY(smlPoolSto);
QS_OBJ_DICTIONARY(tableQueueSto);
QS_OBJ_DICTIONARY(philoQueueSto[0]);
QS_OBJ_DICTIONARY(philoQueueSto[1]);
QS_OBJ_DICTIONARY(philoQueueSto[2]);
QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]);
/* initialize publish-subscribe... */
QF_psInit(subscrSto, Q_DIM(subscrSto));
/* initialize event pools... */
QF_poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
QACTIVE_START(the_Ticker0, 1U, 0, 0, 0, 0, 0);
/* start the active objects... */
for (n = 0U; n < N_PHILO; ++n) {
QACTIVE_START(AO_Philo[n], /* AO to start */
(uint_fast8_t)(n + 2), /* QP priority of the AO */
philoQueueSto[n], /* event queue storage */
Q_DIM(philoQueueSto[n]), /* queue length [events] */
(void *)0, /* stack storage (not used) */
0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
}
QACTIVE_START(AO_Table, /* AO to start */
(uint_fast8_t)(N_PHILO + 2), /* QP priority of the AO */
tableQueueSto, /* event queue storage */
Q_DIM(tableQueueSto), /* queue length [events] */
(void *)0, /* stack storage (not used) */
0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
return QF_run(); /* run the QF application */
}

View File

@ -0,0 +1,24 @@
About this Example
==================
This example demonstrates how to use the uVision IDE together with
the MDK-ARM toolchain.
uVision Project File
====================
The MDK-ARM uVision project file provided with this example uses
relative paths to the QP/C framework location (includes, port, and
libraries. These relative paths must be modified when the project
is moved to different relative location.
Adjusting Stack and Heap Sizes
==============================
The stack and heap sizes are determined in this project by the
command-line options for the ARM assembler (see the Asm tab in
the "Options for Target" dialog box in uVision). Specifically,
you should define symbols: Stack_Size=xxx Heap_Size=yyy, where
xxx represents a numerical value of stack size and yyy the
numberical value of the heap size (for most embedded projects
yyy should be 0, as the using the heap is not recommended).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,532 @@
/*****************************************************************************
* Product: "DPP" example on STM32F4-Discovery board, preemptive QK kernel
* Last Updated for Version: 5.9.1
* Date of the Last Update: 2017-06-01
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
#include "stm32f4xx.h" /* CMSIS-compliant header file for the MCU used */
#include "stm32f4xx_exti.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
/* add other drivers if necessary... */
Q_DEFINE_THIS_FILE
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
*/
enum KernelUnawareISRs { /* see NOTE00 */
USART2_PRIO,
/* ... */
MAX_KERNEL_UNAWARE_CMSIS_PRI /* keep always last */
};
/* "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts */
Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI);
enum KernelAwareISRs {
SYSTICK_PRIO = QF_AWARE_ISR_CMSIS_PRI, /* see NOTE00 */
/* ... */
MAX_KERNEL_AWARE_CMSIS_PRI /* keep always last */
};
/* "kernel-aware" interrupts should not overlap the PendSV priority */
Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS)));
/* ISRs defined in this BSP ------------------------------------------------*/
void SysTick_Handler(void);
void USART2_IRQHandler(void);
/* Local-scope defines -----------------------------------------------------*/
#define LED_GPIO_PORT GPIOD
#define LED_GPIO_CLK RCC_AHB1Periph_GPIOD
#define LED4_PIN GPIO_Pin_12
#define LED3_PIN GPIO_Pin_13
#define LED5_PIN GPIO_Pin_14
#define LED6_PIN GPIO_Pin_15
#define BTN_GPIO_PORT GPIOA
#define BTN_GPIO_CLK RCC_AHB1Periph_GPIOA
#define BTN_B1 GPIO_Pin_0
static unsigned l_rnd; /* random seed */
static QXMutex l_rndMutex; /* mutex to protect the random seed */
#ifdef Q_SPY
static QSTimeCtr QS_tickTime_;
static QSTimeCtr QS_tickPeriod_;
/* event-source identifiers used for tracing */
static uint8_t const l_SysTick;
enum AppRecords { /* application-specific trace records */
PHILO_STAT = QS_USER,
COMMAND_STAT
};
#endif
/* ISRs used in this project ===============================================*/
void SysTick_Handler(void) {
/* state of the button debouncing, see below */
static struct ButtonsDebouncing {
uint32_t depressed;
uint32_t previous;
} buttons = { 0U, 0U };
uint32_t current;
uint32_t tmp;
QXK_ISR_ENTRY(); /* inform QXK about entering an ISR */
#ifdef Q_SPY
{
tmp = SysTick->CTRL; /* clear SysTick_CTRL_COUNTFLAG */
QS_tickTime_ += QS_tickPeriod_; /* account for the clock rollover */
}
#endif
QF_TICK_X(0U, &l_SysTick); /* process time events for rate 0 */
/* Perform the debouncing of buttons. The algorithm for debouncing
* adapted from the book "Embedded Systems Dictionary" by Jack Ganssle
* and Michael Barr, page 71.
*/
current = BTN_GPIO_PORT->IDR; /* read BTN GPIO */
tmp = buttons.depressed; /* save the debounced depressed buttons */
buttons.depressed |= (buttons.previous & current); /* set depressed */
buttons.depressed &= (buttons.previous | current); /* clear released */
buttons.previous = current; /* update the history */
tmp ^= buttons.depressed; /* changed debounced depressed */
if ((tmp & BTN_B1) != 0U) { /* debounced B1 state changed? */
if ((buttons.depressed & BTN_B1) != 0U) { /* is B1 depressed? */
static QEvt const pauseEvt = { PAUSE_SIG, 0U, 0U};
QF_PUBLISH(&pauseEvt, &l_SysTick);
}
else { /* the button is released */
static QEvt const serveEvt = { SERVE_SIG, 0U, 0U};
QF_PUBLISH(&serveEvt, &l_SysTick);
}
}
QXK_ISR_EXIT(); /* inform QXK about exiting an ISR */
}
/*..........................................................................*/
#ifdef Q_SPY
/*
* ISR for receiving bytes from the QSPY Back-End
* NOTE: This ISR is "QF-unaware" meaning that it does not interact with
* the QF/QXK and is not disabled. Such ISRs don't need to call QXK_ISR_ENTRY/
* QXK_ISR_EXIT and they cannot post or publish events.
*/
void USART2_IRQHandler(void) {
if ((USART2->SR & USART_SR_RXNE) != 0) {
uint32_t b = USART2->DR;
QS_RX_PUT(b);
}
}
#else
void USART2_IRQHandler(void) {}
#endif
/* BSP functions ===========================================================*/
void BSP_init(void) {
/* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* configure the FPU usage by choosing one of the options... */
#if 1
/* OPTION 1:
* Use the automatic FPU state preservation and the FPU lazy stacking.
*
* NOTE:
* Use the following setting when FPU is used in more than one task or
* in any ISRs. This setting is the safest and recommended, but requires
* extra stack space and CPU cycles.
*/
FPU->FPCCR |= (1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos);
#else
/* OPTION 2:
* Do NOT to use the automatic FPU state preservation and
* do NOT to use the FPU lazy stacking.
*
* NOTE:
* Use the following setting when FPU is used in ONE task only and not
* in any ISR. This setting is very efficient, but if more than one task
* (or ISR) start using the FPU, this can lead to corruption of the
* FPU registers. This option should be used with CAUTION.
*/
FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
#endif
GPIO_InitTypeDef GPIO_struct;
/* NOTE: SystemInit() already called from the startup code
* but SystemCoreClock needs to be updated
*/
SystemCoreClockUpdate();
/* Explictily Disable the automatic FPU state preservation as well as
* the FPU lazy stacking
*/
FPU->FPCCR &= ~((1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos));
/* Initialize thr port for the LEDs */
RCC_AHB1PeriphClockCmd(LED_GPIO_CLK , ENABLE);
/* GPIO Configuration for the LEDs... */
GPIO_struct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_struct.GPIO_Pin = LED3_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED3_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED4_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED4_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED5_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED5_PIN; /* turn LED off */
GPIO_struct.GPIO_Pin = LED6_PIN;
GPIO_Init(LED_GPIO_PORT, &GPIO_struct);
LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */
/* Initialize thr port for Button */
RCC_AHB1PeriphClockCmd(BTN_GPIO_CLK , ENABLE);
/* GPIO Configuration for the Button... */
GPIO_struct.GPIO_Pin = BTN_B1;
GPIO_struct.GPIO_Mode = GPIO_Mode_IN;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BTN_GPIO_PORT, &GPIO_struct);
/* seed the random number generator */
BSP_randomSeed(1234U);
if (QS_INIT((void *)0) == 0U) { /* initialize the QS software tracing */
Q_ERROR();
}
QS_OBJ_DICTIONARY(&l_SysTick);
QS_USR_DICTIONARY(PHILO_STAT);
QS_USR_DICTIONARY(COMMAND_STAT);
}
/*..........................................................................*/
void BSP_displayPhilStat(uint8_t n, char const *stat) {
(void)n;
if (stat[0] == 'h') {
LED_GPIO_PORT->BSRRL = LED3_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED3_PIN; /* turn LED off */
}
if (stat[0] == 'e') {
LED_GPIO_PORT->BSRRL = LED5_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED5_PIN; /* turn LED on */
}
QS_BEGIN(PHILO_STAT, AO_Philo[n]) /* application-specific record begin */
QS_U8(1, n); /* Philosopher number */
QS_STR(stat); /* Philosopher status */
QS_END() /* application-specific record end */
}
/*..........................................................................*/
void BSP_displayPaused(uint8_t paused) {
if (paused) {
LED_GPIO_PORT->BSRRL = LED4_PIN; /* turn LED on */
}
else {
LED_GPIO_PORT->BSRRH = LED4_PIN; /* turn LED on */
}
}
/*..........................................................................*/
uint32_t BSP_random(void) { /* a very cheap pseudo-random-number generator */
uint32_t rnd;
/* Some flating point code is to exercise the VFP... */
float volatile x = 3.1415926F;
x = x + 2.7182818F;
QXMutex_lock(&l_rndMutex); /* lock the random-seed mutex */
/* "Super-Duper" Linear Congruential Generator (LCG)
* LCG(2^32, 3*7*11*13*23, 0, seed)
*/
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; /* set for the next time */
QXMutex_unlock(&l_rndMutex); /* unlock the random-seed mutex */
return (rnd >> 8);
}
/*..........................................................................*/
void BSP_randomSeed(uint32_t seed) {
l_rnd = seed;
QXMutex_init(&l_rndMutex, N_PHILO); /* ceiling == max Philo priority */
}
/*..........................................................................*/
void BSP_terminate(int16_t result) {
(void)result;
}
/* QF callbacks ============================================================*/
void QF_onStartup(void) {
/* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */
SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);
/* assing all priority bits for preemption-prio. and none to sub-prio. */
NVIC_SetPriorityGrouping(0U);
/* set priorities of ALL ISRs used in the system, see NOTE00
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority().
* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!
*/
NVIC_SetPriority(USART2_IRQn, USART2_PRIO);
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO);
/* ... */
/* enable IRQs... */
#ifdef Q_SPY
NVIC_EnableIRQ(USART2_IRQn); /* USART2 interrupt used for QS-RX */
#endif
}
/*..........................................................................*/
void QF_onCleanup(void) {
}
/*..........................................................................*/
void QXK_onIdle(void) {
QF_INT_DISABLE();
LED_GPIO_PORT->BSRRL = LED6_PIN; /* turn LED on */
__NOP(); /* wait a little to actually see the LED glow */
__NOP();
__NOP();
__NOP();
LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */
QF_INT_ENABLE();
#ifdef Q_SPY
QS_rxParse(); /* parse all the received bytes */
if ((USART2->SR & USART_FLAG_TXE) != 0) { /* TXE empty? */
uint16_t b;
QF_INT_DISABLE();
b = QS_getByte();
QF_INT_ENABLE();
if (b != QS_EOD) { /* not End-Of-Data? */
USART2->DR = (b & 0xFFU); /* put into the DR register */
}
}
#elif defined NDEBUG
/* Put the CPU and peripherals to the low-power mode.
* you might need to customize the clock management for your application,
* see the datasheet for your particular Cortex-M MCU.
*/
/* !!!CAUTION!!!
* The WFI instruction stops the CPU clock, which unfortunately disables
* the JTAG port, so the ST-Link debugger can no longer connect to the
* board. For that reason, the call to __WFI() has to be used with CAUTION.
*
* NOTE: If you find your board "frozen" like this, strap BOOT0 to VDD and
* reset the board, then connect with ST-Link Utilities and erase the part.
* The trick with BOOT(0) is it gets the part to run the System Loader
* instead of your broken code. When done disconnect BOOT0, and start over.
*/
//__WFI(); /* Wait-For-Interrupt */
#endif
}
/*..........................................................................*/
void Q_onAssert(char const *module, int loc) {
/*
* NOTE: add here your application-specific error handling
*/
(void)module;
(void)loc;
QS_ASSERTION(module, loc, (uint32_t)10000U); /* report assertion to QS */
NVIC_SystemReset();
}
/* QS callbacks ============================================================*/
#ifdef Q_SPY
/*..........................................................................*/
uint8_t QS_onStartup(void const *arg) {
static uint8_t qsBuf[2*1024]; /* buffer for QS-TX channel */
static uint8_t qsRxBuf[100]; /* buffer for QS-RX channel */
GPIO_InitTypeDef GPIO_struct;
USART_InitTypeDef USART_struct;
(void)arg; /* avoid the "unused parameter" compiler warning */
QS_initBuf(qsBuf, sizeof(qsBuf));
QS_rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
/* enable peripheral clock for USART2 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* GPIOA Configuration: USART2 TX on PA2 and RX on PA3 */
GPIO_struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_struct.GPIO_Mode = GPIO_Mode_AF;
GPIO_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_struct.GPIO_OType = GPIO_OType_PP;
GPIO_struct.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_struct);
/* Connect USART2 pins to AF2 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); /* TX = PA2 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); /* RX = PA3 */
USART_struct.USART_BaudRate = 115200;
USART_struct.USART_WordLength = USART_WordLength_8b;
USART_struct.USART_StopBits = USART_StopBits_1;
USART_struct.USART_Parity = USART_Parity_No;
USART_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_struct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_struct);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); /* enable RX interrupt */
USART_Cmd(USART2, ENABLE); /* enable USART2 */
QS_tickPeriod_ = SystemCoreClock / BSP_TICKS_PER_SEC;
QS_tickTime_ = QS_tickPeriod_; /* to start the timestamp at zero */
/* setup the QS filters... */
QS_FILTER_ON(QS_SM_RECORDS); /* state machine records */
QS_FILTER_ON(QS_AO_RECORDS); /* active object records */
QS_FILTER_ON(QS_UA_RECORDS); /* all user records */
return (uint8_t)1; /* return success */
}
/*..........................................................................*/
void QS_onCleanup(void) {
}
/*..........................................................................*/
QSTimeCtr QS_onGetTime(void) { /* NOTE: invoked with interrupts DISABLED */
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) { /* not set? */
return QS_tickTime_ - (QSTimeCtr)SysTick->VAL;
}
else { /* the rollover occured, but the SysTick_ISR did not run yet */
return QS_tickTime_ + QS_tickPeriod_ - (QSTimeCtr)SysTick->VAL;
}
}
/*..........................................................................*/
void QS_onFlush(void) {
uint16_t b;
QF_INT_DISABLE();
while ((b = QS_getByte()) != QS_EOD) { /* while not End-Of-Data... */
QF_INT_ENABLE();
while ((USART2->SR & USART_FLAG_TXE) == 0) { /* while TXE not empty */
}
USART2->DR = (b & 0xFF); /* put into the DR register */
QF_INT_DISABLE();
}
QF_INT_ENABLE();
}
/*..........................................................................*/
void QS_onReset(void) {
NVIC_SystemReset();
}
/*..........................................................................*/
void QS_onCommand(uint8_t cmdId,
uint32_t param1, uint32_t param2, uint32_t param3)
{
void assert_failed(char const *module, int loc);
(void)cmdId;
(void)param1;
(void)param2;
(void)param3;
QS_BEGIN(COMMAND_STAT, (void *)1) /* application-specific record begin */
QS_U8(2, cmdId);
QS_U32(8, param1);
QS_U32(8, param2);
QS_U32(8, param3);
QS_END()
if (cmdId == 10U) {
Q_ERROR();
}
else if (cmdId == 11U) {
assert_failed("QS_onCommand", 123);
}
}
#endif /* Q_SPY */
/*--------------------------------------------------------------------------*/
/*****************************************************************************
* NOTE00:
* The QF_AWARE_ISR_CMSIS_PRI constant from the QF port specifies the highest
* ISR priority that is disabled by the QF framework. The value is suitable
* for the NVIC_SetPriority() CMSIS function.
*
* Only ISRs prioritized at or below the QF_AWARE_ISR_CMSIS_PRI level (i.e.,
* with the numerical values of priorities equal or higher than
* QF_AWARE_ISR_CMSIS_PRI) are allowed to call any QF services. These ISRs
* are "QF-aware".
*
* Conversely, any ISRs prioritized above the QF_AWARE_ISR_CMSIS_PRI priority
* level (i.e., with the numerical values of priorities less than
* QF_AWARE_ISR_CMSIS_PRI) are never disabled and are not aware of the kernel.
* Such "QF-unaware" ISRs cannot call any QF services. The only mechanism
* by which a "QF-unaware" ISR can communicate with the QF framework is by
* triggering a "QF-aware" ISR, which can post/publish events.
*
* NOTE01:
* The QV_onIdle() callback is called with interrupts disabled, because the
* determination of the idle condition might change by any interrupt posting
* an event. QV_onIdle() must internally enable interrupts, ideally
* atomically with putting the CPU to the power-saving mode.
*
* NOTE02:
* One of the LEDs is used to visualize the idle loop activity. The brightness
* of the LED is proportional to the frequency of invcations of the idle loop.
* Please note that the LED is toggled with interrupts locked, so no interrupt
* execution time contributes to the brightness of the User LED.
*/

View File

@ -0,0 +1,331 @@
##############################################################################
# Product: DPP on STM32F4-Discovery, QXK, GNU-ARM gnutoolchains.com/arm-eabi
# Last Updated for Version: 5.9.1
# Date of the Last Update: 2017-06-01
#
# Q u a n t u m L e a P s
# ---------------------------
# innovating embedded systems
#
# Copyright (C) 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 3 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:
# https://state-machine.com
# mailto:info@state-machine.com
##############################################################################
# examples of invoking this Makefile:
# building configurations: Debug (default), Release, and Spy
# make
# make CONF=rel
# make CONF=spy
#
# cleaning configurations: Debug (default), Release, and Spy
# make clean
# make CONF=rel clean
# make CONF=spy clean
#
# NOTE:
# To use this Makefile on Windows, you will need the GNU make utility, which
# is included in the Qtools collection for Windows, see:
# http://sourceforge.net/projects/qpc/files/Qtools/
#
#-----------------------------------------------------------------------------
# project name
#
PROJECT := dpp-qxk
#-----------------------------------------------------------------------------
# project directories
#
# location of the QP/C framework (if not provided in an environemnt var.)
ifeq ($(QPC),)
QPC := ../../../../..
endif
# QP port used in this project
QP_PORT_DIR := $(QPC)/ports/arm-cm/qxk/gnu
# list of all source directories used by this project
VPATH = \
.. \
../.. \
$(QPC)/src/qf \
$(QPC)/src/qxk \
$(QPC)/src/qs \
$(QP_PORT_DIR) \
$(QPC)/3rd_party/stm32f4-discovery \
$(QPC)/3rd_party/stm32f4-discovery/src \
$(QPC)/3rd_party/stm32f4-discovery/gnu
# list of all include directories needed by this project
INCLUDES = \
-I../.. \
-I$(QPC)/include \
-I$(QPC)/src \
-I$(QP_PORT_DIR) \
-I$(QPC)/3rd_party/CMSIS/Include \
-I$(QPC)/3rd_party/stm32f4-discovery \
-I$(QPC)/3rd_party/stm32f4-discovery/inc
#-----------------------------------------------------------------------------
# files
#
# assembler source files
ASM_SRCS :=
# C source files
C_SRCS := \
bsp.c \
main.c \
philo.c \
table.c \
test.c \
system_stm32f4xx.c \
startup_stm32f4xx.c \
stm32f4xx_gpio.c \
stm32f4xx_rcc.c \
stm32f4xx_usart.c
# C++ source files
CPP_SRCS :=
OUTPUT := $(PROJECT)
LD_SCRIPT := $(PROJECT).ld
QP_SRCS := \
qep_hsm.c \
qep_msm.c \
qf_act.c \
qf_actq.c \
qf_defer.c \
qf_dyn.c \
qf_mem.c \
qf_ps.c \
qf_qact.c \
qf_qeq.c \
qf_qmact.c \
qf_time.c \
qxk.c \
qxk_mutex.c \
qxk_sema.c \
qxk_xthr.c
QP_ASMS := \
qxk_port.s
QS_SRCS := \
qs.c \
qs_rx.c \
qs_fp.c
LIB_DIRS :=
LIBS :=
# defines
DEFINES :=
# ARM CPU, ARCH, FPU, and Float-ABI types...
# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4]
# ARM_ARCH: [6 | 7] (NOTE: must match ARM_CPU!)
# ARM_FPU: [ | vfp]
# FLOAT_ABI: [ | soft | softfp | hard]
#
ARM_CPU := -mcpu=cortex-m4
ARM_ARCH := 7 # NOTE: must match the ARM_CPU!
ARM_FPU := -mfpu=vfp
FLOAT_ABI := -mfloat-abi=softfp
#-----------------------------------------------------------------------------
# GNU-ARM toolset (NOTE: You need to adjust to your machine)
# see http://gnutoolchains.com/arm-eabi/
#
ifeq ($(GNU_ARM),)
GNU_ARM := $(QTOOLS)/gnu_arm-eabi
endif
# make sure that the GNU-ARM toolset exists...
ifeq ("$(wildcard $(GNU_ARM))","")
$(error GNU_ARM toolset not found. Please adjust the Makefile)
endif
CC := $(GNU_ARM)/bin/arm-eabi-gcc
CPP := $(GNU_ARM)/bin/arm-eabi-g++
AS := $(GNU_ARM)/bin/arm-eabi-as
LINK := $(GNU_ARM)/bin/arm-eabi-gcc
BIN := $(GNU_ARM)/bin/arm-eabi-objcopy
##############################################################################
# Typically, you should not need to change anything below this line
# basic utilities (included in Qtools for Windows), see:
# http://sourceforge.net/projects/qpc/files/Qtools
MKDIR := mkdir
RM := rm
#-----------------------------------------------------------------------------
# build options for various configurations for ARM Cortex-M4F
#
# combine all the soruces...
C_SRCS += $(QP_SRCS)
ASM_SRCS += $(QP_ASMS)
# add the pre-defined symbol for ARM architecture
DEFINES += -D__ARM_ARCH=$(ARM_ARCH)
ASM_CPU += -defsym=__ARM_ARCH=$(ARM_ARCH)
# add the pre-defined symbol __FPU_PRESENT if needed...
ifneq (,$(ARM_FPU))
DEFINES += -D__FPU_PRESENT
ASM_FPU += -defsym=__FPU_PRESENT=1
endif
ifeq (rel, $(CONF)) # Release configuration ..................................
BIN_DIR := rel
ASFLAGS = $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O1 $(INCLUDES) $(DEFINES) -DNDEBUG
CPPFLAGS = $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O1 $(INCLUDES) $(DEFINES) -DNDEBUG
else ifeq (spy, $(CONF)) # Spy configuration ................................
BIN_DIR := spy
C_SRCS += $(QS_SRCS)
ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O $(INCLUDES) $(DEFINES) -DQ_SPY
CPPFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O $(INCLUDES) $(DEFINES) -DQ_SPY
else # default Debug configuration ..........................................
BIN_DIR := dbg
ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU)
CFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections \
-O $(INCLUDES) $(DEFINES)
CPPFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \
-O $(INCLUDES) $(DEFINES)
endif # ......................................................................
LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) \
-mthumb -nostdlib \
-Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS)
ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS)))
C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS)))
CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS)))
TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin
TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf
ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS))
C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS))
C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT))
CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS))
CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT))
# create $(BIN_DIR) if it does not exist
ifeq ("$(wildcard $(BIN_DIR))","")
$(shell $(MKDIR) $(BIN_DIR))
endif
#-----------------------------------------------------------------------------
# rules
#
all: $(TARGET_BIN)
#all: $(TARGET_ELF)
$(TARGET_BIN): $(TARGET_ELF)
$(BIN) -O binary $< $@
$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT)
$(CC) $(CFLAGS) -c $(QPC)/include/qstamp.c -o $(BIN_DIR)/qstamp.o
$(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS)
$(BIN_DIR)/%.d : %.c
$(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@
$(BIN_DIR)/%.d : %.cpp
$(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@
$(BIN_DIR)/%.o : %.s
$(AS) $(ASFLAGS) $< -o $@
$(BIN_DIR)/%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(BIN_DIR)/%.o : %.cpp
$(CPP) $(CPPFLAGS) -c $< -o $@
# include dependency files only if our goal depends on their existence
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),show)
-include $(C_DEPS_EXT) $(CPP_DEPS_EXT)
endif
endif
.PHONY : clean
clean:
-$(RM) $(BIN_DIR)/*.o \
$(BIN_DIR)/*.d \
$(BIN_DIR)/*.bin \
$(BIN_DIR)/*.elf \
$(BIN_DIR)/*.map
show:
@echo PROJECT = $(PROJECT)
@echo CONF = $(CONF)
@echo DEFINES = $(DEFINES)
@echo ASM_FPU = $(ASM_FPU)
@echo ASM_SRCS = $(ASM_SRCS)
@echo C_SRCS = $(C_SRCS)
@echo CPP_SRCS = $(CPP_SRCS)
@echo ASM_OBJS_EXT = $(ASM_OBJS_EXT)
@echo C_OBJS_EXT = $(C_OBJS_EXT)
@echo C_DEPS_EXT = $(C_DEPS_EXT)
@echo CPP_DEPS_EXT = $(CPP_DEPS_EXT)
@echo TARGET_ELF = $(TARGET_ELF)

View File

@ -0,0 +1,71 @@
About this Example
==================
This example can be built from the command prompt with the provided
Makefile. The example can also be imported as a Makefile-based
project into Eclipse-based IDEs.
The Makefile
============
The provided Makefile should be easy to adapt for your own projects.
It contains three build configurations: Debug (default), Release, and
Spy.
Also, the Makefile has been specifically designed to work as an external
Makefile with the Eclipse CDT.
The various build configurations are built as follows:
make
make CONF=rel
make CONF=spy
make clean
make CONF=rel clean
make CONF=spy clean
***
NOTE:
The installation folder of the GNU-ARM toolset on YOUR machine needs
to be adjusted in the provided Makefile, by editing the symbol: GNU_ARM.
As described in the comment for this symbol, the GNU-ARM toolset is taken
from: http://gnutoolchains.com/arm-eabi
It is highly recommened to use the same GNU-ARM distribution, especially
for ARM Cortex-M4F projects, due to the support for the hardware FPU
(float-abi=hard).
***
Adjusting Stack and Heap Sizes
==============================
The stack and heap sizes are determined in this project by the GCC linker
script (.ld file), which provides a template of the recommended GCC linker
script for QP applications.
Startup Code
============
The startup code used in this project is located in the "3rd_party" folder
in the following location:
3rd_party\<board>\gcc\startup_<mcu>.c
The file startup_<mcu>.c provides a template of the recommended
startup for QP applications and should be easily customizable for other
ARM Cortex-M microcontrollers.
The startup file typically does not need to be modified or adapted for
applications. It provides only weak definitions of all exception and
interrupt handlers, as well as the assert_failed() function.
The weak function assert_failed() defined in this file might be re-defined
in the application to customize it for the application-specific error-
handling policy.
***
NOTE: The function assert_failed() typically should NOT use the stack,
because stack might be corrupted by the time this function is called.
Also, assert_failed() is intended to handle catastrophic errors and
should NOT return.
***

View File

@ -0,0 +1,135 @@
/*****************************************************************************
* Product: Linker script for STM32F407VG, GNU-ARM linker
* Last Updated for Version: 5.9.1
* Date of the Last Update: 2017-06-01
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(Reset_Handler) /* entry Point */
MEMORY { /* memory map of Tiva TM4C123GH6PM */
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
/* The size of the stack used by the application. NOTE: you need to adjust */
STACK_SIZE = 1024;
/* The size of the heap used by the application. NOTE: you need to adjust */
HEAP_SIZE = 0;
SECTIONS {
.isr_vector : { /* the vector table goes FIRST into ROM */
KEEP(*(.isr_vector)) /* vector table */
. = ALIGN(4);
} >ROM
.text : { /* code and constants */
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} >ROM
.preinit_array : {
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ROM
.init_array : {
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >ROM
.fini_array : {
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ROM
_etext = .; /* global symbols at end of code */
.stack : {
__stack_start__ = .;
. = . + STACK_SIZE;
. = ALIGN(4);
__stack_end__ = .;
} >RAM
.data : AT (_etext) {
__data_load = LOADADDR (.data);
__data_start = .;
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
__data_end__ = .;
_edata = __data_end__;
} >RAM
.bss : {
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = .;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE ( __end__ = _ebss );
.heap : {
__heap_start__ = .;
. = . + HEAP_SIZE;
. = ALIGN(4);
__heap_end__ = .;
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ : {
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}

View File

@ -0,0 +1,33 @@
::============================================================================
:: Batch file to load the DPP program to the flash of STM32 boards
::
:: NOTE: requires the ST-LINK utlity from ST, see:
:: http://www.st.com/en/embedded-software/stsw-link004.html
::
@echo off
setlocal
@echo Load the program to the flash of STM32 board
@echo usage: flash
@echo usage: flash rel
@echo usage: flash spy
::----------------------------------------------------------------------------
:: NOTE: Adjust the following symbol to the location of the
:: LMFlash utility on your machine
::
set STLINK="C:\tools\ST\ST-LINK\ST-LINK Utility\ST-LINK_CLI.exe"
:: set the build directory depending on the first parameter %1
set BUILD_DIR=dbg
if [%1] NEQ [] set BUILD_DIR=%1
@echo on
%STLINK% -P %BUILD_DIR%\dpp-qxk.bin 0x08000000
@echo.
@echo.
@echo Reset the target to start running your program!
@echo off
endlocal

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\dpp-qxk.ewp</path>
</project>
<batchBuild/>
</workspace>

View File

@ -0,0 +1,35 @@
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 1024;
define symbol __ICFEDIT_size_heap__ = 0;
/**** End of ICF editor section. ###ICF###*/
define symbol __region_RAM1_start__ = 0x10000000;
define symbol __region_RAM1_end__ = 0x1000FFFF;
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
place in RAM1_region { section .sram };

View File

@ -0,0 +1,121 @@
/*****************************************************************************
* Product: DPP example extened for the dual-mode QXK kernel
* Last Updated for Version: 5.9.0
* Date of the Last Update: 2017-04-13
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 2005-2017 Quantum Leaps, LLC. All Rigts 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
/*..........................................................................*/
int main() {
static QEvt const *tableQueueSto[N_PHILO];
static QEvt const *philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList subscrSto[MAX_PUB_SIG];
static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO]; /* small pool */
/* stacks and queues for the extended test threads */
static void const *test1QueueSto[5];
static uint64_t test1StackSto[64];
static void const *test2QueueSto[5];
static uint64_t test2StackSto[64];
uint8_t n;
Philo_ctor(); /* instantiate all Philosopher active objects */
Table_ctor(); /* instantiate the Table active object */
Test1_ctor(); /* instantiate the Test1 extended thread */
Test2_ctor(); /* instantiate the Test2 extended thread */
QF_init(); /* initialize the framework and the underlying RT kernel */
/* initialize publish-subscribe... */
QF_psInit(subscrSto, Q_DIM(subscrSto));
/* initialize event pools... */
QF_poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
/* initialize the Board Support Package
* NOTE: BSP_init() is called *after* initializing publish-subscribe and
* event pools, to make the system ready to accept SysTick interrupts.
* Unfortunately, the STM32Cube code that must be called from BSP,
* configures and starts SysTick.
*/
BSP_init();
/* object dictionaries... */
QS_OBJ_DICTIONARY(smlPoolSto);
QS_OBJ_DICTIONARY(tableQueueSto);
QS_OBJ_DICTIONARY(philoQueueSto[0]);
QS_OBJ_DICTIONARY(philoQueueSto[1]);
QS_OBJ_DICTIONARY(philoQueueSto[2]);
QS_OBJ_DICTIONARY(philoQueueSto[3]);
QS_OBJ_DICTIONARY(philoQueueSto[4]);
/* start the extended thread */
QXTHREAD_START(&XT_Test1->super, /* Thread to start */
(uint_fast8_t)1U, /* QP priority of the thread */
test1QueueSto, /* message queue storage */
Q_DIM(test1QueueSto), /* message length [events] */
test1StackSto, /* stack storage */
sizeof(test1StackSto), /* stack size [bytes] */
(QEvt *)0); /* initialization event */
/* start the Philo active objects... */
for (n = 0U; n < N_PHILO; ++n) {
QACTIVE_START(AO_Philo[n], /* AO to start */
(uint_fast8_t)(n + 2), /* QP priority of the AO */
philoQueueSto[n], /* event queue storage */
Q_DIM(philoQueueSto[n]), /* queue length [events] */
(void *)0, /* stack storage (not used) */
0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
}
QXTHREAD_START(&XT_Test2->super, /* Thread to start */
(uint_fast8_t)(N_PHILO + 2), /* QP priority of the thread */
test2QueueSto, /* message queue storage */
Q_DIM(test2QueueSto), /* message length [events] */
test2StackSto, /* stack storage */
sizeof(test2StackSto), /* stack size [bytes] */
(QEvt *)0); /* initialization event */
QACTIVE_START(AO_Table, /* AO to start */
(uint_fast8_t)(N_PHILO + 3), /* QP priority of the AO */
tableQueueSto, /* event queue storage */
Q_DIM(tableQueueSto), /* queue length [events] */
(void *)0, /* stack storage (not used) */
0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
return QF_run(); /* run the QF application */
}

View File

@ -0,0 +1,117 @@
/*****************************************************************************
* Product: DPP example
* Last Updated for Version: 5.8.2
* Date of the Last Update: 2017-01-28
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 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 3 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:
* https://state-machine.com
* mailto:info@state-machine.com
*****************************************************************************/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
/* local "naked" thread object .............................................*/
static QXThread l_test1;
static QXThread l_test2;
static QXMutex l_mutex;
static QXSemaphore l_sema;
/* global pointer to the test thread .......................................*/
QXThread * const XT_Test1 = &l_test1;
QXThread * const XT_Test2 = &l_test2;
/*..........................................................................*/
static void Thread1_run(QXThread * const me) {
QXMutex_init(&l_mutex, 3U);
(void)me;
for (;;) {
float volatile x;
/* wait on a semaphore (BLOCK with timeout) */
(void)QXSemaphore_wait(&l_sema, BSP_TICKS_PER_SEC, 0U);
//BSP_ledOn();
QXMutex_lock(&l_mutex); /* exercise the mutex */
/* some flating point code to exercise the VFP... */
x = 1.4142135F;
x = x * 1.4142135F;
QXMutex_unlock(&l_mutex);
QXThread_delay(BSP_TICKS_PER_SEC/7, 0U); /* BLOCK */
/* publish to thread2 */
QF_PUBLISH(Q_NEW(QEvt, TEST_SIG), &l_test1);
}
}
/*..........................................................................*/
void Test1_ctor(void) {
QXThread_ctor(&l_test1, Q_XTHREAD_CAST(&Thread1_run), 0U);
}
/*..........................................................................*/
static void Thread2_run(QXThread * const me) {
/* subscribe to the test signal */
QActive_subscribe(&me->super, TEST_SIG);
/* initialize the semaphore before using it
* NOTE: the semaphore is initialized in the highest-priority thread
* that uses it. Alternatively, the semaphore can be initialized
* before any thread runs.
*/
QXSemaphore_init(&l_sema, 0U); /* start with zero count */
for (;;) {
QEvt const *e;
/* some flating point code to exercise the VFP... */
float volatile x;
x = 1.4142135F;
x = x * 1.4142135F;
/* wait on the internal event queue (BLOCK) with timeout */
e = QXThread_queueGet(BSP_TICKS_PER_SEC/2, 0U);
//BSP_ledOff();
if (e != (QEvt *)0) { /* event actually delivered? */
QF_gc(e); /* recycle the event manually! */
}
else {
QXThread_delay(BSP_TICKS_PER_SEC/2, 0U); /* wait more (BLOCK) */
QXSemaphore_signal(&l_sema); /* signal Thread1 */
}
}
}
/*..........................................................................*/
void Test2_ctor(void) {
QXThread_ctor(&l_test2, Q_XTHREAD_CAST(&Thread2_run), 0U);
}

View File

@ -0,0 +1,296 @@
/*****************************************************************************
* Model: dpp.qm
* File: ./table.c
*
* This code has been generated by QM tool (see state-machine.com/qm).
* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
*
* 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.
*
* 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.
*****************************************************************************/
/*${.::table.c} ............................................................*/
#include "qpc.h"
#include "dpp.h"
#include "bsp.h"
Q_DEFINE_THIS_FILE
/* Active object class -----------------------------------------------------*/
#if ((QP_VERSION < 580) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8)))
#error qpc version 5.8.0 or higher required
#endif
/*${AOs::Table} ............................................................*/
typedef struct {
/* protected: */
QActive super;
/* private: */
uint8_t fork[N_PHILO];
uint8_t isHungry[N_PHILO];
} Table;
/* protected: */
static QState Table_initial(Table * const me, QEvt const * const e);
static QState Table_active(Table * const me, QEvt const * const e);
static QState Table_serving(Table * const me, QEvt const * const e);
static QState Table_paused(Table * const me, QEvt const * const e);
#define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1U)) % N_PHILO))
#define LEFT(n_) ((uint8_t)(((n_) + 1U) % N_PHILO))
#define FREE ((uint8_t)0)
#define USED ((uint8_t)1)
/* Local objects -----------------------------------------------------------*/
static Table l_table; /* the single instance of the Table active object */
/* Global-scope objects ----------------------------------------------------*/
QMActive * const AO_Table = &l_table.super; /* "opaque" AO pointer */
/*..........................................................................*/
/*${AOs::Table_ctor} .......................................................*/
void Table_ctor(void) {
uint8_t n;
Table *me = &l_table;
QActive_ctor(&me->super, Q_STATE_CAST(&Table_initial));
for (n = 0U; n < N_PHILO; ++n) {
me->fork[n] = FREE;
me->isHungry[n] = 0U;
}
}
/*${AOs::Table} ............................................................*/
/*${AOs::Table::SM} ........................................................*/
static QState Table_initial(Table * const me, QEvt const * const e) {
/* ${AOs::Table::SM::initial} */
uint8_t n;
(void)e; /* suppress the compiler warning about unused parameter */
QS_OBJ_DICTIONARY(&l_table);
QS_FUN_DICTIONARY(&QHsm_top);
QS_FUN_DICTIONARY(&Table_initial);
QS_FUN_DICTIONARY(&Table_active);
QS_FUN_DICTIONARY(&Table_serving);
QS_FUN_DICTIONARY(&Table_paused);
QS_SIG_DICTIONARY(DONE_SIG, (void *)0); /* global signals */
QS_SIG_DICTIONARY(EAT_SIG, (void *)0);
QS_SIG_DICTIONARY(PAUSE_SIG, (void *)0);
QS_SIG_DICTIONARY(SERVE_SIG, (void *)0);
QS_SIG_DICTIONARY(TEST_SIG, (void *)0);
QS_SIG_DICTIONARY(HUNGRY_SIG, me); /* signal just for Table */
QActive_subscribe(&me->super, DONE_SIG);
QActive_subscribe(&me->super, PAUSE_SIG);
QActive_subscribe(&me->super, SERVE_SIG);
QActive_subscribe(&me->super, TEST_SIG);
for (n = 0U; n < N_PHILO; ++n) {
me->fork[n] = FREE;
me->isHungry[n] = 0U;
BSP_displayPhilStat(n, "thinking");
}
return Q_TRAN(&Table_serving);
}
/*${AOs::Table::SM::active} ................................................*/
static QState Table_active(Table * const me, QEvt const * const e) {
QState status_;
switch (e->sig) {
/* ${AOs::Table::SM::active::TEST} */
case TEST_SIG: {
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::EAT} */
case EAT_SIG: {
Q_ERROR();
status_ = Q_HANDLED();
break;
}
default: {
status_ = Q_SUPER(&QHsm_top);
break;
}
}
return status_;
}
/*${AOs::Table::SM::active::serving} .......................................*/
static QState Table_serving(Table * const me, QEvt const * const e) {
QState status_;
switch (e->sig) {
/* ${AOs::Table::SM::active::serving} */
case Q_ENTRY_SIG: {
uint8_t n;
for (n = 0U; n < N_PHILO; ++n) { /* give permissions to eat... */
if ((me->isHungry[n] != 0U)
&& (me->fork[LEFT(n)] == FREE)
&& (me->fork[n] == FREE))
{
TableEvt *te;
me->fork[LEFT(n)] = USED;
me->fork[n] = USED;
te = Q_NEW(TableEvt, EAT_SIG);
te->philoNum = n;
QF_PUBLISH(&te->super, me);
me->isHungry[n] = 0U;
BSP_displayPhilStat(n, "eating ");
}
}
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::serving::HUNGRY} */
case HUNGRY_SIG: {
uint8_t n, m;
n = Q_EVT_CAST(TableEvt)->philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
BSP_displayPhilStat(n, "hungry ");
m = LEFT(n);
/* ${AOs::Table::SM::active::serving::HUNGRY::[bothfree]} */
if ((me->fork[m] == FREE) && (me->fork[n] == FREE)) {
TableEvt *pe;
me->fork[m] = USED;
me->fork[n] = USED;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = n;
QF_PUBLISH(&pe->super, me);
BSP_displayPhilStat(n, "eating ");
status_ = Q_HANDLED();
}
/* ${AOs::Table::SM::active::serving::HUNGRY::[else]} */
else {
me->isHungry[n] = 1U;
status_ = Q_HANDLED();
}
break;
}
/* ${AOs::Table::SM::active::serving::DONE} */
case DONE_SIG: {
uint8_t n, m;
TableEvt *pe;
n = Q_EVT_CAST(TableEvt)->philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
BSP_displayPhilStat(n, "thinking");
m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED));
me->fork[m] = FREE;
me->fork[n] = FREE;
m = RIGHT(n); /* check the right neighbor */
if ((me->isHungry[m] != 0U) && (me->fork[m] == FREE)) {
me->fork[n] = USED;
me->fork[m] = USED;
me->isHungry[m] = 0U;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
QF_PUBLISH(&pe->super, me);
BSP_displayPhilStat(m, "eating ");
}
m = LEFT(n); /* check the left neighbor */
n = LEFT(m); /* left fork of the left neighbor */
if ((me->isHungry[m] != 0U) && (me->fork[n] == FREE)) {
me->fork[m] = USED;
me->fork[n] = USED;
me->isHungry[m] = 0U;
pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
QF_PUBLISH(&pe->super, me);
BSP_displayPhilStat(m, "eating ");
}
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::serving::EAT} */
case EAT_SIG: {
Q_ERROR();
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::serving::PAUSE} */
case PAUSE_SIG: {
status_ = Q_TRAN(&Table_paused);
break;
}
default: {
status_ = Q_SUPER(&Table_active);
break;
}
}
return status_;
}
/*${AOs::Table::SM::active::paused} ........................................*/
static QState Table_paused(Table * const me, QEvt const * const e) {
QState status_;
switch (e->sig) {
/* ${AOs::Table::SM::active::paused} */
case Q_ENTRY_SIG: {
BSP_displayPaused(1U);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::paused} */
case Q_EXIT_SIG: {
BSP_displayPaused(0U);
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::paused::SERVE} */
case SERVE_SIG: {
status_ = Q_TRAN(&Table_serving);
break;
}
/* ${AOs::Table::SM::active::paused::HUNGRY} */
case HUNGRY_SIG: {
uint8_t n = Q_EVT_CAST(TableEvt)->philoNum;
/* philo ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
me->isHungry[n] = 1U;
BSP_displayPhilStat(n, "hungry ");
status_ = Q_HANDLED();
break;
}
/* ${AOs::Table::SM::active::paused::DONE} */
case DONE_SIG: {
uint8_t n, m;
n = Q_EVT_CAST(TableEvt)->philoNum;
/* phil ID must be in range and he must be not hungry */
Q_ASSERT((n < N_PHILO) && (me->isHungry[n] == 0U));
BSP_displayPhilStat(n, "thinking");
m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED));
me->fork[m] = FREE;
me->fork[n] = FREE;
status_ = Q_HANDLED();
break;
}
default: {
status_ = Q_SUPER(&Table_active);
break;
}
}
return status_;
}

Some files were not shown because too many files have changed in this diff Show More