This commit is contained in:
QL 2018-12-17 20:51:15 -05:00
parent 719bd515a4
commit 6eab63640f
29 changed files with 11803 additions and 1427 deletions

View File

@ -1,452 +0,0 @@
;/***************************************************************************/
; * @file startup_stm32f4xx.s for ThreadX; IAR ARM assembler
; * @brief CMSIS Cortex-M4F Core Device Startup File for STM32F40xx devices
; * @version CMSIS 4.3.0
; * @date 20 August 2015
; *
; * @description
; * Created from the CMSIS template for the specified device
; * Quantum Leaps, www.state-machine.com
; *
; * @attention
; * Adapted for ThreadX STM32demo library, which is NOT CMSIS-compiliant.
; * Specifically, the standard Cortex-M exception names required by
; * ThreadX are different than prescribed by CMSIS.
; *
; * @note
; * The function assert_failed defined at the end of this file defines
; * the error/assertion handling policy for the application and might
; * need to be customized for each project. This function is defined in
; * assembly to re-set the stack pointer, in case it is corrupted by the
; * time assert_failed is called.
; *
; ***************************************************************************/
;/* Copyright (c) 2012 ARM LIMITED
;
; All rights reserved.
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; - Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; - Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; - Neither the name of ARM nor the names of its contributors may be used
; to endorse or promote products derived from this software without
; specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;---------------------------------------------------------------------------*/
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
PUBLIC __vector_table
PUBLIC __Vectors
PUBLIC __Vectors_End
PUBLIC __Vectors_Size
;; QL: added for ThreadX
PUBLIC __tx_vectors
EXTERN __tx_SVCallHandler
EXTERN __tx_PendSVHandler
EXTERN __tx_SysTickHandler
;******************************************************************************
;
DATA
__vector_table
__tx_vectors
DCD sfe(CSTACK)
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; The MPU fault handler
DCD BusFault_Handler ; The bus fault handler
DCD UsageFault_Handler ; The usage fault handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD __tx_SVCallHandler ; QL: SVCall handler (ThreadX) !!!
DCD DebugMon_Handler ; Debug monitor handler
DCD 0 ; Reserved
DCD __tx_PendSVHandler ; QL: PendSV handler (ThreadX) !!!
DCD __tx_SysTickHandler ; QL: SysTick handler (ThreadX) !!!
; IRQ handlers...
DCD WWDG_IRQHandler ; Window WatchDog
DCD PVD_IRQHandler ; PVD through EXTI Line detection
DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s
DCD CAN1_TX_IRQHandler ; CAN1 TX
DCD CAN1_RX0_IRQHandler ; CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; External Line[9:5]s
DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9
DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10
DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; External Line[15:10]s
DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line
DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12
DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13
DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD FSMC_IRQHandler ; FSMC
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5
DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
DCD TIM7_IRQHandler ; TIM7
DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
DCD ETH_IRQHandler ; Ethernet
DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line
DCD CAN2_TX_IRQHandler ; CAN2 TX
DCD CAN2_RX0_IRQHandler ; CAN2 RX0
DCD CAN2_RX1_IRQHandler ; CAN2 RX1
DCD CAN2_SCE_IRQHandler ; CAN2 SCE
DCD OTG_FS_IRQHandler ; USB OTG FS
DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
DCD USART6_IRQHandler ; USART6
DCD I2C3_EV_IRQHandler ; I2C3 event
DCD I2C3_ER_IRQHandler ; I2C3 error
DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out
DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In
DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI
DCD OTG_HS_IRQHandler ; USB OTG HS
DCD DCMI_IRQHandler ; DCMI
DCD CRYP_IRQHandler ; CRYP crypto
DCD HASH_RNG_IRQHandler ; Hash and Rng
DCD FPU_IRQHandler ; FPU
__Vectors_End
__Vectors EQU __vector_table
__Vectors_Size EQU __Vectors_End - __Vectors
;******************************************************************************
;
; Weak fault handlers...
;
SECTION .text:CODE:REORDER:NOROOT(2)
;.............................................................................
PUBWEAK Reset_Handler
EXTERN SystemInit
EXTERN __iar_program_start
Reset_Handler
BL SystemInit ; CMSIS system initialization
BL __iar_program_start ; IAR startup code
;.............................................................................
PUBWEAK NMI_Handler
NMI_Handler
MOVS r0,#0
MOVS r1,#2 ; NMI exception number
B assert_failed
;.............................................................................
PUBWEAK HardFault_Handler
HardFault_Handler
MOVS r0,#0
MOVS r1,#3 ; HardFault exception number
B assert_failed
;.............................................................................
PUBWEAK MemManage_Handler
MemManage_Handler
MOVS r0,#0
MOVS r1,#4 ; MemManage exception number
B assert_failed
;.............................................................................
PUBWEAK BusFault_Handler
BusFault_Handler
MOVS r0,#0
MOVS r1,#5 ; BusFault exception number
B assert_failed
;.............................................................................
PUBWEAK UsageFault_Handler
UsageFault_Handler
MOVS r0,#0
MOVS r1,#6 ; UsageFault exception number
B assert_failed
;******************************************************************************
;
; Weak non-fault handlers...
;
PUBWEAK SVC_Handler
SVC_Handler
MOVS r0,#0
MOVS r1,#11 ; SVCall exception number
B assert_failed
;.............................................................................
PUBWEAK DebugMon_Handler
DebugMon_Handler
MOVS r0,#0
MOVS r1,#12 ; DebugMon exception number
B assert_failed
;.............................................................................
PUBWEAK PendSV_Handler
PendSV_Handler
MOVS r0,#0
MOVS r1,#14 ; PendSV exception number
B assert_failed
;.............................................................................
PUBWEAK SysTick_Handler
SysTick_Handler
MOVS r0,#0
MOVS r1,#15 ; SysTick exception number
B assert_failed
;******************************************************************************
;
; Weak IRQ handlers...
;
PUBWEAK WWDG_IRQHandler
PUBWEAK PVD_IRQHandler
PUBWEAK TAMP_STAMP_IRQHandler
PUBWEAK RTC_WKUP_IRQHandler
PUBWEAK FLASH_IRQHandler
PUBWEAK RCC_IRQHandler
PUBWEAK EXTI0_IRQHandler
PUBWEAK EXTI1_IRQHandler
PUBWEAK EXTI2_IRQHandler
PUBWEAK EXTI3_IRQHandler
PUBWEAK EXTI4_IRQHandler
PUBWEAK DMA1_Stream0_IRQHandler
PUBWEAK DMA1_Stream1_IRQHandler
PUBWEAK DMA1_Stream2_IRQHandler
PUBWEAK DMA1_Stream3_IRQHandler
PUBWEAK DMA1_Stream4_IRQHandler
PUBWEAK DMA1_Stream5_IRQHandler
PUBWEAK DMA1_Stream6_IRQHandler
PUBWEAK ADC_IRQHandler
PUBWEAK CAN1_TX_IRQHandler
PUBWEAK CAN1_RX0_IRQHandler
PUBWEAK CAN1_RX1_IRQHandler
PUBWEAK CAN1_SCE_IRQHandler
PUBWEAK EXTI9_5_IRQHandler
PUBWEAK TIM1_BRK_TIM9_IRQHandler
PUBWEAK TIM1_UP_TIM10_IRQHandler
PUBWEAK TIM1_TRG_COM_TIM11_IRQHandler
PUBWEAK TIM1_CC_IRQHandler
PUBWEAK TIM2_IRQHandler
PUBWEAK TIM3_IRQHandler
PUBWEAK TIM4_IRQHandler
PUBWEAK I2C1_EV_IRQHandler
PUBWEAK I2C1_ER_IRQHandler
PUBWEAK I2C2_EV_IRQHandler
PUBWEAK I2C2_ER_IRQHandler
PUBWEAK SPI1_IRQHandler
PUBWEAK SPI2_IRQHandler
PUBWEAK USART1_IRQHandler
PUBWEAK USART2_IRQHandler
PUBWEAK USART3_IRQHandler
PUBWEAK EXTI15_10_IRQHandler
PUBWEAK RTC_Alarm_IRQHandler
PUBWEAK OTG_FS_WKUP_IRQHandler
PUBWEAK TIM8_BRK_TIM12_IRQHandler
PUBWEAK TIM8_UP_TIM13_IRQHandler
PUBWEAK TIM8_TRG_COM_TIM14_IRQHandler
PUBWEAK TIM8_CC_IRQHandler
PUBWEAK DMA1_Stream7_IRQHandler
PUBWEAK FSMC_IRQHandler
PUBWEAK SDIO_IRQHandler
PUBWEAK TIM5_IRQHandler
PUBWEAK SPI3_IRQHandler
PUBWEAK UART4_IRQHandler
PUBWEAK UART5_IRQHandler
PUBWEAK TIM6_DAC_IRQHandler
PUBWEAK TIM7_IRQHandler
PUBWEAK DMA2_Stream0_IRQHandler
PUBWEAK DMA2_Stream1_IRQHandler
PUBWEAK DMA2_Stream2_IRQHandler
PUBWEAK DMA2_Stream3_IRQHandler
PUBWEAK DMA2_Stream4_IRQHandler
PUBWEAK ETH_IRQHandler
PUBWEAK ETH_WKUP_IRQHandler
PUBWEAK CAN2_TX_IRQHandler
PUBWEAK CAN2_RX0_IRQHandler
PUBWEAK CAN2_RX1_IRQHandler
PUBWEAK CAN2_SCE_IRQHandler
PUBWEAK OTG_FS_IRQHandler
PUBWEAK DMA2_Stream5_IRQHandler
PUBWEAK DMA2_Stream6_IRQHandler
PUBWEAK DMA2_Stream7_IRQHandler
PUBWEAK USART6_IRQHandler
PUBWEAK I2C3_EV_IRQHandler
PUBWEAK I2C3_ER_IRQHandler
PUBWEAK OTG_HS_EP1_OUT_IRQHandler
PUBWEAK OTG_HS_EP1_IN_IRQHandler
PUBWEAK OTG_HS_WKUP_IRQHandler
PUBWEAK OTG_HS_IRQHandler
PUBWEAK DCMI_IRQHandler
PUBWEAK CRYP_IRQHandler
PUBWEAK HASH_RNG_IRQHandler
PUBWEAK FPU_IRQHandler
WWDG_IRQHandler
PVD_IRQHandler
TAMP_STAMP_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Stream0_IRQHandler
DMA1_Stream1_IRQHandler
DMA1_Stream2_IRQHandler
DMA1_Stream3_IRQHandler
DMA1_Stream4_IRQHandler
DMA1_Stream5_IRQHandler
DMA1_Stream6_IRQHandler
ADC_IRQHandler
CAN1_TX_IRQHandler
CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_TIM9_IRQHandler
TIM1_UP_TIM10_IRQHandler
TIM1_TRG_COM_TIM11_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
OTG_FS_WKUP_IRQHandler
TIM8_BRK_TIM12_IRQHandler
TIM8_UP_TIM13_IRQHandler
TIM8_TRG_COM_TIM14_IRQHandler
TIM8_CC_IRQHandler
DMA1_Stream7_IRQHandler
FSMC_IRQHandler
SDIO_IRQHandler
TIM5_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
UART5_IRQHandler
TIM6_DAC_IRQHandler
TIM7_IRQHandler
DMA2_Stream0_IRQHandler
DMA2_Stream1_IRQHandler
DMA2_Stream2_IRQHandler
DMA2_Stream3_IRQHandler
DMA2_Stream4_IRQHandler
ETH_IRQHandler
ETH_WKUP_IRQHandler
CAN2_TX_IRQHandler
CAN2_RX0_IRQHandler
CAN2_RX1_IRQHandler
CAN2_SCE_IRQHandler
OTG_FS_IRQHandler
DMA2_Stream5_IRQHandler
DMA2_Stream6_IRQHandler
DMA2_Stream7_IRQHandler
USART6_IRQHandler
I2C3_EV_IRQHandler
I2C3_ER_IRQHandler
OTG_HS_EP1_OUT_IRQHandler
OTG_HS_EP1_IN_IRQHandler
OTG_HS_WKUP_IRQHandler
OTG_HS_IRQHandler
DCMI_IRQHandler
CRYP_IRQHandler
HASH_RNG_IRQHandler
FPU_IRQHandler
MOV r0,#0
MOV r1,#-1 ; 0xFFFFFFF
B assert_failed
;******************************************************************************
;
; The function assert_failed defines the error/assertion handling policy
; for the application. After making sure that the stack is OK, this function
; calls Q_onAssert, which should NOT return (typically reset the CPU).
;
; NOTE: the function Q_onAssert should NOT return.
;
; The C proptotype of the assert_failed() and Q_onAssert() functions are:
; void assert_failed(char const *file, int line);
; void Q_onAssert (char const *file, int line);
;******************************************************************************
PUBLIC assert_failed
EXTERN Q_onAssert
assert_failed
LDR sp,=sfe(CSTACK) ; re-set the SP in case of stack overflow
BL Q_onAssert ; call the application-specific handler
B . ; should not be reached, but just in case...
END ; end of module

View File

@ -1,258 +0,0 @@
Express Logic's ThreadX for STM3240G-EVAL (Cortex-M4 FPU) Evaluation Board
Using the IAR Tools
*** DEMO VERSION ***
0. About This Version
This version of ThreadX is for demonstration purposes only and may not
be used for any product development, either directly or indirectly. In
addition, this demonstration may not be used for any competitive purpose.
1. Installation
ThreadX for the Cortex-M4 is delivered on a single CD-ROM compatible disk.
The entire distribution can be found in the sub-directory:
\threadx
To install ThreadX to your hard-disk, either run the supplied installer
program Setup.exe or copy the distribution from the CD manually.
To copy the ThreadX distribution manually, make a ThreadX directory on your
hard-disk (we recommend c:\threadx\stm3240g-eval\iar) and copy all the contents
of the ThreadX sub-directory on the distribution disk. The following
is an example MS-DOS copy command from the distribution directory
(assuming source is d: and c: is your hard-drive):
d:\threadx> xcopy /S *.* c:\threadx\stm3240g-eval\iar
2. Building the ThreadX run-time Library
This demonstration version contains a pre-built ThreadX library, tx.a. The library is
intended for demonstration purposes only and thus has the following limitations:
10 Threads
9 Timers
2 Event Flag Groups
2 Mutexes
3 Queues
2 Semaphores
1 Block Pool
1 Byte Pool
3. Demonstration System
The ThreadX demonstration is designed to execute under the IAR debugger on the
STM3240G-EVAL evaluation board (STM32F407 processor).
Building the demonstration is easy; simply open the threadx.www workspace file,
make the demo_threadx.ewp project the "active project" in the IAR Embedded
Workbench, and select the "Make" button.
You should observe the compilation of demo_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file demo_threadx.out is a
binary ELF file that can be downloaded to flash and executed on the STM3240G-EVAL
evaluation board connected via a USB cable to the IAR J-Link JTAG probe.
4. System Initialization
The entry point in ThreadX for the Cortex-M4 using IAR tools is at label
__iar_program_start. This is defined within the IAR compiler's startup code.
In addition, this is where all static and global preset C variable
initialization processing takes place.
The ThreadX tx_initialize_low_level.s file is responsible for setting up
various system data structures, and a periodic timer interrupt source.
By default, the vector area is defined at the top of startup_stm32f40x.s,
which is a slightly modified from the base ST/IAR file.
The _tx_initialize_low_level function inside of tx_initialize_low_level.s
also determines the first available address for use by the application, which
is supplied as the sole input parameter to your application definition function,
tx_application_define. To accomplish this, a section is created in
tx_initialize_low_level.s called FREE_MEM, which must be located after all
other RAM sections in memory.
5. Register Usage and Stack Frames
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 r4
0x04 r5
0x08 r6
0x0C r7
0x10 r8
0x14 r9
0x18 r10 (sl)
0x1C r11
0x20 r0 (Hardware stack starts here!!)
0x24 r1
0x28 r2
0x2C r3
0x30 r12
0x34 lr
0x38 pc
0x3C xPSR
FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 s0
0x04 s1
0x08 s2
0x0C s3
0x10 s4
0x14 s5
0x18 s6
0x1C s7
0x20 s8
0x24 s9
0x28 s10
0x2C s11
0x30 s12
0x34 s13
0x38 s14
0x3C s15
0x40 s16
0x44 s17
0x48 s18
0x4C s19
0x50 s20
0x54 s21
0x58 s22
0x5C s23
0x60 s24
0x64 s25
0x68 s26
0x6C s27
0x70 s28
0x74 s29
0x78 s30
0x7C s31
0x80 fpscr
0x84 r4
0x88 r5
0x8C r6
0x90 r7
0x94 r8
0x98 r9
0x9C r10 (sl)
0xA0 r11
0xA4 r0 (Hardware stack starts here!!)
0xA8 r1
0xAC r2
0xB0 r3
0xB4 r12
0xB8 lr
0xBC pc
0xC0 xPSR
6. Improving Performance
The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make it run faster, you can change the ThreadX library
project to enable various compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
defined.
7. Interrupt Handling
ThreadX provides complete and high-performance interrupt handling for Cortex-M4
targets. There are a certain set of requirements that are defined in the
following sub-sections:
7.1 Vector Area
The Cortex-M4 vectors start at the label __tx_vectors and is defined in cstartup_M.s.
The application may modify the vector area according to its needs.
7.2 Managed Interrupts
A ThreadX managed interrupt is defined below. By following these conventions, the
application ISR is then allowed access to various ThreadX services from the ISR.
Here is the standard template for managed ISRs in ThreadX:
PUBLIC __tx_IntHandler
__tx_IntHandler:
; VOID InterruptHandler (VOID)
; {
PUSH {lr}
BL _tx_thread_context_save
; /* Do interrupt handler work here */
; /* .... */
B _tx_thread_context_restore
; }
8. IAR Thread-safe Library Support
Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
should have the following line added (if not already in place):
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
9. FPU Support
By default, FPU support is disabled for each thread. If saving the context of the FPU registers
is needed, the following API call must be made from the context of the application thread - before
the FPU usage:
void tx_thread_fpu_enable(void);
After this API is called in the application, FPU registers will be saved/restored for this thread if it
is preempted via an interrupt. All other suspension of the this thread will not require the FPU registers
to be saved/restored.
To disable FPU register context saving, simply call the following API:
void tx_thread_fpu_disable(void);
9. Revision History
01/24/2012 Initial ThreadX demo version for ST's STM3240G-EVAL board using IAR's ARM tools.
Copyright(c) 1996-2012 Express Logic, Inc.
Express Logic, Inc.
11423 West Bernardo Court
San Diego, CA 92127
www.expresslogic.com

