mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-01-28 06:02:56 +08:00
6.3.7d
This commit is contained in:
parent
719bd515a4
commit
6eab63640f
@ -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
|
||||
|
258
3rd_party/threadx/readme_threadx.txt
vendored
258
3rd_party/threadx/readme_threadx.txt
vendored
@ -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
|
||||
|
248
3rd_party/threadx/stm32f4xx_iar/readme_threadx.txt
vendored
Normal file
248
3rd_party/threadx/stm32f4xx_iar/readme_threadx.txt
vendored
Normal 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
|
||||
|
431
3rd_party/threadx/stm32f4xx_iar/tx_port.h
vendored
Normal file
431
3rd_party/threadx/stm32f4xx_iar/tx_port.h
vendored
Normal 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
|
||||
|
||||
|
||||
|
247
3rd_party/threadx/tm4c123xx_iar/readme_threadx.txt
vendored
Normal file
247
3rd_party/threadx/tm4c123xx_iar/readme_threadx.txt
vendored
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
1112
3rd_party/threadx/tx_api.h
vendored
1112
3rd_party/threadx/tx_api.h
vendored
File diff suppressed because it is too large
Load Diff
227
3rd_party/threadx/tx_initialize_low_level.s
vendored
227
3rd_party/threadx/tx_initialize_low_level.s
vendored
@ -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
612
3rd_party/threadx/tx_trace.h
vendored
Normal 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
|
||||
|
407
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/bsp.cpp
Normal file
407
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/bsp.cpp
Normal 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.
|
||||
//
|
||||
|
61
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/bsp.h
Normal file
61
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/bsp.h
Normal 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
|
86
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.h
Normal file
86
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.h
Normal 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
|
498
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.qm
Normal file
498
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/dpp.qm
Normal 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(&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->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</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->m_timeEvt.armX(think_time(), 0U);</entry>
|
||||
<exit>(void)me->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)->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->philoNum = PHILO_ID(me);
|
||||
AO_Table->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)->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)->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->m_timeEvt.armX(eat_time(), 0U);</entry>
|
||||
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
|
||||
pe->philoNum = PHILO_ID(me);
|
||||
QP::QF::PUBLISH(pe, me);
|
||||
(void)me->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)->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(&Table::initial))
|
||||
|
||||
for (uint8_t n = 0U; n < 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->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);</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 < 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);
|
||||
}
|
||||
}</entry>
|
||||
<!--${AOs::Table::SM::active::serving::HUNGRY}-->
|
||||
<tran trig="HUNGRY">
|
||||
<action>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);</action>
|
||||
<!--${AOs::Table::SM::active::serving::HUNGRY::[bothfree]}-->
|
||||
<choice>
|
||||
<guard brief="both free">(me->m_fork[m] == FREE) && (me->m_fork[n] == FREE)</guard>
|
||||
<action>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);</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->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)->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);
|
||||
}</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)->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);</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)->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;</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 "qpcpp.h"
|
||||
#include "dpp.h"
|
||||
#include "bsp.h"
|
||||
|
||||
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<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 ----------------------------------------------------------
|
||||
$define(AOs::Philo)</text>
|
||||
</file>
|
||||
<!--${.::table.cpp}-->
|
||||
<file name="table.cpp">
|
||||
<text>#include "qpcpp.h"
|
||||
#include "dpp.h"
|
||||
#include "bsp.h"
|
||||
|
||||
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<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
|
||||
|
||||
//............................................................................
|
||||
$define(AOs::Table)</text>
|
||||
</file>
|
||||
</directory>
|
||||
</model>
|
4213
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewd
Normal file
4213
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewd
Normal file
File diff suppressed because it is too large
Load Diff
3218
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewp
Normal file
3218
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.ewp
Normal file
File diff suppressed because it is too large
Load Diff
10
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.eww
Normal file
10
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.eww
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
|
||||
<workspace>
|
||||
<project>
|
||||
<path>$WS_DIR$\dpp.ewp</path>
|
||||
</project>
|
||||
<batchBuild/>
|
||||
</workspace>
|
||||
|
||||
|
29
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.icf
Normal file
29
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/iar/dpp.icf
Normal 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 };
|
91
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/main.cpp
Normal file
91
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/main.cpp
Normal 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
|
||||
}
|
246
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/philo.cpp
Normal file
246
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/philo.cpp
Normal 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} #######################################################
|
308
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/table.cpp
Normal file
308
examples/threadx/arm-cm/dpp_ek-tm4c123gxl/table.cpp
Normal 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} #######################################################
|
@ -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
|
||||
// Q u a n t u m L e a P s
|
||||
// ------------------------
|
||||
// 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
|
||||
}
|
||||
|
@ -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
|
||||
// ---------------------------
|
||||
@ -46,7 +46,7 @@ public:
|
||||
static void terminate(int16_t const result);
|
||||
|
||||
static void randomSeed(uint32_t const seed); // random seed
|
||||
static uint32_t random(void); // pseudo-random generator
|
||||
static uint32_t random(void); // pseudo-random generator
|
||||
|
||||
// for testing...
|
||||
static void wait4SW1(void);
|
||||
@ -54,6 +54,8 @@ public:
|
||||
static void ledOff(void);
|
||||
};
|
||||
|
||||
extern QP::QActive *the_Ticker0;
|
||||
|
||||
} // namespace DPP
|
||||
|
||||
#endif // bsp_h
|
||||
|
@ -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 {
|
||||
@ -84,4 +83,4 @@ extern QP::QXThread * const XT_Test2;
|
||||
//$enddecl${AOs::XT_Test2} ###################################################
|
||||
#endif // qxk_h
|
||||
|
||||
#endif // dpp_h
|
||||
#endif // dpp_h
|
@ -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(&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->subscribe(EAT_SIG);
|
||||
me->subscribe(TEST_SIG);
|
||||
|
||||
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_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(&Philo::initial);
|
||||
QS_FUN_DICTIONARY(&Philo::thinking);
|
||||
QS_FUN_DICTIONARY(&Philo::hungry);
|
||||
QS_FUN_DICTIONARY(&Philo::eating);
|
||||
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
|
||||
|
||||
me->subscribe(EAT_SIG);
|
||||
me->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->m_timeEvt.armX(think_time(), 0U);</entry>
|
||||
<exit>(void)me->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)->philoNum != PHILO_ID(me));</action>
|
||||
@ -61,6 +71,7 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->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)->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->philoNum = PHILO_ID(me);
|
||||
AO_Table->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)->philoNum == PHILO_ID(me)</guard>
|
||||
<choice_glyph conn="15,30,5,1,7,13,-3">
|
||||
@ -86,6 +100,7 @@ AO_Table->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)->philoNum != PHILO_ID(me));</action>
|
||||
@ -97,17 +112,20 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me));</action>
|
||||
<entry box="1,2,5,2"/>
|
||||
</state_glyph>
|
||||
</state>
|
||||
<!--${AOs::Philo::SM::eating}-->
|
||||
<state name="eating">
|
||||
<entry>me->m_timeEvt.armX(eat_time(), 0U);</entry>
|
||||
<exit>TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
|
||||
pe->philoNum = PHILO_ID(me);
|
||||
QP::QF::PUBLISH(pe, me);
|
||||
(void)me->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)->philoNum != PHILO_ID(me));</action>
|
||||
@ -123,9 +141,13 @@ Q_ASSERT(Q_EVT_CAST(TableEvt)->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(&Table::initial))
|
||||
|
||||
@ -134,25 +156,12 @@ for (uint8_t n = 0U; n < 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(&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);
|
||||
@ -162,23 +171,37 @@ for (uint8_t n = 0U; n < N_PHILO; ++n) {
|
||||
me->m_fork[n] = FREE;
|
||||
me->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 < N_PHILO; ++n) { // give permissions to eat...
|
||||
if (me->m_isHungry[n]
|
||||
@ -194,6 +217,7 @@ for (uint8_t n = 0U; n < 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)->philoNum;
|
||||
// phil ID must be in range and he must be not hungry
|
||||
@ -201,6 +225,7 @@ Q_ASSERT((n < N_PHILO) && (!me->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->m_fork[m] == FREE) && (me->m_fork[n] == FREE)</guard>
|
||||
<action>me->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->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)->philoNum;
|
||||
// phil ID must be in range and he must be not hungry
|
||||
@ -262,12 +289,14 @@ if (me->m_isHungry[m] && (me->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->m_isHungry[m] && (me->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)->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)->philoNum;
|
||||
// phil ID must be in range and he must be not hungry
|
||||
@ -321,12 +354,18 @@ me->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<uint8_t>(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 "qpcpp.h"
|
||||
#include "dpp.h"
|
||||
@ -404,10 +442,10 @@ 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
|
||||
@ -415,6 +453,7 @@ QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Phil
|
||||
// Philo definition ----------------------------------------------------------
|
||||
$define(AOs::Philo)</text>
|
||||
</file>
|
||||
<!--${.::table.cpp}-->
|
||||
<file name="table.cpp">
|
||||
<text>#include "qpcpp.h"
|
||||
#include "dpp.h"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
// Q u a n t u m L e a P s
|
||||
// ------------------------
|
||||
// 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) {
|
||||
|
@ -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} ................................................
|
||||
|
@ -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} ..................................................
|
||||
|
Loading…
x
Reference in New Issue
Block a user