View File

@ -0,0 +1,248 @@
Express Logic's ThreadX for ST's STM32F4 Discovery Evaluation Board (Cortex-M4)
Using the IAR Tools
*** DEMO VERSION ***
0. About This Version
This version of ThreadX is for demonstration purposes only and may not
be used for any product development, either directly or indirectly. In
addition, this demonstration may not be used for any competitive purpose.
1. Installation
ThreadX for ST's STM32F4 Discovery (Cortex-M4) is pre-installed in the evaluation
package.
2. Building the ThreadX run-time Library
This demonstration version contains a pre-built ThreadX library, tx.a. The library is
intended for demonstration purposes only and thus has the following limitations:
10 Threads
10 Timers
10 Event Flag Groups
10 Mutexes
10 Queues
10 Semaphores
10 Block Pool
10 Byte Pool
3. Demonstration System
The ThreadX demonstration is designed to execute on the STM32F4 Discovery evaluation
board under the IAR Windows-based debugger.
Building the demonstration is easy; simply make the demo_threadx.ewp project
the "active project" in the IAR Embedded Workbench and select the "Make" button.
You should observe the compilation of demo_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file demo_threadx.out is a binary
file that can be downloaded and executed on the STM32F4 Discovery evaluation board using
the IAR debugger.
4. System Initialization
The entry point in ThreadX for the (Cortex-M4) using IAR tools is at label
Reset_Handler. This is defined within the STM32 startup code, namely
the file startup_stm32f429xx.s. From this entry point, the IAR startup code
at __iar_program_start is called. This is where all static and global preset
C variable initialization processing takes place.
The ThreadX tx_initialize_low_level.s file is responsible for setting up
various system data structures, and a periodic timer interrupt source.
The _tx_initialize_low_level function inside of tx_initialize_low_level.s
also determines the first available address for use by the application, which
is supplied as the sole input parameter to your application definition function,
tx_application_define. To accomplish this, a section is created in
tx_initialize_low_level.s called FREE_MEM, which must be located after all
other RAM sections in memory.
5. Register Usage and Stack Frames
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x04 r4
0x08 r5
0x0C r6
0x10 r7
0x14 r8
0x18 r9
0x1C r10 (sl)
0x20 r11
0x24 r0 (Hardware stack starts here!!)
0x28 r1
0x2C r2
0x30 r3
0x34 r12
0x38 lr
0x3C pc
0x40 xPSR
FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x04 s0
0x08 s1
0x0C s2
0x10 s3
0x14 s4
0x18 s5
0x1C s6
0x20 s7
0x24 s8
0x28 s9
0x2C s10
0x30 s11
0x34 s12
0x38 s13
0x3C s14
0x40 s15
0x44 s16
0x48 s17
0x4C s18
0x50 s19
0x54 s20
0x58 s21
0x5C s22
0x60 s23
0x64 s24
0x68 s25
0x6C s26
0x70 s27
0x74 s28
0x78 s29
0x7C s30
0x80 s31
0x84 fpscr
0x88 r4
0x8C r5
0x90 r6
0x94 r7
0x98 r8
0x9C r9
0xA0 r10 (sl)
0xA4 r11
0xA8 r0 (Hardware stack starts here!!)
0xAC r1
0xB0 r2
0xB4 r3
0xB8 r12
0xBC lr
0xC0 pc
0xC4 xPSR
6. Improving Performance
The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make it run faster, you can change the ThreadX library
project to enable various compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
defined.
7. Interrupt Handling
The Cortex-M4 vectors start at the label __vector_table and is defined in cstartup_M.s.
The application may modify the vector area according to its needs.
7.2 Managed Interrupts
From version 5.6 going forward, ISRs for Cortex-M using the IAR tools can be written
completely in C (or assembly language) without any calls to _tx_thread_context_save or
_tx_thread_context_restore. These ISRs are allowed access to the ThreadX API that is
available to ISRs.
ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
void your_C_isr(void)
{
/* ISR processing goes here, including any needed function calls. */
}
ISRs written in assembly language will take the form:
PUBLIC your_assembly_isr
your_assembly_isr:
PUSH {lr}
; ISR processing goes here, including any needed function calls.
POP {lr}
BX lr
Backward compatibility to the previous style assembly ISRs is maintained, which was of
the form:
PUBLIC __legacy_isr_handler
__legacy_isr_handler:
PUSH {lr}
BL _tx_thread_context_save
; /* Do interrupt handler work here */
; /* .... */
B _tx_thread_context_restore
8. IAR Thread-safe Library Support
Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
should have the following line added (if not already in place):
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
The project options "General Options -> Library Configuration" should also have the
"Enable thread support in library" box selected.
9. VFP Support
When applicable, ThreadX for the STM32F4 Discovery (Cortex-M4) supports lazy VFP support, which
means that applications threads can simply use the VFP and ThreadX automatically maintains
the VFP registers as part of the thread context - no additional setup by the application
is required.
10. Revision History
08/01/2017 Initial ThreadX version for STM32F4 Discovery (Cortex-M4) using IAR's ARM tools.
Copyright(c) 1996-2017 Express Logic, Inc.
Express Logic, Inc.
11323 West Bernardo Court
San Diego, CA 92127
www.expresslogic.com

View File

@ -0,0 +1,431 @@
/**************************************************************************/
/* */
/* Copyright (c) 1996-2017 by Express Logic Inc. */
/* */
/* This software is copyrighted by and is the sole property of Express */
/* Logic, Inc. All rights, title, ownership, or other interests */
/* in the software remain the property of Express Logic, Inc. This */
/* software may only be used in accordance with the corresponding */
/* license agreement. Any unauthorized use, duplication, transmission, */
/* distribution, or disclosure of this software is expressly forbidden. */
/* */
/* This Copyright notice may not be removed or modified without prior */
/* written consent of Express Logic, Inc. */
/* */
/* Express Logic, Inc. reserves the right to modify this software */
/* without notice. */
/* */
/* Express Logic, Inc. info@expresslogic.com */
/* 11423 West Bernardo Court http://www.expresslogic.com */
/* San Diego, CA 92127 */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Port Specific */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/IAR */
/* 5.6 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Express Logic, Inc. */
/* */
/* DESCRIPTION */
/* */
/* This file contains data type definitions that make the ThreadX */
/* real-time kernel function identically on a variety of different */
/* processor architectures. For example, the size or number of bits */
/* in an "int" data type vary between microprocessor architectures and */
/* even C compilers for the same microprocessor. ThreadX does not */
/* directly use native C data types. Instead, ThreadX creates its */
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 10-10-2010 William E. Lamie Initial Cortex-M4 IAR */
/* Support Version 5.0 */
/* 07-15-2011 William E. Lamie Modified comment(s), added */
/* IAR thread-safe library */
/* support, and updated */
/* version string, resulting */
/* in version 5.1 */
/* 04-15-2012 William E. Lamie Modified comment(s), added */
/* FPU enable/disable function */
/* prototypes, and updated */
/* version string, resulting */
/* in version 5.2 */
/* 01-01-2014 William E. Lamie Modified comment(s), added */
/* FPU enable/disable struct */
/* member, and updated */
/* version string, resulting */
/* in version 5.3 */
/* 04-15-2014 William E. Lamie Modified comment(s), and */
/* updated version string, */
/* resulting in version 5.4 */
/* 09-01-2014 William E. Lamie Modified comment(s), and */
/* updated version string, */
/* resulting in version 5.5 */
/* 06-01-2017 William E. Lamie Modified comment(s), added */
/* support for new thread-safe */
/* IAR libraries, removed */
/* unneeded VFP enable flag, */
/* added logic to remove the */
/* need for context */
/* save/restore calls in ISRs, */
/* modified code for MISRA */
/* compliance, and updated */
/* version string, resulting */
/* in version 5.6 */
/* */
/**************************************************************************/
#ifndef TX_PORT_H
#define TX_PORT_H
/* Determine if the optional ThreadX user define file should be used. */
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
#endif
/* Define compiler library include files. */
#include <stdlib.h>
#include <string.h>
#include <intrinsics.h>
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif
/* Define ThreadX basic types for this port. */
#define VOID void
typedef char CHAR;
typedef unsigned char UCHAR;
typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef short SHORT;
typedef unsigned short USHORT;
/*enable execution profile*/
#define TX_ENABLE_EXECUTION_CHANGE_NOTIFY
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
#ifndef TX_MAX_PRIORITIES
#define TX_MAX_PRIORITIES 32
#endif
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
thread creation is less than this value, the thread create call will return an error. */
#ifndef TX_MINIMUM_STACK
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
#endif
/* Define the system timer thread's default stack size and priority. These are only applicable
if TX_TIMER_PROCESS_IN_ISR is not defined. */
#ifndef TX_TIMER_THREAD_STACK_SIZE
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
#endif
#ifndef TX_TIMER_THREAD_PRIORITY
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
#endif
/* Define various constants for the ThreadX Cortex-M3 port. */
#define TX_INT_DISABLE 1 /* Disable interrupts */
#define TX_INT_ENABLE 0 /* Enable interrupts */
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
*/
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
#endif
#ifndef TX_TRACE_TIME_MASK
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0)
/* Define the in-line initialization constant so that modules with in-line
initialization capabilities can prevent their initialization from being
a function call. */
#ifdef TX_MISRA_ENABLE
#define TX_DISABLE_INLINE
#else
#define TX_INLINE_INITIALIZATION
#endif
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
define is negated, thereby forcing the stack fill which is necessary for the stack checking
logic. */
#ifndef TX_MISRA_ENABLE
#ifdef TX_ENABLE_STACK_CHECKING
#undef TX_DISABLE_STACK_FILLING
#endif
#endif
/* Define the TX_THREAD control block extensions for this port. The main reason
for the multiple macros is so that backward compatibility can be maintained with
existing ThreadX kernel awareness modules. */
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#else
#define TX_THREAD_EXTENSION_2
#endif
#ifndef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
#define TX_THREAD_EXTENSION_3
#else
#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
unsigned long long tx_thread_execution_time_last_start;
#endif
/* Define the port extensions of the remaining ThreadX objects. */
#define TX_BLOCK_POOL_EXTENSION
#define TX_BYTE_POOL_EXTENSION
#define TX_EVENT_FLAGS_GROUP_EXTENSION
#define TX_MUTEX_EXTENSION
#define TX_QUEUE_EXTENSION
#define TX_SEMAPHORE_EXTENSION
#define TX_TIMER_EXTENSION
/* Define the user extension field of the thread control block. Nothing
additional is needed for this port so it is defined as white space. */
#ifndef TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
tx_thread_shell_entry, and tx_thread_terminate. */
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
/* Define the ThreadX object creation extensions for the remaining objects. */
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
/* Define the ThreadX object deletion extensions for the remaining objects. */
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#else
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#endif
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
prevent early scheduling on Cortex-M parts. */
#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
/* Determine if the ARM architecture has the CLZ instruction. This is available on
architectures v5 and above. If available, redefine the macro for calculating the
lowest bit set. */
#ifndef TX_DISABLE_INLINE
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \
b = (UINT) __CLZ(m); \
b = 31 - b;
#endif
/* Define ThreadX interrupt lockout and restore macros for protection on
access of critical kernel information. The restore interrupt macro must
restore the interrupt posture of the running thread prior to the value
present prior to the disable macro. In most cases, the save area macro
is used to define a local function save area for the disable and restore
macros. */
#ifdef TX_DISABLE_INLINE
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#else
#define TX_INTERRUPT_SAVE_AREA __istate_t interrupt_save;
#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();};
#define TX_RESTORE {__set_interrupt_state(interrupt_save);};
#define _tx_thread_system_return _tx_thread_system_return_inline
static void _tx_thread_system_return_inline(void)
{
__istate_t interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_IPSR() == 0)
{
interrupt_save = __get_interrupt_state();
__enable_interrupt();
__set_interrupt_state(interrupt_save);
}
}
#endif
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
thread. These are no longer needed, but are preserved for backward compatibility only. */
void tx_thread_fpu_enable(void);
void tx_thread_fpu_disable(void);
/* Define the interrupt lockout macros for each ThreadX object. */
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
#define TX_BYTE_POOL_DISABLE TX_DISABLE
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
#define TX_MUTEX_DISABLE TX_DISABLE
#define TX_QUEUE_DISABLE TX_DISABLE
#define TX_SEMAPHORE_DISABLE TX_DISABLE
/* Define the version ID of ThreadX. This may be utilized by the application. */
#ifdef TX_THREAD_INIT
CHAR _tx_version_id[] =
"Copyright (c) 1996-2017 Express Logic Inc. * ThreadX Cortex-M4/IAR Version G5.8.5.6 SN: X-WARE_PLATFORM_STM32F4_DISCOVERY_EVALUATION_VERSION_08-01-2017 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
#else
extern CHAR _tx_version_id[];
#endif
#endif
#endif

View File

@ -0,0 +1,247 @@
Express Logic's ThreadX for EK-TM4C123GXL Evaluation Board (Cortex-M4)
Using the IAR Tools
*** DEMO VERSION ***
0. About This Version
This version of ThreadX is for demonstration purposes only and may not
be used for any product development, either directly or indirectly. In
addition, this demonstration may not be used for any competitive purpose.
1. Installation
ThreadX for EK-TM4C123GXL (Cortex-M4) is pre-installed in the evaluation package.
2. Building the ThreadX run-time Library
This demonstration version contains a pre-built ThreadX library, tx.a. The library is
intended for demonstration purposes only and thus has the following limitations:
10 Threads
10 Timers
10 Event Flag Groups
10 Mutexes
10 Queues
10 Semaphores
10 Block Pool
10 Byte Pool
3. Demonstration System
The ThreadX demonstration is designed to execute on the EK-TM4C123GXL evaluation
board under the IAR Windows-based debugger.
Building the demonstration is easy; simply make the demo_threadx.ewp project
the "active project" in the IAR Embedded Workbench and select the "Make" button.
You should observe the compilation of demo_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file demo_threadx.out is a binary
file that can be downloaded and executed on the EK-TM4C123GXL evaluation board using
the IAR debugger.
4. System Initialization
The entry point in ThreadX for the (Cortex-M4) using IAR tools is at label
__Reset_Handler. This is defined within the EK-TM4C123GXL startup code, namely
the file startup_ewarm.s. From this entry point, the IAR startup code
at __iar_program_start is called. This is where all static and global preset
C variable initialization processing takes place.
The ThreadX tx_initialize_low_level.s file is responsible for setting up
various system data structures, and a periodic timer interrupt source.
The _tx_initialize_low_level function inside of tx_initialize_low_level.s
also determines the first available address for use by the application, which
is supplied as the sole input parameter to your application definition function,
tx_application_define. To accomplish this, a section is created in
tx_initialize_low_level.s called FREE_MEM, which must be located after all
other RAM sections in memory.
5. Register Usage and Stack Frames
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x04 r4
0x08 r5
0x0C r6
0x10 r7
0x14 r8
0x18 r9
0x1C r10 (sl)
0x20 r11
0x24 r0 (Hardware stack starts here!!)
0x28 r1
0x2C r2
0x30 r3
0x34 r12
0x38 lr
0x3C pc
0x40 xPSR
FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x04 s0
0x08 s1
0x0C s2
0x10 s3
0x14 s4
0x18 s5
0x1C s6
0x20 s7
0x24 s8
0x28 s9
0x2C s10
0x30 s11
0x34 s12
0x38 s13
0x3C s14
0x40 s15
0x44 s16
0x48 s17
0x4C s18
0x50 s19
0x54 s20
0x58 s21
0x5C s22
0x60 s23
0x64 s24
0x68 s25
0x6C s26
0x70 s27
0x74 s28
0x78 s29
0x7C s30
0x80 s31
0x84 fpscr
0x88 r4
0x8C r5
0x90 r6
0x94 r7
0x98 r8
0x9C r9
0xA0 r10 (sl)
0xA4 r11
0xA8 r0 (Hardware stack starts here!!)
0xAC r1
0xB0 r2
0xB4 r3
0xB8 r12
0xBC lr
0xC0 pc
0xC4 xPSR
6. Improving Performance
The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make it run faster, you can change the ThreadX library
project to enable various compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
defined.
7. Interrupt Handling
The Cortex-M4 vectors start at the label __vector_table and is defined in cstartup_M.s.
The application may modify the vector area according to its needs.
7.2 Managed Interrupts
From version 5.6 going forward, ISRs for Cortex-M using the IAR tools can be written
completely in C (or assembly language) without any calls to _tx_thread_context_save or
_tx_thread_context_restore. These ISRs are allowed access to the ThreadX API that is
available to ISRs.
ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
void your_C_isr(void)
{
/* ISR processing goes here, including any needed function calls. */
}
ISRs written in assembly language will take the form:
PUBLIC your_assembly_isr
your_assembly_isr:
PUSH {lr}
; ISR processing goes here, including any needed function calls.
POP {lr}
BX lr
Backward compatibility to the previous style assembly ISRs is maintained, which was of
the form:
PUBLIC __legacy_isr_handler
__legacy_isr_handler:
PUSH {lr}
BL _tx_thread_context_save
; /* Do interrupt handler work here */
; /* .... */
B _tx_thread_context_restore
8. IAR Thread-safe Library Support
Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
should have the following line added (if not already in place):
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
The project options "General Options -> Library Configuration" should also have the
"Enable thread support in library" box selected.
9. VFP Support
When applicable, ThreadX for the EK-TM4C123GXL (Cortex-M4) supports lazy VFP support, which
means that applications threads can simply use the VFP and ThreadX automatically maintains
the VFP registers as part of the thread context - no additional setup by the application
is required.
10. Revision History
08/01/2017 Initial ThreadX version for EK-TM4C123GXL (Cortex-M4) using IAR's ARM tools.
Copyright(c) 1996-2017 Express Logic, Inc.
Express Logic, Inc.
11323 West Bernardo Court
San Diego, CA 92127
www.expresslogic.com

View File

@ -1,6 +1,6 @@
/**************************************************************************/
/* */
/* Copyright (c) 1996-2011 by Express Logic Inc. */
/* Copyright (c) 1996-2017 by Express Logic Inc. */
/* */
/* This software is copyrighted by and is the sole property of Express */
/* Logic, Inc. All rights, title, ownership, or other interests */
@ -38,7 +38,7 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/IAR */
/* 5.1 */
/* 5.6 */
/* */
/* AUTHOR */
/* */
@ -66,6 +66,33 @@
/* support, and updated */
/* version string, resulting */
/* in version 5.1 */
/* 04-15-2012 William E. Lamie Modified comment(s), added */
/* FPU enable/disable function */
/* prototypes, and updated */
/* version string, resulting */
/* in version 5.2 */
/* 01-01-2014 William E. Lamie Modified comment(s), added */
/* FPU enable/disable struct */
/* member, and updated */
/* version string, resulting */
/* in version 5.3 */
/* 04-15-2014 William E. Lamie Modified comment(s), and */
/* updated version string, */
/* resulting in version 5.4 */
/* 09-01-2014 William E. Lamie Modified comment(s), and */
/* updated version string, */
/* resulting in version 5.5 */
/* 06-01-2017 William E. Lamie Modified comment(s), added */
/* support for new thread-safe */
/* IAR libraries, removed */
/* unneeded VFP enable flag, */
/* added logic to remove the */
/* need for context */
/* save/restore calls in ISRs, */
/* modified code for MISRA */
/* compliance, and updated */
/* version string, resulting */
/* in version 5.6 */
/* */
/**************************************************************************/
@ -73,14 +100,6 @@
#define TX_PORT_H
/* Define default parameters for the Cortex-M4 build for smaller footprint. */
#define TX_TIMER_PROCESS_IN_ISR
#define TX_DISABLE_PREEMPTION_THRESHOLD
#define TX_DISABLE_NOTIFY_CALLBACKS
#define TX_DISABLE_ERROR_CHECKING
/* Determine if the optional ThreadX user define file should be used. */
#ifdef TX_INCLUDE_USER_DEFINE_FILE
@ -158,9 +177,15 @@ typedef unsigned short USHORT;
*/
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
#endif
#ifndef TX_TRACE_TIME_MASK
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
@ -169,14 +194,18 @@ typedef unsigned short USHORT;
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0)
/* Define the in-line initialization constant so that modules with in-line
initialization capabilities can prevent their initialization from being
a function call. */
#ifdef TX_MISRA_ENABLE
#define TX_DISABLE_INLINE
#else
#define TX_INLINE_INITIALIZATION
#endif
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
@ -185,9 +214,11 @@ typedef unsigned short USHORT;
define is negated, thereby forcing the stack fill which is necessary for the stack checking
logic. */
#ifndef TX_MISRA_ENABLE
#ifdef TX_ENABLE_STACK_CHECKING
#undef TX_DISABLE_STACK_FILLING
#endif
#endif
/* Define the TX_THREAD control block extensions for this port. The main reason
@ -196,11 +227,16 @@ typedef unsigned short USHORT;
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_2
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_3 VOID *tx_thread_iar_tls_pointer;
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#else
#define TX_THREAD_EXTENSION_2
#endif
#ifndef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
#define TX_THREAD_EXTENSION_3
#else
#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
unsigned long long tx_thread_execution_time_last_start;
#endif
@ -228,11 +264,22 @@ typedef unsigned short USHORT;
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
@ -262,13 +309,44 @@ typedef unsigned short USHORT;
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#else
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#endif
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
prevent early scheduling on Cortex-M parts. */
#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
/* Determine if the ARM architecture has the CLZ instruction. This is available on
architectures v5 and above. If available, redefine the macro for calculating the
lowest bit set. */
#ifndef TX_DISABLE_INLINE
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \
b = (UINT) __CLZ(m); \
b = 31 - b;
#endif
/* Define ThreadX interrupt lockout and restore macros for protection on
@ -278,21 +356,16 @@ typedef unsigned short USHORT;
is used to define a local function save area for the disable and restore
macros. */
/* The embedded assembler blocks are design so as to be inlinable by the
armlink linker inlining. This requires them to consist of either a
single 32-bit instruction, or either one or two 16-bit instructions
followed by a "BX lr". Note that to reduce the critical region size, the
16-bit "CPSID i" instruction is preceeded by a 16-bit NOP */
#ifdef TX_DISABLE_INLINE
unsigned int _tx_thread_interrupt_control(unsigned int new_posture);
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
#define TX_INTERRUPT_SAVE_AREA register int interrupt_save;
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#else
@ -300,11 +373,27 @@ unsigned int _tx_thread_interrupt_control(uns
#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();};
#define TX_RESTORE {__set_interrupt_state(interrupt_save);};
#define _tx_thread_system_return _tx_thread_system_return_inline
static void _tx_thread_system_return_inline(void)
{
__istate_t interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_IPSR() == 0)
{
interrupt_save = __get_interrupt_state();
__enable_interrupt();
__set_interrupt_state(interrupt_save);
}
}
#endif
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
thread. */
thread. These are no longer needed, but are preserved for backward compatibility only. */
void tx_thread_fpu_enable(void);
void tx_thread_fpu_disable(void);
@ -324,10 +413,17 @@ void tx_thread_fpu_disable(void);
#ifdef TX_THREAD_INIT
CHAR _tx_version_id[] =
"Copyright (c) 1996-2012 Express Logic Inc. * ThreadX Cortex-M4/IAR Version G5.5.5.1 SN: Evaluation_Only_Version_012012 *";
"Copyright (c) 1996-2017 Express Logic Inc. * ThreadX Cortex-M4/IAR Version G5.8.5.6 SN: X-WARE_PLATFORM_EK-TM4C123GXL_LaunchPad_Evaluation_Version_08-01-2017 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
#else
extern CHAR _tx_version_id[];
#endif
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,227 +0,0 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) 1996-2011 by Express Logic Inc. */
;/* */
;/* This software is copyrighted by and is the sole property of Express */
;/* Logic, Inc. All rights, title, ownership, or other interests */
;/* in the software remain the property of Express Logic, Inc. This */
;/* software may only be used in accordance with the corresponding */
;/* license agreement. Any unauthorized use, duplication, transmission, */
;/* distribution, or disclosure of this software is expressly forbidden. */
;/* */
;/* This Copyright notice may not be removed or modified without prior */
;/* written consent of Express Logic, Inc. */
;/* */
;/* Express Logic, Inc. reserves the right to modify this software */
;/* without notice. */
;/* */
;/* Express Logic, Inc. info@expresslogic.com */
;/* 11423 West Bernardo Court http://www.expresslogic.com */
;/* San Diego, CA 92127 */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Initialize */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;#define TX_SOURCE_CODE
;
;
;/* Include necessary system files. */
;
;#include "tx_api.h"
;#include "tx_initialize.h"
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;
EXTERN _tx_thread_system_stack_ptr
EXTERN _tx_initialize_unused_memory
EXTERN _tx_thread_context_save
EXTERN _tx_thread_context_restore
EXTERN _tx_timer_interrupt
EXTERN __iar_program_start
EXTERN __tx_SVCallHandler
EXTERN __tx_PendSVHandler
EXTERN __tx_vectors
EXTERN __iar_program_start
;
;
SYSTEM_CLOCK EQU 150000000
SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 100) -1)
RSEG FREE_MEM:DATA
PUBLIC __tx_free_memory_start
__tx_free_memory_start
DS32 4
;
;
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_initialize_low_level Cortex-M4/IAR */
;/* 5.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Express Logic, Inc. */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for any low-level processor */
;/* initialization, including setting up interrupt vectors, setting */
;/* up a periodic timer interrupt source, saving the system stack */
;/* pointer for use in ISR processing later, and finding the first */
;/* available RAM memory address for tx_application_define. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* _tx_initialize_kernel_enter ThreadX entry function */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 10-10-2010 William E. Lamie Initial Version 5.0 */
;/* 07-15-2011 William E. Lamie Modified comment(s), */
;/* resulting in version 5.1 */
;/* */
;/**************************************************************************/
;VOID _tx_initialize_low_level(VOID)
;{
PUBLIC _tx_initialize_low_level
_tx_initialize_low_level:
;
; /* Ensure that interrupts are disabled. */
;
CPSID i ; Disable interrupts
;
;
; /* Set base of available memory to end of non-initialised RAM area. */
;
LDR r0, =__tx_free_memory_start ; Get end of non-initialized RAM area
LDR r2, =_tx_initialize_unused_memory ; Build address of unused memory pointer
STR r0, [r2, #0] ; Save first free memory address
;
; /* Enable the cycle count register. */
;
LDR r0, =0xE0001000 ; Build address of DWT register
LDR r1, [r0] ; Pickup the current value
ORR r1, r1, #1 ; Set the CYCCNTENA bit
STR r1, [r0] ; Enable the cycle count register
;
; /* Setup Vector Table Offset Register. */
;
MOV r0, #0xE000E000 ; Build address of NVIC registers
LDR r1, =__tx_vectors ; Pickup address of vector table
STR r1, [r0, #0xD08] ; Set vector table address
;
; /* Set system stack pointer from vector value. */
;
LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer
LDR r1, =__tx_vectors ; Pickup address of vector table
LDR r1, [r1] ; Pickup reset stack pointer
STR r1, [r0] ; Save system stack pointer
;
; /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
;
MOV r0, #0xE000E000 ; Build address of NVIC registers
LDR r1, =SYSTICK_CYCLES
STR r1, [r0, #0x14] ; Setup SysTick Reload Value
MOV r1, #0x7 ; Build SysTick Control Enable Value
STR r1, [r0, #0x10] ; Setup SysTick Control
;
; /* Configure handler priorities. */
;
LDR r1, =0x00000000 ; Rsrv, UsgF, BusF, MemM
STR r1, [r0, #0xD18] ; Setup System Handlers 4-7 Priority Registers
LDR r1, =0xFF000000 ; SVCl, Rsrv, Rsrv, Rsrv
STR r1, [r0, #0xD1C] ; Setup System Handlers 8-11 Priority Registers
; Note: SVC must be lowest priority, which is 0xFF
LDR r1, =0x40FF0000 ; SysT, PnSV, Rsrv, DbgM
STR r1, [r0, #0xD20] ; Setup System Handlers 12-15 Priority Registers
; Note: PnSV must be lowest priority, which is 0xFF
LDR r0, =0xE000EF34 ; Pickup FPCCR
LDR r1, [r0] ;
LDR r2, =0x3FFFFFFF ; Build mask to clear ASPEN and LSPEN
AND r1, r1, r2 ; Clear the ASPEN and LSPEN bits
STR r1, [r0] ; Update FPCCR
;
; /* Return to caller. */
;
BX lr
;}
;
;
PUBLIC __stack_test
__stack_test:
push {r0}
push {r1}
push {r2}
push {r3}
pop {r3}
pop {r2}
pop {r1}
pop {r0}
bx lr
;/* Define shells for each of the unused vectors. */
;
PUBLIC __tx_IntHandler
__tx_IntHandler:
; VOID InterruptHandler (VOID)
; {
PUSH {lr}
BL _tx_thread_context_save
; /* Do interrupt handler work here */
; /* .... */
B _tx_thread_context_restore
; }
PUBLIC __tx_SysTickHandler
__tx_SysTickHandler:
; VOID TimerInterruptHandler (VOID)
; {
;
PUSH {lr}
BL _tx_thread_context_save
MOV r0, #0xE000E000 ; Build address of NVIC registers
LDR r1, [r0, #0x10] ; Clear SysTick interrupt
BL _tx_timer_interrupt
B _tx_thread_context_restore
; }
END

612
3rd_party/threadx/tx_trace.h vendored Normal file
View File

@ -0,0 +1,612 @@
/**************************************************************************/
/* */
/* Copyright (c) 1996-2017 by Express Logic Inc. */
/* */
/* This software is copyrighted by and is the sole property of Express */
/* Logic, Inc. All rights, title, ownership, or other interests */
/* in the software remain the property of Express Logic, Inc. This */
/* software may only be used in accordance with the corresponding */
/* license agreement. Any unauthorized use, duplication, transmission, */
/* distribution, or disclosure of this software is expressly forbidden. */
/* */
/* This Copyright notice may not be removed or modified without prior */
/* written consent of Express Logic, Inc. */
/* */
/* Express Logic, Inc. reserves the right to modify this software */
/* without notice. */
/* */
/* Express Logic, Inc. info@expresslogic.com */
/* 11423 West Bernardo Court www.expresslogic.com */
/* San Diego, CA 92127 */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Trace */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* COMPONENT DEFINITION RELEASE */
/* */
/* tx_trace.h PORTABLE C */
/* 5.8 */
/* AUTHOR */
/* */
/* William E. Lamie, Express Logic, Inc. */
/* */
/* DESCRIPTION */
/* */
/* This file defines the ThreadX trace component, including constants */
/* and structure definitions as well as external references. It is */
/* assumed that tx_api.h and tx_port.h have already been included. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 12-12-2005 William E. Lamie Initial Version 5.0 */
/* 04-02-2007 William E. Lamie Modified comment(s), */
/* resulting in version 5.1 */
/* 12-12-2008 William E. Lamie Modified comment(s), added */
/* new event definitions, */
/* changed types to ensure the */
/* trace has universal format, */
/* optimized event macro, and */
/* added filter logic and new */
/* function prototypes, */
/* resulting in version 5.2 */
/* 07-04-2009 William E. Lamie Modified comment(s), removed */
/* FileX & NetX event IDs since*/
/* they are defined elsewhere, */
/* and corrected priority */
/* assignment in event trace, */
/* resulting in version 5.3 */
/* 12-12-2009 William E. Lamie Modified comment(s), added */
/* defines for default source, */
/* and added logic to insert */
/* the thread's preemption- */
/* threshold along with its */
/* priority, resulting in */
/* version 5.4 */
/* 07-15-2011 William E. Lamie Modified comment(s), and */
/* added variables for object */
/* registry optimizations, */
/* resulting in version 5.5 */
/* 11-01-2012 William E. Lamie Modified comment(s), and */
/* added conditional around */
/* Trace function prototypes, */
/* resulting in version 5.6 */
/* 05-01-2015 William E. Lamie Modified comment(s), and */
/* modified code for MISRA */
/* compliance, resulting in */
/* version 5.7 */
/* 06-01-2017 William E. Lamie Modified comment(s), made */
/* MISRA compatibility changes,*/
/* and utilized macros for */
/* system state and current */
/* thread pointer retrieval, */
/* resulting in version 5.8 */
/* */
/**************************************************************************/
/* Include necessary system files. */
#ifndef TX_TRACE_H
#define TX_TRACE_H
/* Determine if tracing is enabled. If not, simply define the in-line trace
macros to whitespace. */
#ifndef TX_ENABLE_EVENT_TRACE
#define TX_TRACE_INITIALIZE
#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b)
#define TX_TRACE_OBJECT_UNREGISTER(o)
#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,f)
#else
/* Event tracing is enabled. */
/* Ensure that the thread component information is included. */
#include "tx_thread.h"
/* Define trace port-specfic extension to white space if it isn't defined
already. */
#ifndef TX_TRACE_PORT_EXTENSION
#define TX_TRACE_PORT_EXTENSION
#endif
/* Define the default clock source for trace event entry time stamp. The following two item are port specific.
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
*/
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
#endif
#ifndef TX_TRACE_TIME_MASK
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
/* Define the ID showing the event trace buffer is valid. */
#define TX_TRACE_VALID 0x54585442UL
/* ThreadX Trace Description. The ThreadX Trace feature is designed to capture
events in real-time in a circular event buffer. This buffer may be analyzed by other
tools. The high-level format of the Trace structure is:
[Trace Control Header ]
[Trace Object Registry - Entry 0 ]
...
[Trace Object Registry - Entry "n" ]
[Trace Buffer - Entry 0 ]
...
[Trace Buffer - Entry "n" ]
*/
/* Trace Control Header. The Trace Control Header contains information that
defines the format of the Trace Object Registry as well as the location and
current entry of the Trace Buffer itself. The high-level format of the
Trace Control Header is:
Entry Size Description
[Trace ID] 4 This 4-byte field contains the ThreadX Trace
Identification. If the trace buffer is valid, the
contents are 0x54585442 (TXTB). Since it is written as
a 32-bit unsigned word, this value is also used to
determine if the event trace information is in
little or big endian format.
[Timer Valid Mask] 4 Mask of valid bits in the 32-bit time stamp. This
enables use of 32, 24, 16, or event 8-bit timers.
If the time source is 32-bits, the mask is
0xFFFFFFFF. If the time source is 16-bits, the
mask is 0x0000FFFF.
[Trace Base Address] 4 The base address for all trace pointer. Subtracting
the pointer and this address will yield the proper
offset into the trace buffer.
[Trace Object Registry Start Pointer] 4 Pointer to the start of Trace Object Registry
[Reserved] 2 Reserved two bytes - should be 0x0000
[Trace Object Object Name Size] 2 Number of bytes in object name
[Trace Object Registry End Pointer] 4 Pointer to the end of Trace Object Registry
[Trace Buffer Start Pointer] 4 Pointer to the start of the Trace Buffer Area
[Trace Buffer End Pointer] 4 Pointer to the end of the Trace Buffer Area
[Trace Buffer Current Pointer] 4 Pointer to the oldest entry in the Trace Buffer.
This entry will be overwritten on the next event and
incremented to the next event (wrapping to the top
if the buffer end pointer is exceeded).
[Reserved] 4 Reserved 4 bytes, should be 0xAAAAAAAA
[Reserved] 4 Reserved 4 bytes, should be 0xBBBBBBBB
[Reserved] 4 Reserved 4 bytes, should be 0xCCCCCCCC
*/
/* Define the Trace Control Header. */
typedef struct TX_TRACE_HEADER_STRUCT
{
ULONG tx_trace_header_id;
ULONG tx_trace_header_timer_valid_mask;
ULONG tx_trace_header_trace_base_address;
ULONG tx_trace_header_registry_start_pointer;
USHORT tx_trace_header_reserved1;
USHORT tx_trace_header_object_name_size;
ULONG tx_trace_header_registry_end_pointer;
ULONG tx_trace_header_buffer_start_pointer;
ULONG tx_trace_header_buffer_end_pointer;
ULONG tx_trace_header_buffer_current_pointer;
ULONG tx_trace_header_reserved2;
ULONG tx_trace_header_reserved3;
ULONG tx_trace_header_reserved4;
} TX_TRACE_HEADER;
/* Trace Object Registry. The Trace Object Registry is used to map the object pointer in the trace buffer to
the application's name for the object (defined during object creation in ThreadX). */
#ifndef TX_TRACE_OBJECT_REGISTRY_NAME
#define TX_TRACE_OBJECT_REGISTRY_NAME 32
#endif
/* Define the object name types as well as the contents of any additional parameters that might be useful in
trace analysis. */
#define TX_TRACE_OBJECT_TYPE_NOT_VALID ((UCHAR) 0) /* Object is not valid */
#define TX_TRACE_OBJECT_TYPE_THREAD ((UCHAR) 1) /* P1 = stack start address, P2 = stack size */
#define TX_TRACE_OBJECT_TYPE_TIMER ((UCHAR) 2) /* P1 = initial ticks, P2 = reschedule ticks */
#define TX_TRACE_OBJECT_TYPE_QUEUE ((UCHAR) 3) /* P1 = queue size, P2 = message size */
#define TX_TRACE_OBJECT_TYPE_SEMAPHORE ((UCHAR) 4) /* P1 = initial instances */
#define TX_TRACE_OBJECT_TYPE_MUTEX ((UCHAR) 5) /* P1 = priority inheritance flag */
#define TX_TRACE_OBJECT_TYPE_EVENT_FLAGS ((UCHAR) 6) /* none */
#define TX_TRACE_OBJECT_TYPE_BLOCK_POOL ((UCHAR) 7) /* P1 = total blocks, P2 = block size */
#define TX_TRACE_OBJECT_TYPE_BYTE_POOL ((UCHAR) 8) /* P1 = total bytes */
typedef struct TX_TRACE_OBJECT_ENTRY_STRUCT
{
UCHAR tx_trace_object_entry_available; /* TX_TRUE -> available */
UCHAR tx_trace_object_entry_type; /* Types defined above */
UCHAR tx_trace_object_entry_reserved1; /* Should be zero - except for thread */
UCHAR tx_trace_object_entry_reserved2; /* Should be zero - except for thread */
ULONG tx_trace_object_entry_thread_pointer; /* ThreadX object pointer */
ULONG tx_trace_object_entry_param_1; /* Parameter value defined */
ULONG tx_trace_object_entry_param_2; /* according to type above */
UCHAR tx_trace_object_entry_name[TX_TRACE_OBJECT_REGISTRY_NAME]; /* Object name */
} TX_TRACE_OBJECT_ENTRY;
/* Trace Buffer Entry. The Trace Buffer Entry contains information about a particular
event in the system. The high-level format of the Trace Buffer Entry is:
Entry Size Description
[Thread Pointer] 4 This 4-byte field contains the pointer to the
ThreadX thread running that caused the event.
If this field is NULL, the entry hasn't been used
yet. If this field is 0xFFFFFFFF, the event occurred
from within an ISR. If this entry is 0xF0F0F0F0, the
event occurred during initialization.
[Thread Priority or 4 This 4-byte field contains the current thread pointer for interrupt
Current Thread events or the thread preemption-threshold/priority for thread events.
Preemption-Threshold/
Priority]
[Event ID] 4 This 4-byte field contains the Event ID of the event. A value of
0xFFFFFFFF indicates the event is invalid. All events are marked
as invalid during initialization.
[Time Stamp] 4 This 4-byte field contains the time stamp of the event.
[Information Field 1] 4 This 4-byte field contains the first 4-bytes of information
specific to the event.
[Information Field 2] 4 This 4-byte field contains the second 4-bytes of information
specific to the event.
[Information Field 3] 4 This 4-byte field contains the third 4-bytes of information
specific to the event.
[Information Field 4] 4 This 4-byte field contains the fourth 4-bytes of information
specific to the event.
*/
#define TX_TRACE_INVALID_EVENT 0xFFFFFFFFUL
/* Define ThreadX Trace Events, along with a brief description of the additional information fields,
where I1 -> Information Field 1, I2 -> Information Field 2, etc. */
/* Event numbers 0 through 4095 are reserved by Express Logic. Specific event assignments are:
ThreadX events: 1-199
FileX events: 200-299
NetX events: 300-599
USBX events: 600-999
User-defined event numbers start at 4096 and continue through 65535, as defined by the constants
TX_TRACE_USER_EVENT_START and TX_TRACE_USER_EVENT_END, respectively. User events should be based
on these constants in case the user event number assignment is changed in future releases. */
/* Define the basic ThreadX thread scheduling events first. */
#define TX_TRACE_THREAD_RESUME 1 /* I1 = thread ptr, I2 = previous_state, I3 = stack ptr, I4 = next thread */
#define TX_TRACE_THREAD_SUSPEND 2 /* I1 = thread ptr, I2 = new_state, I3 = stack ptr I4 = next thread */
#define TX_TRACE_ISR_ENTER 3 /* I1 = stack_ptr, I2 = ISR number, I3 = system state, I4 = preempt disable */
#define TX_TRACE_ISR_EXIT 4 /* I1 = stack_ptr, I2 = ISR number, I3 = system state, I4 = preempt disable */
#define TX_TRACE_TIME_SLICE 5 /* I1 = next thread ptr, I2 = system state, I3 = preempt disable, I4 = stack*/
#define TX_TRACE_RUNNING 6 /* None */
/* Define the rest of the ThreadX system events. */
#define TX_TRACE_BLOCK_ALLOCATE 10 /* I1 = pool ptr, I2 = memory ptr, I3 = wait option, I4 = remaining blocks */
#define TX_TRACE_BLOCK_POOL_CREATE 11 /* I1 = pool ptr, I2 = pool_start, I3 = total blocks, I4 = block size */
#define TX_TRACE_BLOCK_POOL_DELETE 12 /* I1 = pool ptr, I2 = stack ptr */
#define TX_TRACE_BLOCK_POOL_INFO_GET 13 /* I1 = pool ptr */
#define TX_TRACE_BLOCK_POOL_PERFORMANCE_INFO_GET 14 /* I1 = pool ptr */
#define TX_TRACE_BLOCK_POOL__PERFORMANCE_SYSTEM_INFO_GET 15 /* None */
#define TX_TRACE_BLOCK_POOL_PRIORITIZE 16 /* I1 = pool ptr, I2 = suspended count, I3 = stack ptr */
#define TX_TRACE_BLOCK_RELEASE 17 /* I1 = pool ptr, I2 = memory ptr, I3 = suspended, I4 = stack ptr */
#define TX_TRACE_BYTE_ALLOCATE 20 /* I1 = pool ptr, I2 = memory ptr, I3 = size requested, I4 = wait option */
#define TX_TRACE_BYTE_POOL_CREATE 21 /* I1 = pool ptr, I2 = start ptr, I3 = pool size, I4 = stack ptr */
#define TX_TRACE_BYTE_POOL_DELETE 22 /* I1 = pool ptr, I2 = stack ptr */
#define TX_TRACE_BYTE_POOL_INFO_GET 23 /* I1 = pool ptr */
#define TX_TRACE_BYTE_POOL_PERFORMANCE_INFO_GET 24 /* I1 = pool ptr */
#define TX_TRACE_BYTE_POOL__PERFORMANCE_SYSTEM_INFO_GET 25 /* None */
#define TX_TRACE_BYTE_POOL_PRIORITIZE 26 /* I1 = pool ptr, I2 = suspended count, I3 = stack ptr */
#define TX_TRACE_BYTE_RELEASE 27 /* I1 = pool ptr, I2 = memory ptr, I3 = suspended, I4 = available bytes */
#define TX_TRACE_EVENT_FLAGS_CREATE 30 /* I1 = group ptr, I2 = stack ptr */
#define TX_TRACE_EVENT_FLAGS_DELETE 31 /* I1 = group ptr, I2 = stack ptr */
#define TX_TRACE_EVENT_FLAGS_GET 32 /* I1 = group ptr, I2 = requested flags, I3 = current flags, I4 = get option*/
#define TX_TRACE_EVENT_FLAGS_INFO_GET 33 /* I1 = group ptr */
#define TX_TRACE_EVENT_FLAGS_PERFORMANCE_INFO_GET 34 /* I1 = group ptr */
#define TX_TRACE_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET 35 /* None */
#define TX_TRACE_EVENT_FLAGS_SET 36 /* I1 = group ptr, I2 = flags to set, I3 = set option, I4= suspended count */
#define TX_TRACE_EVENT_FLAGS_SET_NOTIFY 37 /* I1 = group ptr */
#define TX_TRACE_INTERRUPT_CONTROL 40 /* I1 = new interrupt posture, I2 = stack ptr */
#define TX_TRACE_MUTEX_CREATE 50 /* I1 = mutex ptr, I2 = inheritance, I3 = stack ptr */
#define TX_TRACE_MUTEX_DELETE 51 /* I1 = mutex ptr, I2 = stack ptr */
#define TX_TRACE_MUTEX_GET 52 /* I1 = mutex ptr, I2 = wait option, I3 = owning thread, I4 = own count */
#define TX_TRACE_MUTEX_INFO_GET 53 /* I1 = mutex ptr */
#define TX_TRACE_MUTEX_PERFORMANCE_INFO_GET 54 /* I1 = mutex ptr */
#define TX_TRACE_MUTEX_PERFORMANCE_SYSTEM_INFO_GET 55 /* None */
#define TX_TRACE_MUTEX_PRIORITIZE 56 /* I1 = mutex ptr, I2 = suspended count, I3 = stack ptr */
#define TX_TRACE_MUTEX_PUT 57 /* I1 = mutex ptr, I2 = owning thread, I3 = own count, I4 = stack ptr */
#define TX_TRACE_QUEUE_CREATE 60 /* I1 = queue ptr, I2 = message size, I3 = queue start, I4 = queue size */
#define TX_TRACE_QUEUE_DELETE 61 /* I1 = queue ptr, I2 = stack ptr */
#define TX_TRACE_QUEUE_FLUSH 62 /* I1 = queue ptr, I2 = stack ptr */
#define TX_TRACE_QUEUE_FRONT_SEND 63 /* I1 = queue ptr, I2 = source ptr, I3 = wait option, I4 = enqueued */
#define TX_TRACE_QUEUE_INFO_GET 64 /* I1 = queue ptr */
#define TX_TRACE_QUEUE_PERFORMANCE_INFO_GET 65 /* I1 = queue ptr */
#define TX_TRACE_QUEUE_PERFORMANCE_SYSTEM_INFO_GET 66 /* None */
#define TX_TRACE_QUEUE_PRIORITIZE 67 /* I1 = queue ptr, I2 = suspended count, I3 = stack ptr */
#define TX_TRACE_QUEUE_RECEIVE 68 /* I1 = queue ptr, I2 = destination ptr, I3 = wait option, I4 = enqueued */
#define TX_TRACE_QUEUE_SEND 69 /* I1 = queue ptr, I2 = source ptr, I3 = wait option, I4 = enqueued */
#define TX_TRACE_QUEUE_SEND_NOTIFY 70 /* I1 = queue ptr */
#define TX_TRACE_SEMAPHORE_CEILING_PUT 80 /* I1 = semaphore ptr, I2 = current count, I3 = suspended count,I4 =ceiling */
#define TX_TRACE_SEMAPHORE_CREATE 81 /* I1 = semaphore ptr, I2 = initial count, I3 = stack ptr */
#define TX_TRACE_SEMAPHORE_DELETE 82 /* I1 = semaphore ptr, I2 = stack ptr */
#define TX_TRACE_SEMAPHORE_GET 83 /* I1 = semaphore ptr, I2 = wait option, I3 = current count, I4 = stack ptr */
#define TX_TRACE_SEMAPHORE_INFO_GET 84 /* I1 = semaphore ptr */
#define TX_TRACE_SEMAPHORE_PERFORMANCE_INFO_GET 85 /* I1 = semaphore ptr */
#define TX_TRACE_SEMAPHORE__PERFORMANCE_SYSTEM_INFO_GET 86 /* None */
#define TX_TRACE_SEMAPHORE_PRIORITIZE 87 /* I1 = semaphore ptr, I2 = suspended count, I2 = stack ptr */
#define TX_TRACE_SEMAPHORE_PUT 88 /* I1 = semaphore ptr, I2 = current count, I3 = suspended count,I4=stack ptr*/
#define TX_TRACE_SEMAPHORE_PUT_NOTIFY 89 /* I1 = semaphore ptr */
#define TX_TRACE_THREAD_CREATE 100 /* I1 = thread ptr, I2 = priority, I3 = stack ptr, I4 = stack_size */
#define TX_TRACE_THREAD_DELETE 101 /* I1 = thread ptr, I2 = stack ptr */
#define TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY 102 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
#define TX_TRACE_THREAD_IDENTIFY 103 /* None */
#define TX_TRACE_THREAD_INFO_GET 104 /* I1 = thread ptr, I2 = thread state */
#define TX_TRACE_THREAD_PERFORMANCE_INFO_GET 105 /* I1 = thread ptr, I2 = thread state */
#define TX_TRACE_THREAD_PERFORMANCE_SYSTEM_INFO_GET 106 /* None */
#define TX_TRACE_THREAD_PREEMPTION_CHANGE 107 /* I1 = thread ptr, I2 = new threshold, I3 = old threshold, I4 =thread state*/
#define TX_TRACE_THREAD_PRIORITY_CHANGE 108 /* I1 = thread ptr, I2 = new priority, I3 = old priority, I4 = thread state */
#define TX_TRACE_THREAD_RELINQUISH 109 /* I1 = stack ptr, I2 = next thread ptr */
#define TX_TRACE_THREAD_RESET 110 /* I1 = thread ptr, I2 = thread state */
#define TX_TRACE_THREAD_RESUME_API 111 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
#define TX_TRACE_THREAD_SLEEP 112 /* I1 = sleep value, I2 = thread state, I3 = stack ptr */
#define TX_TRACE_THREAD_STACK_ERROR_NOTIFY 113 /* None */
#define TX_TRACE_THREAD_SUSPEND_API 114 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
#define TX_TRACE_THREAD_TERMINATE 115 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
#define TX_TRACE_THREAD_TIME_SLICE_CHANGE 116 /* I1 = thread ptr, I2 = new timeslice, I3 = old timeslice */
#define TX_TRACE_THREAD_WAIT_ABORT 117 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
#define TX_TRACE_TIME_GET 120 /* I1 = current time, I2 = stack ptr */
#define TX_TRACE_TIME_SET 121 /* I1 = new time */
#define TX_TRACE_TIMER_ACTIVATE 122 /* I1 = timer ptr */
#define TX_TRACE_TIMER_CHANGE 123 /* I1 = timer ptr, I2 = initial ticks, I3= reschedule ticks */
#define TX_TRACE_TIMER_CREATE 124 /* I1 = timer ptr, I2 = initial ticks, I3= reschedule ticks, I4 = enable */
#define TX_TRACE_TIMER_DEACTIVATE 125 /* I1 = timer ptr, I2 = stack ptr */
#define TX_TRACE_TIMER_DELETE 126 /* I1 = timer ptr */
#define TX_TRACE_TIMER_INFO_GET 127 /* I1 = timer ptr, I2 = stack ptr */
#define TX_TRACE_TIMER_PERFORMANCE_INFO_GET 128 /* I1 = timer ptr */
#define TX_TRACE_TIMER_PERFORMANCE_SYSTEM_INFO_GET 129 /* None */
/* Define the an Trace Buffer Entry. */
typedef struct TX_TRACE_BUFFER_ENTRY_STRUCT
{
ULONG tx_trace_buffer_entry_thread_pointer;
ULONG tx_trace_buffer_entry_thread_priority;
ULONG tx_trace_buffer_entry_event_id;
ULONG tx_trace_buffer_entry_time_stamp;
#ifdef TX_MISRA_ENABLE
ULONG tx_trace_buffer_entry_info_1;
ULONG tx_trace_buffer_entry_info_2;
ULONG tx_trace_buffer_entry_info_3;
ULONG tx_trace_buffer_entry_info_4;
#else
ULONG tx_trace_buffer_entry_information_field_1;
ULONG tx_trace_buffer_entry_information_field_2;
ULONG tx_trace_buffer_entry_information_field_3;
ULONG tx_trace_buffer_entry_information_field_4;
#endif
} TX_TRACE_BUFFER_ENTRY;
/* Trace management component data declarations follow. */
/* Determine if the initialization function of this component is including
this file. If so, make the data definitions really happen. Otherwise,
make them extern so other functions in the component can access them. */
#ifdef TX_TRACE_INIT
#define TRACE_DECLARE
#else
#define TRACE_DECLARE extern
#endif
/* Define the pointer to the start of the trace buffer control structure. */
TRACE_DECLARE TX_TRACE_HEADER *_tx_trace_header_ptr;
/* Define the pointer to the start of the trace object registry area in the trace buffer. */
TRACE_DECLARE TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_start_ptr;
/* Define the pointer to the end of the trace object registry area in the trace buffer. */
TRACE_DECLARE TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_end_ptr;
/* Define the pointer to the starting entry of the actual trace event area of the trace buffer. */
TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_start_ptr;
/* Define the pointer to the ending entry of the actual trace event area of the trace buffer. */
TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_end_ptr;
/* Define the pointer to the current entry of the actual trace event area of the trace buffer. */
TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_current_ptr;
/* Define the trace event enable bits, where each bit represents a type of event that can be enabled
or disabled dynamically by the application. */
TRACE_DECLARE ULONG _tx_trace_event_enable_bits;
/* Define a counter that is used in environments that don't have a timer source. This counter
is incremented on each use giving each event a unique timestamp. */
TRACE_DECLARE ULONG _tx_trace_simulated_time;
/* Define the function pointer used to call the application when the trace buffer wraps. If NULL,
the application has not registered a callback function. */
TRACE_DECLARE VOID (*_tx_trace_full_notify_function)(VOID *buffer);
/* Define the total number of registry entries. */
TRACE_DECLARE ULONG _tx_trace_total_registry_entries;
/* Define a counter that is used to track the number of available registry entries. */
TRACE_DECLARE ULONG _tx_trace_available_registry_entries;
/* Define an index that represents the start of the registry search. */
TRACE_DECLARE ULONG _tx_trace_registry_search_start;
/* Define the event trace macros that are expanded in-line when event tracing is enabled. */
#ifdef TX_MISRA_ENABLE
#define TX_TRACE_INFO_FIELD_ASSIGNMENT(a,b,c,d) trace_event_ptr -> tx_trace_buffer_entry_info_1 = (ULONG) (a); trace_event_ptr -> tx_trace_buffer_entry_info_2 = (ULONG) (b); trace_event_ptr -> tx_trace_buffer_entry_info_3 = (ULONG) (c); trace_event_ptr -> tx_trace_buffer_entry_info_4 = (ULONG) (d);
#else
#define TX_TRACE_INFO_FIELD_ASSIGNMENT(a,b,c,d) trace_event_ptr -> tx_trace_buffer_entry_information_field_1 = (ULONG) (a); trace_event_ptr -> tx_trace_buffer_entry_information_field_2 = (ULONG) (b); trace_event_ptr -> tx_trace_buffer_entry_information_field_3 = (ULONG) (c); trace_event_ptr -> tx_trace_buffer_entry_information_field_4 = (ULONG) (d);
#endif
#define TX_TRACE_INITIALIZE _tx_trace_initialize();
#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (CHAR *) (n), (ULONG) (a), (ULONG) (b));
#define TX_TRACE_OBJECT_UNREGISTER(o) _tx_trace_object_unregister((VOID *) (o));
#ifndef TX_TRACE_IN_LINE_INSERT
#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) \
{ \
TX_TRACE_BUFFER_ENTRY *trace_event_ptr; \
ULONG trace_system_state; \
ULONG trace_priority; \
TX_THREAD *trace_thread_ptr; \
trace_event_ptr = _tx_trace_buffer_current_ptr; \
if ((trace_event_ptr) && (_tx_trace_event_enable_bits & ((ULONG) (e)))) \
{ \
TX_TRACE_PORT_EXTENSION \
trace_system_state = (ULONG) TX_THREAD_GET_SYSTEM_STATE(); \
TX_THREAD_GET_CURRENT(trace_thread_ptr) \
\
if (trace_system_state == 0) \
{ \
trace_priority = trace_thread_ptr -> tx_thread_priority; \
trace_priority = trace_priority | 0x80000000UL | (trace_thread_ptr -> tx_thread_preempt_threshold << 16); \
} \
else if (trace_system_state < 0xF0F0F0F0UL) \
{ \
trace_priority = (ULONG) trace_thread_ptr; \
trace_thread_ptr = (TX_THREAD *) 0xFFFFFFFFUL; \
} \
else \
{ \
trace_thread_ptr = (TX_THREAD *) 0xF0F0F0F0UL; \
trace_priority = 0; \
} \
trace_event_ptr -> tx_trace_buffer_entry_thread_pointer = (ULONG) trace_thread_ptr; \
trace_event_ptr -> tx_trace_buffer_entry_thread_priority = (ULONG) trace_priority; \
trace_event_ptr -> tx_trace_buffer_entry_event_id = (ULONG) (i); \
trace_event_ptr -> tx_trace_buffer_entry_time_stamp = (ULONG) TX_TRACE_TIME_SOURCE; \
TX_TRACE_INFO_FIELD_ASSIGNMENT((a),(b),(c),(d)) \
trace_event_ptr++; \
if (trace_event_ptr >= _tx_trace_buffer_end_ptr) \
{ \
trace_event_ptr = _tx_trace_buffer_start_ptr; \
_tx_trace_buffer_current_ptr = trace_event_ptr; \
_tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; \
if (_tx_trace_full_notify_function) \
(_tx_trace_full_notify_function)((VOID *) _tx_trace_header_ptr); \
} \
else \
{ \
_tx_trace_buffer_current_ptr = trace_event_ptr; \
_tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; \
} \
} \
}
#endif
#endif
#ifdef TX_SOURCE_CODE
/* Define internal function prototypes of the trace component, only if compiling ThreadX source code. */
VOID _tx_trace_initialize(VOID);
VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2);
VOID _tx_trace_object_unregister(VOID *object_ptr);
#ifdef TX_ENABLE_EVENT_TRACE
/* Check for MISRA compliance requirements. */
#ifdef TX_MISRA_ENABLE
/* Define MISRA-specific routines. */
UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer);
TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer);
TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer);
TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer);
UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer);
#define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_object_to_uchar_pointer_convert((a))
#define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) _tx_misra_uchar_to_object_pointer_convert((a))
#define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) _tx_misra_uchar_to_header_pointer_convert((a))
#define TX_UCHAR_TO_ENTRY_POINTER_CONVERT(a) _tx_misra_uchar_to_entry_pointer_convert((a))
#define TX_ENTRY_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_entry_to_uchar_pointer_convert((a))
#else
#define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
#define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) ((TX_TRACE_OBJECT_ENTRY *) ((VOID *) (a)))
#define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) ((TX_TRACE_HEADER *) ((VOID *) (a)))
#define TX_UCHAR_TO_ENTRY_POINTER_CONVERT(a) ((TX_TRACE_BUFFER_ENTRY *) ((VOID *) (a)))
#define TX_ENTRY_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
#endif
#endif
#endif
#endif

View File

@ -0,0 +1,407 @@
//****************************************************************************
// Product: DPP example, EK-TM4C123GXL board, ThreadX kernel
// Last Updated for Version: 6.3.7
// Date of the Last Update: 2018-12-17
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005-2018 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://www.state-machine.com
// mailto:info@state-machine.com
//****************************************************************************
#include "qpcpp.h"
#include "dpp.h"
#include "bsp.h"
#include "TM4C123GH6PM.h" // the device specific header (TI)
#include "rom.h" // the built-in ROM functions (TI)
#include "sysctl.h" // system control driver (TI)
#include "gpio.h" // GPIO driver (TI)
// add other drivers if necessary...
Q_DEFINE_THIS_FILE
// namespace DPP *************************************************************
namespace DPP {
// Local-scope objects -------------------------------------------------------
#define LED_RED (1U << 1)
#define LED_BLUE (1U << 2)
#define LED_GREEN (1U << 3)
#define BTN_SW1 (1U << 4)
#define BTN_SW2 (1U << 0)
static unsigned l_rnd; // random seed
#ifdef Q_SPY
QP::QSTimeCtr QS_tickTime_;
QP::QSTimeCtr QS_tickPeriod_;
#define UART_BAUD_RATE 115200U
#define UART_FR_TXFE (1U << 7)
#define UART_FR_RXFE (1U << 4)
#define UART_TXFIFO_DEPTH 16U
enum AppRecords { // application-specific trace records
PHILO_STAT = QP::QS_USER,
COMMAND_STAT
};
#endif
extern "C" {
// ISRs used in this project =================================================
#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 UART0_IRQHandler(void) {
uint32_t status = UART0->RIS; // get the raw interrupt status
UART0->ICR = status; // clear the asserted interrupts
while ((UART0->FR & UART_FR_RXFE) == 0) { // while RX FIFO NOT empty
uint32_t b = UART0->DR;
QP::QS::rxPut(b);
}
}
#else
void UART0_IRQHandler(void) {}
#endif
} // extern "C"
// BSP functions =============================================================
void BSP::init(void) {
// NOTE: SystemInit() has been 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));
// enable clock for to the peripherals used by this application...
SYSCTL->RCGCGPIO |= (1U << 5); // enable Run mode for GPIOF
// configure the LEDs and push buttons
GPIOF->DIR |= (LED_RED | LED_GREEN | LED_BLUE); // set as output
GPIOF->DEN |= (LED_RED | LED_GREEN | LED_BLUE); // digital enable
GPIOF->DATA_Bits[LED_RED] = 0U; // turn the LED off
GPIOF->DATA_Bits[LED_GREEN] = 0U; // turn the LED off
GPIOF->DATA_Bits[LED_BLUE] = 0U; // turn the LED off
// configure the Buttons
GPIOF->DIR &= ~(BTN_SW1 | BTN_SW2); // set direction: input
ROM_GPIOPadConfigSet(GPIOF_BASE, (BTN_SW1 | BTN_SW2),
GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
// seed the random number generator
BSP::randomSeed(1234U);
if (!QS_INIT((void *)0)) { // initialize the QS software tracing
Q_ERROR();
}
QS_USR_DICTIONARY(PHILO_STAT);
QS_USR_DICTIONARY(COMMAND_STAT);
}
//............................................................................
void BSP::displayPhilStat(uint8_t n, char const *stat) {
GPIOF->DATA_Bits[LED_RED] = ((stat[0] == 'h') ? 0xFFU : 0U);
GPIOF->DATA_Bits[LED_GREEN] = ((stat[0] == 'e') ? 0xFFU : 0U);
QS_BEGIN(PHILO_STAT, AO_Philo[n]) // application-specific record begin
QS_U8(1, n); // Philosopher number
QS_STR(stat); // Philosopher status
QS_END()
}
//............................................................................
void BSP::displayPaused(uint8_t paused) {
GPIOF->DATA_Bits[LED_RED] = ((paused != 0U) ? LED_RED : 0U);
}
//............................................................................
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
// Some flating point code is to exercise the VFP...
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)
*/
uint32_t 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;
}
} // namespace DPP
// namespace QP **************************************************************
namespace QP {
static TX_TIMER l_tick_timer; // ThreadX timer to call QF::tickX_()
#ifdef Q_SPY
// ThreadX thread and thread function for QS output, see NOTE1
static TX_THREAD l_qs_output_thread;
static void qs_thread_function(ULONG thread_input);
static ULONG qs_thread_stkSto[64];
#endif
// QF callbacks ==============================================================
void QF::onStartup(void) {
//
// NOTE:
// This application uses the ThreadX timer to periodically call
// the QF_tickX_(0) function. Here, only the clock tick rate of 0
// is used, but other timers can be used to call QF_tickX_() for
// other clock tick rates, if needed.
//
// The choice of a ThreadX timer is not the only option. Applications
// might choose to call QF_tickX_() directly from timer interrupts
// or from active object(s).
//
Q_ALLEGE(tx_timer_create(&l_tick_timer, // ThreadX timer object
const_cast<CHAR *>("QF_TICK"), // name of the timer
(VOID (*)(ULONG))&QP::QF::tickX_, // expiration fun
0U, // expiration function input (tick rate)
1U, // initial ticks
1U, // reschedule ticks
TX_AUTO_ACTIVATE) // automatically activate timer
== TX_SUCCESS);
#ifdef Q_SPY
NVIC_EnableIRQ(UART0_IRQn); // UART0 interrupt used for QS-RX
// start a ThreadX timer to perform QS output. See NOTE1...
Q_ALLEGE(tx_thread_create(&l_qs_output_thread, // thread control block
const_cast<CHAR *>("QS_TX"), // thread name
&qs_thread_function, // thread function
0LU, // thread input (unsued)
qs_thread_stkSto, // stack start
sizeof(qs_thread_stkSto), // stack size in bytes
TX_MAX_PRIORITIES - 1U, // ThreadX priority (lowest possible)
TX_MAX_PRIORITIES - 1U, // preemption threshold disabled
TX_NO_TIME_SLICE,
TX_AUTO_START)
== TX_SUCCESS);
#endif // Q_SPY
}
//............................................................................
void QF::onCleanup(void) {
}
//............................................................................
extern "C" void Q_onAssert(char const *module, int loc) {
//
// NOTE: add here your application-specific error handling
//
(void)module;
(void)loc;
QS_ASSERTION(module, loc, static_cast<uint32_t>(10000U));
#ifndef NDEBUG
/* for debugging, hang on in an endless loop toggling the RED LED... */
while (GPIOF->DATA_Bits[BTN_SW1] != 0) {
GPIOF->DATA = LED_RED;
GPIOF->DATA = 0U;
}
#endif
NVIC_SystemReset();
}
// QS callbacks ==============================================================
#ifdef Q_SPY
//............................................................................
static void qs_thread_function(ULONG /*thread_input*/) { // see NOTE1
for (;;) {
QS::rxParse(); // parse all the received bytes
if ((UART0->FR & UART_FR_TXFE) != 0U) { // TX done?
uint16_t fifo = UART_TXFIFO_DEPTH; // max bytes we can accept
uint8_t const *block;
QF_CRIT_STAT_TYPE intStat;
QF_CRIT_ENTRY(intStat);
block = QS::getBlock(&fifo); // try to get next block to transmit
QF_CRIT_EXIT(intStat);
while (fifo-- != 0U) { // any bytes in the block?
UART0->DR = *block++; // put into the FIFO
}
}
// no blocking in this thread; see NOTE1
}
}
//............................................................................
bool QS::onStartup(void const *arg) {
static uint8_t qsTxBuf[2*1024]; // buffer for QS transmit channel
static uint8_t qsRxBuf[100]; // buffer for QS receive channel
uint32_t tmp;
initBuf(qsTxBuf, sizeof(qsTxBuf));
rxInitBuf(qsRxBuf, sizeof(qsRxBuf));
// enable clock for UART0 and GPIOA (used by UART0 pins)
SYSCTL->RCGCUART |= (1U << 0); // enable Run mode for UART0
SYSCTL->RCGCGPIO |= (1U << 0); // enable Run mode for GPIOA
// configure UART0 pins for UART operation
tmp = (1U << 0) | (1U << 1);
GPIOA->DIR &= ~tmp;
GPIOA->SLR &= ~tmp;
GPIOA->ODR &= ~tmp;
GPIOA->PUR &= ~tmp;
GPIOA->PDR &= ~tmp;
GPIOA->AMSEL &= ~tmp; // disable analog function on the pins
GPIOA->AFSEL |= tmp; // enable ALT function on the pins
GPIOA->DEN |= tmp; // enable digital I/O on the pins
GPIOA->PCTL &= ~0x00U;
GPIOA->PCTL |= 0x11U;
// configure the UART for the desired baud rate, 8-N-1 operation
tmp = (((SystemCoreClock * 8U) / UART_BAUD_RATE) + 1U) / 2U;
UART0->IBRD = tmp / 64U;
UART0->FBRD = tmp % 64U;
UART0->LCRH = (0x3U << 5); // configure 8-N-1 operation
UART0->LCRH |= (0x1U << 4); // enable FIFOs
UART0->CTL = (1U << 0) // UART enable
| (1U << 8) // UART TX enable
| (1U << 9); // UART RX enable
// configure UART interrupts (for the RX channel)
UART0->IM |= (1U << 4) | (1U << 6); // enable RX and RX-TO interrupt
UART0->IFLS |= (0x2U << 2); // interrupt on RX FIFO half-full
// NOTE: do not enable the UART0 interrupt yet. Wait till QF_onStartup()
DPP::QS_tickPeriod_ = SystemCoreClock / DPP::BSP::TICKS_PER_SEC;
DPP::QS_tickTime_ = DPP::QS_tickPeriod_; // to start the timestamp at zero
// setup the QS filters...
QS_FILTER_ON(QS_ALL_RECORDS);
QS_FILTER_OFF(QS_QF_TICK);
return true; // return success
}
//............................................................................
void QS::onCleanup(void) {
}
//............................................................................
QSTimeCtr QS::onGetTime(void) { // NOTE: invoked with interrupts DISABLED
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0U) { // not set?
return DPP::QS_tickTime_ - static_cast<QSTimeCtr>(SysTick->VAL);
}
else { // the rollover occured, but the SysTick_ISR did not run yet
return DPP::QS_tickTime_ + DPP::QS_tickPeriod_
- static_cast<QSTimeCtr>(SysTick->VAL);
}
}
//............................................................................
void QS::onFlush(void) {
uint16_t fifo = UART_TXFIFO_DEPTH; // Tx FIFO depth
uint8_t const *block;
while ((block = getBlock(&fifo)) != static_cast<uint8_t *>(0)) {
// busy-wait until TX FIFO empty
while ((UART0->FR & UART_FR_TXFE) == 0U) {
}
while (fifo-- != 0U) { // any bytes in the block?
UART0->DR = *block++; // put into the TX FIFO
}
fifo = UART_TXFIFO_DEPTH; // re-load the Tx FIFO depth
}
}
//............................................................................
//! callback function to reset the target (to be implemented in the BSP)
void QS::onReset(void) {
NVIC_SystemReset();
}
//............................................................................
//! callback function to execute a user command
extern "C" void assert_failed(char const *module, int loc); // prototype
extern void QS_target_info_(uint8_t isReset); // prototype
void QS::onCommand(uint8_t cmdId, uint32_t param1,
uint32_t param2, uint32_t param3)
{
(void)cmdId;
(void)param1;
(void)param2;
(void)param3;
// application-specific record
QS_BEGIN(DPP::COMMAND_STAT, static_cast<void *>(0))
QS_U8(2, cmdId);
QS_U32(8, param1);
QS_U32(8, param2);
QS_U32(8, param3);
QS_END()
switch (cmdId) {
case 1: {
QS_target_info_(static_cast<uint8_t>(0xFF)); // test a reset
break;
}
case 10: {
assert_failed("QS_onCommand", 10); // for testing assertions
break;
}
}
}
#endif // Q_SPY
//----------------------------------------------------------------------------
} // namespace QP
//****************************************************************************
// NOTE1:
// This application uses the ThreadX thread of the lowest priority to perform
// the QS data output to the host. This is not the only choice available, and
// other applications might choose to peform the QS output some other way.
//
// The lowest-priority thread does not block, so in effect, it becomes the
// idle loop. This presents no problems to ThreadX - its idle task in the
// scheduler does not need to run.
//

View File

@ -0,0 +1,61 @@
//****************************************************************************
// 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
namespace DPP {
class BSP {
public:
enum { TICKS_PER_SEC = 100 };
static void init(void);
static void displayPaused(uint8_t const paused);
static void displayPhilStat(uint8_t const n, char_t const *stat);
static void terminate(int16_t const result);
static void randomSeed(uint32_t const seed); // random seed
static uint32_t random(void); // pseudo-random generator
// for testing...
static void wait4SW1(void);
static void ledOn(void);
static void ledOff(void);
};
extern QP::QActive *the_Ticker0;
} // namespace DPP
#endif // bsp_h

View File

@ -0,0 +1,86 @@
//$file${.::dpp.h} ###########################################################
//
// Model: dpp.qm
// File: ${.::dpp.h}
//
// This code has been generated by QM 4.3.0 (https://www.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.
//
//$endhead${.::dpp.h} ########################################################
#ifndef dpp_h
#define dpp_h
namespace DPP {
enum DPPSignals {
EAT_SIG = QP::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 the application
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
MAX_SIG // the last signal
};
} // namespace DPP
//$declare${Events::TableEvt} ################################################
namespace DPP {
//${Events::TableEvt} ........................................................
class TableEvt : public QP::QEvt {
public:
uint8_t philoNum;
};
} // namespace DPP
//$enddecl${Events::TableEvt} ################################################
// number of philosophers
#define N_PHILO ((uint8_t)5)
//$declare${AOs::AO_Philo[N_PHILO]} ##########################################
namespace DPP {
extern QP::QActive * const AO_Philo[N_PHILO];
} // namespace DPP
//$enddecl${AOs::AO_Philo[N_PHILO]} ##########################################
//$declare${AOs::AO_Table} ###################################################
namespace DPP {
extern QP::QActive * const AO_Table;
} // namespace DPP
//$enddecl${AOs::AO_Table} ###################################################
#ifdef qxk_h
//$declare${AOs::XT_Test1} ###################################################
namespace DPP {
extern QP::QXThread * const XT_Test1;
} // namespace DPP
//$enddecl${AOs::XT_Test1} ###################################################
//$declare${AOs::XT_Test2} ###################################################
namespace DPP {
extern QP::QXThread * const XT_Test2;
} // namespace DPP
//$enddecl${AOs::XT_Test2} ###################################################
#endif // qxk_h
#endif // dpp_h

View File

@ -0,0 +1,498 @@
<?xml version="1.0" encoding="UTF-8"?>
<model version="4.3.0" links="1">
<documentation>Dining Philosopher Problem example with MSM state machines</documentation>
<!--${qpcpp}-->
<framework name="qpcpp"/>
<!--${Events}-->
<package name="Events" stereotype="0x01" namespace="DPP::">
<!--${Events::TableEvt}-->
<class name="TableEvt" superclass="qpcpp::QEvt">
<!--${Events::TableEvt::philoNum}-->
<attribute name="philoNum" type="uint8_t" visibility="0x00" properties="0x00"/>
</class>
</package>
<!--${AOs}-->
<package name="AOs" stereotype="0x02" namespace="DPP::">
<!--${AOs::Philo}-->
<class name="Philo" superclass="qpcpp::QActive">
<!--${AOs::Philo::m_timeEvt}-->
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
<!--${AOs::Philo::Philo}-->
<operation name="Philo" type="" visibility="0x00" properties="0x00">
<code> : QActive(Q_STATE_CAST(&amp;Philo::initial)),
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
</operation>
<!--${AOs::Philo::SM}-->
<statechart>
<!--${AOs::Philo::SM::initial}-->
<initial target="../1">
<action>static bool registered = false; // starts off with 0, per C-standard
(void)e; // suppress the compiler warning about unused parameter
me-&gt;subscribe(EAT_SIG);
me-&gt;subscribe(TEST_SIG);
if (!registered) {
registered = true;
QS_OBJ_DICTIONARY(&amp;l_philo[0].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[1].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[2].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[3].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[4].m_timeEvt);
QS_FUN_DICTIONARY(&amp;initial);
QS_FUN_DICTIONARY(&amp;thinking);
QS_FUN_DICTIONARY(&amp;hungry);
QS_FUN_DICTIONARY(&amp;eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos</action>
<initial_glyph conn="2,3,5,1,20,5,-3">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<!--${AOs::Philo::SM::thinking}-->
<state name="thinking">
<entry>me-&gt;m_timeEvt.armX(think_time(), 0U);</entry>
<exit>(void)me-&gt;m_timeEvt.disarm();</exit>
<!--${AOs::Philo::SM::thinking::TIMEOUT}-->
<tran trig="TIMEOUT" target="../../2">
<tran_glyph conn="2,13,3,1,20,12,-3">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::thinking::EAT, DONE}-->
<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,16,3,-1,13">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::thinking::TEST}-->
<tran trig="TEST">
<tran_glyph conn="2,19,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,5,2"/>
</state_glyph>
</state>
<!--${AOs::Philo::SM::hungry}-->
<state name="hungry">
<entry>TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
pe-&gt;philoNum = PHILO_ID(me);
AO_Table-&gt;POST(pe, me);</entry>
<!--${AOs::Philo::SM::hungry::EAT}-->
<tran trig="EAT">
<!--${AOs::Philo::SM::hungry::EAT::[Q_EVT_CAST(TableEvt)->philoNum=~}-->
<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>
<!--${AOs::Philo::SM::hungry::DONE}-->
<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>
<!--${AOs::Philo::SM::eating}-->
<state name="eating">
<entry>me-&gt;m_timeEvt.armX(eat_time(), 0U);</entry>
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe-&gt;philoNum = PHILO_ID(me);
QP::QF::PUBLISH(pe, me);
(void)me-&gt;m_timeEvt.disarm();</exit>
<!--${AOs::Philo::SM::eating::TIMEOUT}-->
<tran trig="TIMEOUT" target="../../1">
<tran_glyph conn="2,51,3,1,22,-41,-5">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::eating::EAT, DONE}-->
<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="36,61"/>
</statechart>
</class>
<!--${AOs::Table}-->
<class name="Table" superclass="qpcpp::QActive">
<!--${AOs::Table::m_fork[N_PHILO]}-->
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
<!--${AOs::Table::m_isHungry[N_PHILO]}-->
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
<!--${AOs::Table::Table}-->
<operation name="Table" type="" visibility="0x00" properties="0x00">
<code> : QActive(Q_STATE_CAST(&amp;Table::initial))
for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
m_fork[n] = FREE;
m_isHungry[n] = false;
}</code>
</operation>
<!--${AOs::Table::SM}-->
<statechart properties="QS_FUN_DICT">
<!--${AOs::Table::SM::initial}-->
<initial target="../1/2">
<action>(void)e; // suppress the compiler warning about unused parameter
me-&gt;subscribe(DONE_SIG);
me-&gt;subscribe(PAUSE_SIG);
me-&gt;subscribe(SERVE_SIG);
me-&gt;subscribe(TEST_SIG);
for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
me-&gt;m_fork[n] = FREE;
me-&gt;m_isHungry[n] = false;
BSP::displayPhilStat(n, THINKING);
}
// global signals...
QS_SIG_DICTIONARY(DONE_SIG, (void *)0);
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);
// signals just for this AO...
QS_SIG_DICTIONARY(HUNGRY_SIG, me);</action>
<initial_glyph conn="3,3,5,1,45,18,-10">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<!--${AOs::Table::SM::active}-->
<state name="active">
<!--${AOs::Table::SM::active::TEST}-->
<tran trig="TEST">
<tran_glyph conn="2,11,3,-1,14">
<action box="0,-2,11,4"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::EAT}-->
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="2,15,3,-1,14">
<action box="0,-2,10,4"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving}-->
<state name="serving">
<entry brief="give pending permitions to eat">for (uint8_t n = 0U; n &lt; N_PHILO; ++n) { // give permissions to eat...
if (me-&gt;m_isHungry[n]
&amp;&amp; (me-&gt;m_fork[LEFT(n)] == FREE)
&amp;&amp; (me-&gt;m_fork[n] == FREE))
{
me-&gt;m_fork[LEFT(n)] = USED;
me-&gt;m_fork[n] = USED;
TableEvt *te = Q_NEW(TableEvt, EAT_SIG);
te-&gt;philoNum = n;
QP::QF::PUBLISH(te, me);
me-&gt;m_isHungry[n] = false;
BSP::displayPhilStat(n, EATING);
}
}</entry>
<!--${AOs::Table::SM::active::serving::HUNGRY}-->
<tran trig="HUNGRY">
<action>uint8_t 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;m_isHungry[n]));
BSP::displayPhilStat(n, HUNGRY);
uint8_t m = LEFT(n);</action>
<!--${AOs::Table::SM::active::serving::HUNGRY::[bothfree]}-->
<choice>
<guard brief="both free">(me-&gt;m_fork[m] == FREE) &amp;&amp; (me-&gt;m_fork[n] == FREE)</guard>
<action>me-&gt;m_fork[m] = USED;
me-&gt;m_fork[n] = USED;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = n;
QP::QF::PUBLISH(pe, me);
BSP::displayPhilStat(n, EATING);</action>
<choice_glyph conn="19,26,5,-1,10">
<action box="1,0,10,2"/>
</choice_glyph>
</choice>
<!--${AOs::Table::SM::active::serving::HUNGRY::[else]}-->
<choice>
<guard>else</guard>
<action>me-&gt;m_isHungry[n] = true;</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>
<!--${AOs::Table::SM::active::serving::DONE}-->
<tran trig="DONE">
<action>uint8_t 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;m_isHungry[n]));
BSP::displayPhilStat(n, THINKING);
uint8_t m = LEFT(n);
// both forks of Phil[n] must be used
Q_ASSERT((me-&gt;m_fork[n] == USED) &amp;&amp; (me-&gt;m_fork[m] == USED));
me-&gt;m_fork[m] = FREE;
me-&gt;m_fork[n] = FREE;
m = RIGHT(n); // check the right neighbor
if (me-&gt;m_isHungry[m] &amp;&amp; (me-&gt;m_fork[m] == FREE)) {
me-&gt;m_fork[n] = USED;
me-&gt;m_fork[m] = USED;
me-&gt;m_isHungry[m] = false;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = m;
QP::QF::PUBLISH(pe, me);
BSP::displayPhilStat(m, EATING);
}
m = LEFT(n); // check the left neighbor
n = LEFT(m); // left fork of the left neighbor
if (me-&gt;m_isHungry[m] &amp;&amp; (me-&gt;m_fork[n] == FREE)) {
me-&gt;m_fork[m] = USED;
me-&gt;m_fork[n] = USED;
me-&gt;m_isHungry[m] = false;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe-&gt;philoNum = m;
QP::QF::PUBLISH(pe, me);
BSP::displayPhilStat(m, EATING);
}</action>
<tran_glyph conn="4,34,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving::EAT}-->
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="4,37,3,-1,15">
<action box="0,-2,12,4"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving::PAUSE}-->
<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>
<!--${AOs::Table::SM::active::paused}-->
<state name="paused">
<entry>BSP::displayPaused(1U);</entry>
<exit>BSP::displayPaused(0U);</exit>
<!--${AOs::Table::SM::active::paused::SERVE}-->
<tran trig="SERVE" target="../../2">
<tran_glyph conn="4,57,3,1,39,-29,-5">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::paused::HUNGRY}-->
<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;m_isHungry[n]));
me-&gt;m_isHungry[n] = true;
BSP::displayPhilStat(n, HUNGRY);</action>
<tran_glyph conn="4,60,3,-1,15">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::paused::DONE}-->
<tran trig="DONE">
<action>uint8_t 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;m_isHungry[n]));
BSP::displayPhilStat(n, THINKING);
uint8_t m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me-&gt;m_fork[n] == USED) &amp;&amp; (me-&gt;m_fork[m] == USED));
me-&gt;m_fork[m] = FREE;
me-&gt;m_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,44,62"/>
</state>
<state_diagram size="50,69"/>
</statechart>
</class>
<!--${AOs::AO_Philo[N_PHILO]}-->
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
<!--${AOs::AO_Table}-->
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
<!--${AOs::XT_Test1}-->
<attribute name="XT_Test1" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
<!--${AOs::XT_Test2}-->
<attribute name="XT_Test2" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
</package>
<!--${.}-->
<directory name=".">
<!--${.::dpp.h}-->
<file name="dpp.h">
<text>#ifndef dpp_h
#define dpp_h
namespace DPP {
enum DPPSignals {
EAT_SIG = QP::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 the application
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
MAX_SIG // the last signal
};
} // namespace DPP
$declare(Events::TableEvt)
// number of philosophers
#define N_PHILO ((uint8_t)5)
$declare(AOs::AO_Philo[N_PHILO])
$declare(AOs::AO_Table)
#ifdef qxk_h
$declare(AOs::XT_Test1)
$declare(AOs::XT_Test2)
#endif // qxk_h
#endif // dpp_h</text>
</file>
<!--${.::philo.cpp}-->
<file name="philo.cpp">
<text>#include &quot;qpcpp.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
Q_DEFINE_THIS_FILE
// Active object class -------------------------------------------------------
$declare(AOs::Philo)
namespace DPP {
// Local objects -------------------------------------------------------------
static Philo l_philo[N_PHILO]; // storage for all Philos
// helper function to provide a randomized think time for Philos
inline QP::QTimeEvtCtr think_time() {
return static_cast&lt;QP::QTimeEvtCtr&gt;((BSP::random() % BSP::TICKS_PER_SEC)
+ (BSP::TICKS_PER_SEC/2U));
}
// helper function to provide a randomized eat time for Philos
inline QP::QTimeEvtCtr eat_time() {
return static_cast&lt;QP::QTimeEvtCtr&gt;((BSP::random() % BSP::TICKS_PER_SEC)
+ BSP::TICKS_PER_SEC);
}
// helper function to provide the ID of Philo &quot;me&quot;
inline uint8_t PHILO_ID(Philo const * const me) {
return static_cast&lt;uint8_t&gt;(me - l_philo);
}
enum InternalSignals { // internal signals
TIMEOUT_SIG = MAX_SIG
};
// Global objects ------------------------------------------------------------
QP::QActive * const AO_Philo[N_PHILO] = { // &quot;opaque&quot; pointers to Philo AO
&amp;l_philo[0],
&amp;l_philo[1],
&amp;l_philo[2],
&amp;l_philo[3],
&amp;l_philo[4]
};
} // namespace DPP
// Philo definition ----------------------------------------------------------
$define(AOs::Philo)</text>
</file>
<!--${.::table.cpp}-->
<file name="table.cpp">
<text>#include &quot;qpcpp.h&quot;
#include &quot;dpp.h&quot;
#include &quot;bsp.h&quot;
Q_DEFINE_THIS_FILE
// Active object class -------------------------------------------------------
$declare(AOs::Table)
namespace DPP {
// helper function to provide the RIGHT neighbour of a Philo[n]
inline uint8_t RIGHT(uint8_t const n) {
return static_cast&lt;uint8_t&gt;((n + (N_PHILO - 1U)) % N_PHILO);
}
// helper function to provide the LEFT neighbour of a Philo[n]
inline uint8_t LEFT(uint8_t const n) {
return static_cast&lt;uint8_t&gt;((n + 1U) % N_PHILO);
}
static uint8_t const FREE = static_cast&lt;uint8_t&gt;(0);
static uint8_t const USED = static_cast&lt;uint8_t&gt;(1);
static char_t const * const THINKING = &amp;&quot;thinking&quot;[0];
static char_t const * const HUNGRY = &amp;&quot;hungry &quot;[0];
static char_t const * const EATING = &amp;&quot;eating &quot;[0];
// Local objects -------------------------------------------------------------
static Table l_table; // the single instance of the Table active object
// Global-scope objects ------------------------------------------------------
QP::QActive * const AO_Table = &amp;l_table; // &quot;opaque&quot; AO pointer
} // namespace DPP
//............................................................................
$define(AOs::Table)</text>
</file>
</directory>
</model>

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.ewp</path>
</project>
<batchBuild/>
</workspace>

View File

@ -0,0 +1,29 @@
/*###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__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x0003FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20007FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 1024;
define symbol __ICFEDIT_size_heap__ = 0;
/**** End of ICF editor section. ###ICF###*/
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 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 at start of RAM_region {block CSTACK };
place in RAM_region { readwrite, block HEAP };

View File

@ -0,0 +1,91 @@
//////////////////////////////////////////////////////////////////////////////
// Product: DPP example for ThreadX
// Last updated for version 6.3.7
// Last updated on 2018-12-17
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// Copyright (C) 2005-2018 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://www.state-machine.com
// mailto:info@state-machine.com
//////////////////////////////////////////////////////////////////////////////
#include "qpcpp.h"
#include "dpp.h"
#include "bsp.h"
// Local-scope objects -------------------------------------------------------
static QP::QEvt const *l_tableQueueSto[N_PHILO];
static QP::QEvt const *l_philoQueueSto[N_PHILO][N_PHILO];
static QP::QSubscrList l_subscrSto[DPP::MAX_PUB_SIG];
static union SmallEvents {
void *e0; // minimum event size
uint8_t e1[sizeof(DPP::TableEvt)];
// ... other event types to go into this pool
} l_smlPoolSto[2*N_PHILO + 10]; // storage for the small event pool
static ULONG l_philoStk[N_PHILO][256]; // stacks for the Philosophers
static ULONG l_tableStk[256]; // stack for the Table
//............................................................................
int main() {
DPP::BSP::init(); // initialize the Board Support Package
tx_kernel_enter(); // transfet control to the ThreadX RTOS
return 0; // tx_kernel_enter() does not return
}
//............................................................................
void tx_application_define(void * /*first_unused_memory*/) {
// initialize the framework and the underlying RT kernel...
QP::QF::init();
// init publish-subscribe
QP::QF::psInit(l_subscrSto, Q_DIM(l_subscrSto));
// initialize event pools...
QP::QF::poolInit(l_smlPoolSto, sizeof(l_smlPoolSto),
sizeof(l_smlPoolSto[0]));
QS_OBJ_DICTIONARY(l_smlPoolSto);
QS_OBJ_DICTIONARY(l_tableQueueSto);
QS_OBJ_DICTIONARY(l_philoQueueSto[0]);
QS_OBJ_DICTIONARY(l_philoQueueSto[1]);
QS_OBJ_DICTIONARY(l_philoQueueSto[2]);
QS_OBJ_DICTIONARY(l_philoQueueSto[3]);
QS_OBJ_DICTIONARY(l_philoQueueSto[4]);
// start the active objects...
for (uint8_t n = 0; n < N_PHILO; ++n) {
DPP::AO_Philo[n]->start(
static_cast<uint_fast8_t>(n + 1),
l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),
l_philoStk[n], sizeof(l_philoStk[n]));
}
DPP::AO_Table->start(
static_cast<uint_fast8_t>(N_PHILO + 1),
l_tableQueueSto, Q_DIM(l_tableQueueSto),
l_tableStk, sizeof(l_tableStk));
(void)QP::QF::run(); // run the QF application
}

View File

@ -0,0 +1,246 @@
//$file${.::philo.cpp} #######################################################
//
// Model: dpp.qm
// File: ${.::philo.cpp}
//
// This code has been generated by QM 4.3.0 (https://www.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.
//
//$endhead${.::philo.cpp} ####################################################
#include "qpcpp.h"
#include "dpp.h"
#include "bsp.h"
Q_DEFINE_THIS_FILE
// Active object class -------------------------------------------------------
//$declare${AOs::Philo} ######################################################
namespace DPP {
//${AOs::Philo} ..............................................................
class Philo : public QP::QActive {
private:
QP::QTimeEvt m_timeEvt;
public:
Philo();
protected:
static QP::QState initial(Philo * const me, QP::QEvt const * const e);
static QP::QState thinking(Philo * const me, QP::QEvt const * const e);
static QP::QState hungry(Philo * const me, QP::QEvt const * const e);
static QP::QState eating(Philo * const me, QP::QEvt const * const e);
};
} // namespace DPP
//$enddecl${AOs::Philo} ######################################################
namespace DPP {
// Local objects -------------------------------------------------------------
static Philo l_philo[N_PHILO]; // storage for all Philos
// helper function to provide a randomized think time for Philos
inline QP::QTimeEvtCtr think_time() {
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
+ (BSP::TICKS_PER_SEC/2U));
}
// helper function to provide a randomized eat time for Philos
inline QP::QTimeEvtCtr eat_time() {
return static_cast<QP::QTimeEvtCtr>((BSP::random() % BSP::TICKS_PER_SEC)
+ BSP::TICKS_PER_SEC);
}
// helper function to provide the ID of Philo "me"
inline uint8_t PHILO_ID(Philo const * const me) {
return static_cast<uint8_t>(me - l_philo);
}
enum InternalSignals { // internal signals
TIMEOUT_SIG = MAX_SIG
};
// Global objects ------------------------------------------------------------
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
&l_philo[0],
&l_philo[1],
&l_philo[2],
&l_philo[3],
&l_philo[4]
};
} // namespace DPP
// Philo definition ----------------------------------------------------------
// Check for the minimum required QP version
#if (QP_VERSION < 630U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
#error qpcpp version 6.3.0 or higher required
#endif
//$define${AOs::Philo} #######################################################
namespace DPP {
//${AOs::Philo} ..............................................................
//${AOs::Philo::Philo} .......................................................
Philo::Philo()
: QActive(Q_STATE_CAST(&Philo::initial)),
m_timeEvt(this, TIMEOUT_SIG, 0U)
{}
//${AOs::Philo::SM} ..........................................................
QP::QState Philo::initial(Philo * const me, QP::QEvt const * const e) {
//${AOs::Philo::SM::initial}
static bool registered = false; // starts off with 0, per C-standard
(void)e; // suppress the compiler warning about unused parameter
me->subscribe(EAT_SIG);
me->subscribe(TEST_SIG);
if (!registered) {
registered = true;
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
QS_FUN_DICTIONARY(&initial);
QS_FUN_DICTIONARY(&thinking);
QS_FUN_DICTIONARY(&hungry);
QS_FUN_DICTIONARY(&eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos
return Q_TRAN(&thinking);
}
//${AOs::Philo::SM::thinking} ................................................
QP::QState Philo::thinking(Philo * const me, QP::QEvt const * const e) {
QP::QState status_;
switch (e->sig) {
//${AOs::Philo::SM::thinking}
case Q_ENTRY_SIG: {
me->m_timeEvt.armX(think_time(), 0U);
status_ = Q_HANDLED();
break;
}
//${AOs::Philo::SM::thinking}
case Q_EXIT_SIG: {
(void)me->m_timeEvt.disarm();
status_ = Q_HANDLED();
break;
}
//${AOs::Philo::SM::thinking::TIMEOUT}
case TIMEOUT_SIG: {
status_ = Q_TRAN(&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(&top);
break;
}
}
return status_;
}
//${AOs::Philo::SM::hungry} ..................................................
QP::QState Philo::hungry(Philo * const me, QP::QEvt const * const e) {
QP::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);
AO_Table->POST(pe, 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(&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(&top);
break;
}
}
return status_;
}
//${AOs::Philo::SM::eating} ..................................................
QP::QState Philo::eating(Philo * const me, QP::QEvt const * const e) {
QP::QState status_;
switch (e->sig) {
//${AOs::Philo::SM::eating}
case Q_ENTRY_SIG: {
me->m_timeEvt.armX(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);
QP::QF::PUBLISH(pe, me);
(void)me->m_timeEvt.disarm();
status_ = Q_HANDLED();
break;
}
//${AOs::Philo::SM::eating::TIMEOUT}
case TIMEOUT_SIG: {
status_ = Q_TRAN(&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(&top);
break;
}
}
return status_;
}
} // namespace DPP
//$enddef${AOs::Philo} #######################################################

View File

@ -0,0 +1,308 @@
//$file${.::table.cpp} #######################################################
//
// Model: dpp.qm
// File: ${.::table.cpp}
//
// This code has been generated by QM 4.3.0 (https://www.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.
//
//$endhead${.::table.cpp} ####################################################
#include "qpcpp.h"
#include "dpp.h"
#include "bsp.h"
Q_DEFINE_THIS_FILE
// Active object class -------------------------------------------------------
//$declare${AOs::Table} ######################################################
namespace DPP {
//${AOs::Table} ..............................................................
class Table : public QP::QActive {
private:
uint8_t m_fork[N_PHILO];
bool m_isHungry[N_PHILO];
public:
Table();
protected:
static QP::QState initial(Table * const me, QP::QEvt const * const e);
static QP::QState active(Table * const me, QP::QEvt const * const e);
static QP::QState serving(Table * const me, QP::QEvt const * const e);
static QP::QState paused(Table * const me, QP::QEvt const * const e);
};
} // namespace DPP
//$enddecl${AOs::Table} ######################################################
namespace DPP {
// helper function to provide the RIGHT neighbour of a Philo[n]
inline uint8_t RIGHT(uint8_t const n) {
return static_cast<uint8_t>((n + (N_PHILO - 1U)) % N_PHILO);
}
// helper function to provide the LEFT neighbour of a Philo[n]
inline uint8_t LEFT(uint8_t const n) {
return static_cast<uint8_t>((n + 1U) % N_PHILO);
}
static uint8_t const FREE = static_cast<uint8_t>(0);
static uint8_t const USED = static_cast<uint8_t>(1);
static char_t const * const THINKING = &"thinking"[0];
static char_t const * const HUNGRY = &"hungry "[0];
static char_t const * const EATING = &"eating "[0];
// Local objects -------------------------------------------------------------
static Table l_table; // the single instance of the Table active object
// Global-scope objects ------------------------------------------------------
QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
} // namespace DPP
//............................................................................
// Check for the minimum required QP version
#if (QP_VERSION < 630U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
#error qpcpp version 6.3.0 or higher required
#endif
//$define${AOs::Table} #######################################################
namespace DPP {
//${AOs::Table} ..............................................................
//${AOs::Table::Table} .......................................................
Table::Table()
: QActive(Q_STATE_CAST(&Table::initial))
{
for (uint8_t n = 0U; n < N_PHILO; ++n) {
m_fork[n] = FREE;
m_isHungry[n] = false;
}
}
//${AOs::Table::SM} ..........................................................
QP::QState Table::initial(Table * const me, QP::QEvt const * const e) {
//${AOs::Table::SM::initial}
(void)e; // suppress the compiler warning about unused parameter
me->subscribe(DONE_SIG);
me->subscribe(PAUSE_SIG);
me->subscribe(SERVE_SIG);
me->subscribe(TEST_SIG);
for (uint8_t n = 0U; n < N_PHILO; ++n) {
me->m_fork[n] = FREE;
me->m_isHungry[n] = false;
BSP::displayPhilStat(n, THINKING);
}
// global signals...
QS_SIG_DICTIONARY(DONE_SIG, (void *)0);
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);
// signals just for this AO...
QS_SIG_DICTIONARY(HUNGRY_SIG, me);
QS_FUN_DICTIONARY(&active);
QS_FUN_DICTIONARY(&serving);
QS_FUN_DICTIONARY(&paused);
return Q_TRAN(&serving);
}
//${AOs::Table::SM::active} ..................................................
QP::QState Table::active(Table * const me, QP::QEvt const * const e) {
QP::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(&top);
break;
}
}
return status_;
}
//${AOs::Table::SM::active::serving} .........................................
QP::QState Table::serving(Table * const me, QP::QEvt const * const e) {
QP::QState status_;
switch (e->sig) {
//${AOs::Table::SM::active::serving}
case Q_ENTRY_SIG: {
for (uint8_t n = 0U; n < N_PHILO; ++n) { // give permissions to eat...
if (me->m_isHungry[n]
&& (me->m_fork[LEFT(n)] == FREE)
&& (me->m_fork[n] == FREE))
{
me->m_fork[LEFT(n)] = USED;
me->m_fork[n] = USED;
TableEvt *te = Q_NEW(TableEvt, EAT_SIG);
te->philoNum = n;
QP::QF::PUBLISH(te, me);
me->m_isHungry[n] = false;
BSP::displayPhilStat(n, EATING);
}
}
status_ = Q_HANDLED();
break;
}
//${AOs::Table::SM::active::serving::HUNGRY}
case HUNGRY_SIG: {
uint8_t n = Q_EVT_CAST(TableEvt)->philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP::displayPhilStat(n, HUNGRY);
uint8_t m = LEFT(n);
//${AOs::Table::SM::active::serving::HUNGRY::[bothfree]}
if ((me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)) {
me->m_fork[m] = USED;
me->m_fork[n] = USED;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = n;
QP::QF::PUBLISH(pe, me);
BSP::displayPhilStat(n, EATING);
status_ = Q_HANDLED();
}
//${AOs::Table::SM::active::serving::HUNGRY::[else]}
else {
me->m_isHungry[n] = true;
status_ = Q_HANDLED();
}
break;
}
//${AOs::Table::SM::active::serving::DONE}
case DONE_SIG: {
uint8_t n = Q_EVT_CAST(TableEvt)->philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP::displayPhilStat(n, THINKING);
uint8_t m = LEFT(n);
// both forks of Phil[n] must be used
Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
me->m_fork[m] = FREE;
me->m_fork[n] = FREE;
m = RIGHT(n); // check the right neighbor
if (me->m_isHungry[m] && (me->m_fork[m] == FREE)) {
me->m_fork[n] = USED;
me->m_fork[m] = USED;
me->m_isHungry[m] = false;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
QP::QF::PUBLISH(pe, me);
BSP::displayPhilStat(m, EATING);
}
m = LEFT(n); // check the left neighbor
n = LEFT(m); // left fork of the left neighbor
if (me->m_isHungry[m] && (me->m_fork[n] == FREE)) {
me->m_fork[m] = USED;
me->m_fork[n] = USED;
me->m_isHungry[m] = false;
TableEvt *pe = Q_NEW(TableEvt, EAT_SIG);
pe->philoNum = m;
QP::QF::PUBLISH(pe, 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(&paused);
break;
}
default: {
status_ = Q_SUPER(&active);
break;
}
}
return status_;
}
//${AOs::Table::SM::active::paused} ..........................................
QP::QState Table::paused(Table * const me, QP::QEvt const * const e) {
QP::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(&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->m_isHungry[n]));
me->m_isHungry[n] = true;
BSP::displayPhilStat(n, HUNGRY);
status_ = Q_HANDLED();
break;
}
//${AOs::Table::SM::active::paused::DONE}
case DONE_SIG: {
uint8_t n = Q_EVT_CAST(TableEvt)->philoNum;
// phil ID must be in range and he must be not hungry
Q_ASSERT((n < N_PHILO) && (!me->m_isHungry[n]));
BSP::displayPhilStat(n, THINKING);
uint8_t m = LEFT(n);
/* both forks of Phil[n] must be used */
Q_ASSERT((me->m_fork[n] == USED) && (me->m_fork[m] == USED));
me->m_fork[m] = FREE;
me->m_fork[n] = FREE;
status_ = Q_HANDLED();
break;
}
default: {
status_ = Q_SUPER(&active);
break;
}
}
return status_;
}
} // namespace DPP
//$enddef${AOs::Table} #######################################################

View File

@ -1,13 +1,13 @@
//****************************************************************************
// Product: DPP example, STM32F4-Discovery board, ThreadX kernel
// Last updated for version 5.9.0
// Last updated on 2017-05-09
// Last Updated for Version: 6.3.7
// Date of the Last Update: 2018-12-17
//
// Q u a n t u m L e a P s
// ---------------------------
// innovating embedded systems
// ------------------------
// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
// Copyright (C) 2005-2018 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
@ -28,7 +28,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Contact information:
// https://state-machine.com
// https://www.state-machine.com
// mailto:info@state-machine.com
//****************************************************************************
#include "qpcpp.h"
@ -325,17 +325,8 @@ bool QS::onStartup(void const *arg) {
DPP::QS_tickTime_ = DPP::QS_tickPeriod_; // to start the timestamp at zero
// setup the QS filters...
QS_FILTER_ON(QS_QEP_STATE_ENTRY);
QS_FILTER_ON(QS_QEP_STATE_EXIT);
QS_FILTER_ON(QS_QEP_STATE_INIT);
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(DPP::PHILO_STAT);
QS_FILTER_ON(QS_ALL_RECORDS);
QS_FILTER_OFF(QS_QF_TICK);
return true; // return success
}

View File

@ -1,7 +1,7 @@
//****************************************************************************
// Product: DPP example
// Last Updated for Version: 5.6.0
// Date of the Last Update: 2015-12-28
// 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
// ---------------------------
@ -54,6 +54,8 @@ public:
static void ledOff(void);
};
extern QP::QActive *the_Ticker0;
} // namespace DPP
#endif // bsp_h

View File

@ -3,7 +3,7 @@
// Model: dpp.qm
// File: ${.::dpp.h}
//
// This code has been generated by QM tool (https://state-machine.com/qm).
// This code has been generated by QM 4.3.0 (https://www.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
@ -48,8 +48,7 @@ public:
//$enddecl${Events::TableEvt} ################################################
// number of philosophers
// NOTE: Only one Philo, because of the ThreadX demo library limits
#define N_PHILO (static_cast<uint8_t>(1))
#define N_PHILO ((uint8_t)5)
//$declare${AOs::AO_Philo[N_PHILO]} ##########################################
namespace DPP {

View File

@ -1,59 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<model version="4.1.2" links="0">
<model version="4.3.0" links="1">
<documentation>Dining Philosopher Problem example with MSM state machines</documentation>
<!--${qpcpp}-->
<framework name="qpcpp"/>
<!--${Events}-->
<package name="Events" stereotype="0x01" namespace="DPP::">
<!--${Events::TableEvt}-->
<class name="TableEvt" superclass="qpcpp::QEvt">
<!--${Events::TableEvt::philoNum}-->
<attribute name="philoNum" type="uint8_t" visibility="0x00" properties="0x00"/>
</class>
</package>
<!--${AOs}-->
<package name="AOs" stereotype="0x02" namespace="DPP::">
<!--${AOs::Philo}-->
<class name="Philo" superclass="qpcpp::QActive">
<!--${AOs::Philo::m_timeEvt}-->
<attribute name="m_timeEvt" type="QP::QTimeEvt" visibility="0x02" properties="0x00"/>
<!--${AOs::Philo::Philo}-->
<operation name="Philo" type="" visibility="0x00" properties="0x00">
<code> : QActive(Q_STATE_CAST(&amp;Philo::initial)),
m_timeEvt(this, TIMEOUT_SIG, 0U)</code>
</operation>
<!--${AOs::Philo::SM}-->
<statechart>
<!--${AOs::Philo::SM::initial}-->
<initial target="../1">
<action>static bool registered = false; // starts off with 0, per C-standard
(void)e; // suppress the compiler warning about unused parameter
me-&gt;subscribe(EAT_SIG);
me-&gt;subscribe(TEST_SIG);
if (!registered) {
registered = true;
QS_OBJ_DICTIONARY(&amp;l_philo[0]);
QS_OBJ_DICTIONARY(&amp;l_philo[0].m_timeEvt);
//QS_OBJ_DICTIONARY(&amp;l_philo[1]);
//QS_OBJ_DICTIONARY(&amp;l_philo[1].m_timeEvt);
//QS_OBJ_DICTIONARY(&amp;l_philo[2]);
//QS_OBJ_DICTIONARY(&amp;l_philo[2].m_timeEvt);
//QS_OBJ_DICTIONARY(&amp;l_philo[3]);
//QS_OBJ_DICTIONARY(&amp;l_philo[3].m_timeEvt);
//QS_OBJ_DICTIONARY(&amp;l_philo[4]);
//QS_OBJ_DICTIONARY(&amp;l_philo[4].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[1].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[2].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[3].m_timeEvt);
QS_OBJ_DICTIONARY(&amp;l_philo[4].m_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_FUN_DICTIONARY(&amp;initial);
QS_FUN_DICTIONARY(&amp;thinking);
QS_FUN_DICTIONARY(&amp;hungry);
QS_FUN_DICTIONARY(&amp;eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos
me-&gt;subscribe(EAT_SIG);
me-&gt;subscribe(TEST_SIG);</action>
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos</action>
<initial_glyph conn="2,3,5,1,20,5,-3">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<!--${AOs::Philo::SM::thinking}-->
<state name="thinking">
<entry>me-&gt;m_timeEvt.armX(think_time(), 0U);</entry>
<exit>(void)me-&gt;m_timeEvt.disarm();</exit>
<!--${AOs::Philo::SM::thinking::TIMEOUT}-->
<tran trig="TIMEOUT" target="../../2">
<tran_glyph conn="2,13,3,1,20,12,-3">
<action box="0,-2,11,2"/>
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::thinking::EAT, DONE}-->
<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>
@ -61,6 +71,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::thinking::TEST}-->
<tran trig="TEST">
<tran_glyph conn="2,19,3,-1,13">
<action box="0,-2,11,4"/>
@ -71,11 +82,14 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<!--${AOs::Philo::SM::hungry}-->
<state name="hungry">
<entry>TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
pe-&gt;philoNum = PHILO_ID(me);
AO_Table-&gt;POST(pe, me);</entry>
<!--${AOs::Philo::SM::hungry::EAT}-->
<tran trig="EAT">
<!--${AOs::Philo::SM::hungry::EAT::[Q_EVT_CAST(TableEvt)->philoNum=~}-->
<choice target="../../../3">
<guard>Q_EVT_CAST(TableEvt)-&gt;philoNum == PHILO_ID(me)</guard>
<choice_glyph conn="15,30,5,1,7,13,-3">
@ -86,6 +100,7 @@ AO_Table-&gt;POST(pe, me);</entry>
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::hungry::DONE}-->
<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>
@ -97,17 +112,20 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<entry box="1,2,5,2"/>
</state_glyph>
</state>
<!--${AOs::Philo::SM::eating}-->
<state name="eating">
<entry>me-&gt;m_timeEvt.armX(eat_time(), 0U);</entry>
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
pe-&gt;philoNum = PHILO_ID(me);
QP::QF::PUBLISH(pe, me);
(void)me-&gt;m_timeEvt.disarm();</exit>
<!--${AOs::Philo::SM::eating::TIMEOUT}-->
<tran trig="TIMEOUT" target="../../1">
<tran_glyph conn="2,51,3,1,22,-41,-5">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Philo::SM::eating::EAT, DONE}-->
<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>
@ -123,9 +141,13 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)-&gt;philoNum != PHILO_ID(me));</action>
<state_diagram size="36,61"/>
</statechart>
</class>
<!--${AOs::Table}-->
<class name="Table" superclass="qpcpp::QActive">
<!--${AOs::Table::m_fork[N_PHILO]}-->
<attribute name="m_fork[N_PHILO]" type="uint8_t" visibility="0x02" properties="0x00"/>
<!--${AOs::Table::m_isHungry[N_PHILO]}-->
<attribute name="m_isHungry[N_PHILO]" type="bool" visibility="0x02" properties="0x00"/>
<!--${AOs::Table::Table}-->
<operation name="Table" type="" visibility="0x00" properties="0x00">
<code> : QActive(Q_STATE_CAST(&amp;Table::initial))
@ -134,25 +156,12 @@ for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
m_isHungry[n] = false;
}</code>
</operation>
<statechart>
<!--${AOs::Table::SM}-->
<statechart properties="QS_FUN_DICT">
<!--${AOs::Table::SM::initial}-->
<initial target="../1/2">
<action>(void)e; // suppress the compiler warning about unused parameter
QS_OBJ_DICTIONARY(&amp;l_table);
QS_FUN_DICTIONARY(&amp;QP::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
me-&gt;subscribe(DONE_SIG);
me-&gt;subscribe(PAUSE_SIG);
me-&gt;subscribe(SERVE_SIG);
@ -162,23 +171,37 @@ for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
me-&gt;m_fork[n] = FREE;
me-&gt;m_isHungry[n] = false;
BSP::displayPhilStat(n, THINKING);
}</action>
}
// global signals...
QS_SIG_DICTIONARY(DONE_SIG, (void *)0);
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);
// signals just for this AO...
QS_SIG_DICTIONARY(HUNGRY_SIG, me);</action>
<initial_glyph conn="3,3,5,1,45,18,-10">
<action box="0,-2,6,2"/>
</initial_glyph>
</initial>
<!--${AOs::Table::SM::active}-->
<state name="active">
<!--${AOs::Table::SM::active::TEST}-->
<tran trig="TEST">
<tran_glyph conn="2,11,3,-1,14">
<action box="0,-2,11,4"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::EAT}-->
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="2,15,3,-1,14">
<action box="0,-2,10,4"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving}-->
<state name="serving">
<entry brief="give pending permitions to eat">for (uint8_t n = 0U; n &lt; N_PHILO; ++n) { // give permissions to eat...
if (me-&gt;m_isHungry[n]
@ -194,6 +217,7 @@ for (uint8_t n = 0U; n &lt; N_PHILO; ++n) {
BSP::displayPhilStat(n, EATING);
}
}</entry>
<!--${AOs::Table::SM::active::serving::HUNGRY}-->
<tran trig="HUNGRY">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
// phil ID must be in range and he must be not hungry
@ -201,6 +225,7 @@ Q_ASSERT((n &lt; N_PHILO) &amp;&amp; (!me-&gt;m_isHungry[n]));
BSP::displayPhilStat(n, HUNGRY);
uint8_t m = LEFT(n);</action>
<!--${AOs::Table::SM::active::serving::HUNGRY::[bothfree]}-->
<choice>
<guard brief="both free">(me-&gt;m_fork[m] == FREE) &amp;&amp; (me-&gt;m_fork[n] == FREE)</guard>
<action>me-&gt;m_fork[m] = USED;
@ -213,6 +238,7 @@ BSP::displayPhilStat(n, EATING);</action>
<action box="1,0,10,2"/>
</choice_glyph>
</choice>
<!--${AOs::Table::SM::active::serving::HUNGRY::[else]}-->
<choice>
<guard>else</guard>
<action>me-&gt;m_isHungry[n] = true;</action>
@ -224,6 +250,7 @@ BSP::displayPhilStat(n, EATING);</action>
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving::DONE}-->
<tran trig="DONE">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
// phil ID must be in range and he must be not hungry
@ -262,12 +289,14 @@ if (me-&gt;m_isHungry[m] &amp;&amp; (me-&gt;m_fork[n] == FREE)) {
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving::EAT}-->
<tran trig="EAT">
<action>Q_ERROR();</action>
<tran_glyph conn="4,37,3,-1,15">
<action box="0,-2,12,4"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::serving::PAUSE}-->
<tran trig="PAUSE" target="../../3">
<tran_glyph conn="4,41,3,1,37,6,-3">
<action box="0,-2,7,2"/>
@ -277,14 +306,17 @@ if (me-&gt;m_isHungry[m] &amp;&amp; (me-&gt;m_fork[n] == FREE)) {
<entry box="1,2,27,2"/>
</state_glyph>
</state>
<!--${AOs::Table::SM::active::paused}-->
<state name="paused">
<entry>BSP::displayPaused(1U);</entry>
<exit>BSP::displayPaused(0U);</exit>
<!--${AOs::Table::SM::active::paused::SERVE}-->
<tran trig="SERVE" target="../../2">
<tran_glyph conn="4,57,3,1,39,-29,-5">
<action box="0,-2,7,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::paused::HUNGRY}-->
<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
@ -295,6 +327,7 @@ BSP::displayPhilStat(n, HUNGRY);</action>
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<!--${AOs::Table::SM::active::paused::DONE}-->
<tran trig="DONE">
<action>uint8_t n = Q_EVT_CAST(TableEvt)-&gt;philoNum;
// phil ID must be in range and he must be not hungry
@ -321,12 +354,18 @@ me-&gt;m_fork[n] = FREE;</action>
<state_diagram size="50,69"/>
</statechart>
</class>
<!--${AOs::AO_Philo[N_PHILO]}-->
<attribute name="AO_Philo[N_PHILO]" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
<!--${AOs::AO_Table}-->
<attribute name="AO_Table" type="QP::QActive * const" visibility="0x00" properties="0x00"/>
<!--${AOs::XT_Test1}-->
<attribute name="XT_Test1" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
<!--${AOs::XT_Test2}-->
<attribute name="XT_Test2" type="QP::QXThread * const" visibility="0x00" properties="0x00"/>
</package>
<!--${.}-->
<directory name=".">
<!--${.::dpp.h}-->
<file name="dpp.h">
<text>#ifndef dpp_h
#define dpp_h
@ -350,8 +389,7 @@ enum DPPSignals {
$declare(Events::TableEvt)
// number of philosophers
// NOTE: Only one Philo, because of the ThreadX demo library limits
#define N_PHILO (static_cast&lt;uint8_t&gt;(1))
#define N_PHILO ((uint8_t)5)
$declare(AOs::AO_Philo[N_PHILO])
@ -362,9 +400,9 @@ $declare(AOs::XT_Test1)
$declare(AOs::XT_Test2)
#endif // qxk_h
#endif // dpp_h
</text>
#endif // dpp_h</text>
</file>
<!--${.::philo.cpp}-->
<file name="philo.cpp">
<text>#include &quot;qpcpp.h&quot;
#include &quot;dpp.h&quot;
@ -404,10 +442,10 @@ enum InternalSignals { // internal signals
// Global objects ------------------------------------------------------------
QP::QActive * const AO_Philo[N_PHILO] = { // &quot;opaque&quot; pointers to Philo AO
&amp;l_philo[0],
//&amp;l_philo[1],
//&amp;l_philo[2],
//&amp;l_philo[3],
//&amp;l_philo[4]
&amp;l_philo[1],
&amp;l_philo[2],
&amp;l_philo[3],
&amp;l_philo[4]
};
} // namespace DPP
@ -415,6 +453,7 @@ QP::QActive * const AO_Philo[N_PHILO] = { // &quot;opaque&quot; pointers to Phil
// Philo definition ----------------------------------------------------------
$define(AOs::Philo)</text>
</file>
<!--${.::table.cpp}-->
<file name="table.cpp">
<text>#include &quot;qpcpp.h&quot;
#include &quot;dpp.h&quot;

View File

@ -2894,7 +2894,7 @@
</option>
<option>
<name>OCLastSavedByProductVersion</name>
<state>8.11.1.13270</state>
<state>7.40.3.8937</state>
</option>
<option>
<name>UseFlashLoader</name>

View File

@ -36,7 +36,7 @@
</option>
<option>
<name>Output description</name>
<state>No specifier a, A, no specifier n, no float nor long long, no flags.</state>
<state>No specifier a, A, no specifier n, no float nor long long, no flags, without multibyte support.</state>
</option>
<option>
<name>GOutputBinary</name>
@ -235,7 +235,7 @@
</option>
<option>
<name>CCListCFile</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CCListCMnemonics</name>
@ -296,11 +296,11 @@
</option>
<option>
<name>IExtraOptionsCheck</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>IExtraOptions</name>
<state>--enable-restrict</state>
<state></state>
</option>
<option>
<name>CCLangConformance</name>
@ -348,6 +348,7 @@
<state>$PROJ_DIR$\..\..\..\..\..\src</state>
<state>$PROJ_DIR$\..\..\..\..\..\ports\threadx</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery\inc</state>
@ -1325,11 +1326,11 @@
</option>
<option>
<name>IExtraOptionsCheck</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>IExtraOptions</name>
<state>--enable-restrict</state>
<state></state>
</option>
<option>
<name>CCLangConformance</name>
@ -1377,6 +1378,7 @@
<state>$PROJ_DIR$\..\..\..\..\..\src</state>
<state>$PROJ_DIR$\..\..\..\..\..\ports\threadx</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery\inc</state>
@ -2094,7 +2096,7 @@
</option>
<option>
<name>Output description</name>
<state>No specifier a, A, no specifier n, no float nor long long, no flags, without multibyte support.</state>
<state>No specifier a, A, no specifier n, no float nor long long, no flags.</state>
</option>
<option>
<name>GOutputBinary</name>
@ -2175,7 +2177,7 @@
<option>
<name>GBECoreSlave</name>
<version>26</version>
<state>39</state>
<state>40</state>
</option>
<option>
<name>OGUseCmsis</name>
@ -2354,11 +2356,11 @@
</option>
<option>
<name>IExtraOptionsCheck</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>IExtraOptions</name>
<state>--enable-restrict</state>
<state></state>
</option>
<option>
<name>CCLangConformance</name>
@ -2406,6 +2408,7 @@
<state>$PROJ_DIR$\..\..\..\..\..\src</state>
<state>$PROJ_DIR$\..\..\..\..\..\ports\threadx</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery</state>
<state>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery\inc</state>
@ -2978,7 +2981,7 @@
</option>
<option>
<name>IlinkOptExceptionsAllow</name>
<state>0</state>
<state>1</state>
</option>
<option>
<name>IlinkOptExceptionsForce</name>
@ -3130,7 +3133,7 @@
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_dyn.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_pkg.h</name>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf_pkg.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\src\qf\qf_ps.cpp</name>
@ -3185,7 +3188,7 @@
<group>
<name>stm32f4-discovery</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery\iar\startup_stm32f4xx_threadx.s</name>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery\iar\startup_stm32f4xx.s</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\stm32f4-discovery\stm32f4xx.h</name>
@ -3212,19 +3215,19 @@
<group>
<name>ThreadX</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx.a</name>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar\readme_threadx.txt</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar\tx.a</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_api.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_initialize_low_level.s</name>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\stm32f4xx_iar\tx_port.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_port.h</name>
<name>$PROJ_DIR$\..\..\..\..\..\3rd_party\threadx\tx_trace.h</name>
</file>
</group>
<file>
<name>$PROJ_DIR$\ReadMe.txt</name>
</file>
</project>

View File

@ -1,13 +1,13 @@
//////////////////////////////////////////////////////////////////////////////
// Product: DPP example for ThreadX
// Last updated for version 6.2.0
// Last updated on 2018-04-06
// Last updated for version 6.3.7
// Last updated on 2018-12-17
//
// Q u a n t u m L e a P s
// ---------------------------
// innovating embedded systems
// ------------------------
// Modern Embedded Software
//
// Copyright (C) Quantum Leaps, LLC. All rights reserved.
// Copyright (C) 2005-2018 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
@ -70,11 +70,10 @@ void tx_application_define(void * /*first_unused_memory*/) {
QS_OBJ_DICTIONARY(l_smlPoolSto);
QS_OBJ_DICTIONARY(l_tableQueueSto);
QS_OBJ_DICTIONARY(l_philoQueueSto[0]);
//NOTE: can't use more active objects in the ThreadX demo!
//QS_OBJ_DICTIONARY(l_philoQueueSto[1]);
//QS_OBJ_DICTIONARY(l_philoQueueSto[2]);
//QS_OBJ_DICTIONARY(l_philoQueueSto[3]);
//QS_OBJ_DICTIONARY(l_philoQueueSto[4]);
QS_OBJ_DICTIONARY(l_philoQueueSto[1]);
QS_OBJ_DICTIONARY(l_philoQueueSto[2]);
QS_OBJ_DICTIONARY(l_philoQueueSto[3]);
QS_OBJ_DICTIONARY(l_philoQueueSto[4]);
// start the active objects...
for (uint8_t n = 0; n < N_PHILO; ++n) {

View File

@ -3,7 +3,7 @@
// Model: dpp.qm
// File: ${.::philo.cpp}
//
// This code has been generated by QM tool (https://state-machine.com/qm).
// This code has been generated by QM 4.3.0 (https://www.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
@ -73,20 +73,21 @@ enum InternalSignals { // internal signals
// Global objects ------------------------------------------------------------
QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO
&l_philo[0],
//&l_philo[1],
//&l_philo[2],
//&l_philo[3],
//&l_philo[4]
&l_philo[1],
&l_philo[2],
&l_philo[3],
&l_philo[4]
};
} // namespace DPP
// Philo definition ----------------------------------------------------------
//$define${AOs::Philo} #######################################################
// Check for the minimum required QP version
#if ((QP_VERSION < 601) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8)))
#error qpcpp version 6.0.1 or higher required
#if (QP_VERSION < 630U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
#error qpcpp version 6.3.0 or higher required
#endif
//$define${AOs::Philo} #######################################################
namespace DPP {
//${AOs::Philo} ..............................................................
@ -95,36 +96,32 @@ Philo::Philo()
: QActive(Q_STATE_CAST(&Philo::initial)),
m_timeEvt(this, TIMEOUT_SIG, 0U)
{}
//${AOs::Philo::SM} ..........................................................
QP::QState Philo::initial(Philo * const me, QP::QEvt const * const e) {
//${AOs::Philo::SM::initial}
static bool registered = false; // starts off with 0, per C-standard
(void)e; // suppress the compiler warning about unused parameter
if (!registered) {
registered = true;
QS_OBJ_DICTIONARY(&l_philo[0]);
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
//QS_OBJ_DICTIONARY(&l_philo[1]);
//QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
//QS_OBJ_DICTIONARY(&l_philo[2]);
//QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
//QS_OBJ_DICTIONARY(&l_philo[3]);
//QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
//QS_OBJ_DICTIONARY(&l_philo[4]);
//QS_OBJ_DICTIONARY(&l_philo[4].m_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
me->subscribe(EAT_SIG);
me->subscribe(TEST_SIG);
if (!registered) {
registered = true;
QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[1].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[2].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[3].m_timeEvt);
QS_OBJ_DICTIONARY(&l_philo[4].m_timeEvt);
QS_FUN_DICTIONARY(&initial);
QS_FUN_DICTIONARY(&thinking);
QS_FUN_DICTIONARY(&hungry);
QS_FUN_DICTIONARY(&eating);
}
QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos
QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos
return Q_TRAN(&thinking);
}
//${AOs::Philo::SM::thinking} ................................................

View File

@ -3,7 +3,7 @@
// Model: dpp.qm
// File: ${.::table.cpp}
//
// This code has been generated by QM tool (https://state-machine.com/qm).
// This code has been generated by QM 4.3.0 (https://www.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
@ -73,11 +73,12 @@ QP::QActive * const AO_Table = &l_table; // "opaque" AO pointer
} // namespace DPP
//............................................................................
//$define${AOs::Table} #######################################################
// Check for the minimum required QP version
#if ((QP_VERSION < 601) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8)))
#error qpcpp version 6.0.1 or higher required
#if (QP_VERSION < 630U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
#error qpcpp version 6.3.0 or higher required
#endif
//$define${AOs::Table} #######################################################
namespace DPP {
//${AOs::Table} ..............................................................
@ -90,27 +91,11 @@ Table::Table()
m_isHungry[n] = false;
}
}
//${AOs::Table::SM} ..........................................................
QP::QState Table::initial(Table * const me, QP::QEvt const * const e) {
//${AOs::Table::SM::initial}
(void)e; // suppress the compiler warning about unused parameter
QS_OBJ_DICTIONARY(&l_table);
QS_FUN_DICTIONARY(&QP::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
me->subscribe(DONE_SIG);
me->subscribe(PAUSE_SIG);
me->subscribe(SERVE_SIG);
@ -121,6 +106,21 @@ QP::QState Table::initial(Table * const me, QP::QEvt const * const e) {
me->m_isHungry[n] = false;
BSP::displayPhilStat(n, THINKING);
}
// global signals...
QS_SIG_DICTIONARY(DONE_SIG, (void *)0);
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);
// signals just for this AO...
QS_SIG_DICTIONARY(HUNGRY_SIG, me);
QS_FUN_DICTIONARY(&active);
QS_FUN_DICTIONARY(&serving);
QS_FUN_DICTIONARY(&paused);
return Q_TRAN(&serving);
}
//${AOs::Table::SM::active} ..................................................