02年世界杯韩国黑哨_曲棍球世界杯 - guanchafang.com

【第十四篇】QP移植与配置
2025-07-03 04:09:28

QP本身可以看做是一个软件的框架(其实和操作系统有点像,但是又有一点不一样),在移植之前,先看一下这个QP他主要位于我们项目开发的哪一个层上,假如我们采用分层的思想来组织我们的项目,如下:

从图中可以看到QP在项目开发中所处于的层的位置,他更接近于我们的应用,在他的下面有BSP,RTOS 还有hardware(硬件)。那么站在移植的角度上来看的话,QP移植有关的内容有,CPU(架构),编译器和操作系统(可能没有)。

QP为了实现跨平台移植及通用性,所以在设计之初就考虑到了后面的移植的问题,也就是对外有了一个叫做PAL的层,也就是我的port接口文件。

PAL层有两个目的: 简化QP使用 和 简化移植 qf_port.h(新版本变更为qpc.h)(PAL层接口文件),

简化QP使用:根据qf_port.h(新版本变更为qpc.h)文件在应用中调用QP.lib提供的服务。

简化移植:根据qf_port.h文件裁剪QP源代码,生成特定的qp.lib库文件。

如何能够生成qp.lib库文件,假如我们讲自己编写的某个软件以组件的形式提供给他人应用,如果组织自己的代码,这里QP给了我们很好的一些建议。

所有 QP 构件被设计为使用一个细粒度的目标库来部署。 QP 库允许连接器在链接时消除任 何没有被引用的 QP 代码,这为广泛的应用程序导致了对每个 QP 构件的自动处理。这个方法消除了为每个应用程序进行手工配置和充新编译 QP 源代码的需求。具体如何实现的,可以查看其源码的组织方式。

接下来我们以QPC691版本进行分析,main.c文件中包含qpc.h:

#ifndef QPC_H

#define QPC_H

/**

* @description

* This header file must be included directly or indirectly

* in all application modules (*.c files) that use QP/C.

*/

#ifdef __cplusplus

extern "C" {

#endif

/****************************************************************************/

#include "qf_port.h" /* QF/C port from the port directory */

#include "qassert.h" /* QP embedded systems-friendly assertions */

#ifdef Q_SPY /* software tracing enabled? */

#include "qs_port.h" /* QS/C port from the port directory */

#else

#include "qs_dummy.h" /* QS/C dummy (inactive) interface */

#endif

由qpc.h包含qf_port.h文件:

#ifndef QF_PORT_H

#define QF_PORT_H

/* The maximum number of system clock tick rates */

#define QF_MAX_TICK_RATE 2U

/* QF interrupt disable/enable and log2()... */

#if (__ARM_ARCH == 6) /* Cortex-M0/M0+/M1(v6-M, v6S-M)? */

/* The maximum number of active objects in the application, see NOTE1 */

#define QF_MAX_ACTIVE 8U

/* Cortex-M0/M0+/M1(v6-M, v6S-M) interrupt disabling policy, see NOTE2 */

#define QF_INT_DISABLE() __asm volatile ("cpsid i")

#define QF_INT_ENABLE() __asm volatile ("cpsie i")

/* QF critical section entry/exit (unconditional interrupt disabling) */

/*#define QF_CRIT_STAT_TYPE not defined */

#define QF_CRIT_ENTRY(dummy) QF_INT_DISABLE()

#define QF_CRIT_EXIT(dummy) QF_INT_ENABLE()

/* CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 */

#define QF_AWARE_ISR_CMSIS_PRI 0

/* hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) */

#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))

#else /* Cortex-M3/M4/M7 */

/* The maximum number of active objects in the application, see NOTE1 */

#define QF_MAX_ACTIVE 16U

/* Cortex-M3/M4/M7 alternative interrupt disabling with PRIMASK */

#define QF_PRIMASK_DISABLE() __asm volatile ("cpsid i")

#define QF_PRIMASK_ENABLE() __asm volatile ("cpsie i")

/* Cortex-M3/M4/M7 interrupt disabling policy, see NOTE3 and NOTE4 */

#define QF_INT_DISABLE() __asm volatile (\

"cpsid i\n" "msr BASEPRI,%0\n" "cpsie i" :: "r" (QF_BASEPRI) : )

#define QF_INT_ENABLE() __asm volatile (\

"msr BASEPRI,%0" :: "r" (0) : )

/* QF critical section entry/exit (unconditional interrupt disabling) */

/*#define QF_CRIT_STAT_TYPE not defined */

#define QF_CRIT_ENTRY(dummy) QF_INT_DISABLE()

#define QF_CRIT_EXIT(dummy) QF_INT_ENABLE()

/* BASEPRI threshold for "QF-aware" interrupts, see NOTE3 */

#define QF_BASEPRI 0x3F

/* CMSIS threshold for "QF-aware" interrupts, see NOTE5 */

#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))

/* Cortex-M3/M4/M7 provide the CLZ instruction for fast LOG2 */

#define QF_LOG2(n_) ((uint_fast8_t)(32U - __builtin_clz((unsigned)(n_))))

#endif

#define QF_CRIT_EXIT_NOP() __asm volatile ("isb")

#include "qep_port.h" /* QEP port */

#if (__ARM_ARCH == 6) /* Cortex-M0/M0+/M1(v6-M, v6S-M)? */

/* hand-optimized quick LOG2 in assembly */

uint_fast8_t QF_qlog2(uint32_t x);

#endif /* Cortex-M0/M0+/M1(v6-M, v6S-M) */

#include "qv_port.h" /* QV cooperative kernel port */

#include "qf.h" /* QF platform-independent public interface */

接下来是qs_port.h:

#ifndef QS_PORT_H

#define QS_PORT_H

/* QS time-stamp size in bytes */

#define QS_TIME_SIZE 4

/* object pointer size in bytes */

#define QS_OBJ_PTR_SIZE 4

/* function pointer size in bytes */

#define QS_FUN_PTR_SIZE 4

/*****************************************************************************

* NOTE: QS might be used with or without other QP components, in which case

* the separate definitions of the macros QF_CRIT_STAT_TYPE, QF_CRIT_ENTRY,

* and QF_CRIT_EXIT are needed. In this port QS is configured to be used with

* the other QP component, by simply including "qf_port.h" *before* "qs.h".

*/

#include "qf_port.h" /* use QS with QF */

#include "qs.h" /* QS platform-independent public interface */

#endif /* QS_PORT_H */

接下来是包含qep_port.h:

#ifndef QEP_PORT_H

#define QEP_PORT_H

/*! no-return function specifier (ARM-Clang/LLVM compiler) */

#define Q_NORETURN __attribute__ ((noreturn)) void

#include /* Exact-width types. WG14/N843 C99 Standard */

#include /* Boolean type. WG14/N843 C99 Standard */

#include "qep.h" /* QEP platform-independent public interface */

#endif /* QEP_PORT_H */

接下来是qv_port.h:

#ifndef QV_PORT_H

#define QV_PORT_H

#if (__ARM_ARCH == 6) /* Cortex-M0/M0+/M1 ? */

/* macro to put the CPU to sleep inside QV_onIdle() */

#define QV_CPU_SLEEP() do { \

__asm volatile ("wfi"); \

QF_INT_ENABLE(); \

} while (false)

#else /* Cortex-M3/M4/M4F */

/* macro to put the CPU to sleep inside QV_onIdle() */

#define QV_CPU_SLEEP() do { \

QF_PRIMASK_DISABLE(); \

QF_INT_ENABLE(); \

__asm volatile ("wfi"); \

QF_PRIMASK_ENABLE(); \

} while (false)

/* initialization of the QV kernel for Cortex-M3/M4/M4F */

#define QV_INIT() QV_init()

void QV_init(void);

#endif

#include "qv.h" /* QV platform-independent public interface */

#endif /* QV_PORT_H */

接下来是qv_port.c:

#else /* NOT Cortex-M0/M0+/M1(v6-M, v6S-M)? */

#define SCnSCB_ICTR ((uint32_t volatile *)0xE000E004)

#define SCB_SYSPRI ((uint32_t volatile *)0xE000ED14)

#define NVIC_IP ((uint32_t volatile *)0xE000E400)

/*

* Initialize the exception priorities and IRQ priorities to safe values.

*

* Description:

* On Cortex-M3/M4/M7, this QV port disables interrupts by means of the

* BASEPRI register. However, this method cannot disable interrupt

* priority zero, which is the default for all interrupts out of reset.

* The following code changes the SysTick priority and all IRQ priorities

* to the safe value QF_BASEPRI, wich the QF critical section can disable.

* This avoids breaching of the QF critical sections in case the

* application programmer forgets to explicitly set priorities of all

* "kernel aware" interrupts.

*

* The interrupt priorities established in QV_init() can be later

* changed by the application-level code.

*/

void QV_init(void) {

uint32_t n;

/* set exception priorities to QF_BASEPRI...

* SCB_SYSPRI1: Usage-fault, Bus-fault, Memory-fault

*/

SCB_SYSPRI[1] |= (QF_BASEPRI << 16) | (QF_BASEPRI << 8) | QF_BASEPRI;

/* SCB_SYSPRI2: SVCall */

SCB_SYSPRI[2] |= (QF_BASEPRI << 24);

/* SCB_SYSPRI3: SysTick, PendSV, Debug */

SCB_SYSPRI[3] |= (QF_BASEPRI << 24) | (QF_BASEPRI << 16) | QF_BASEPRI;

/* set all implemented IRQ priories to QF_BASEPRI... */

n = 8U + ((*SCnSCB_ICTR & 0x7U) << 3); /* (# NVIC_PRIO registers)/4 */

do {

--n;

NVIC_IP[n] = (QF_BASEPRI << 24) | (QF_BASEPRI << 16)

| (QF_BASEPRI << 8) | QF_BASEPRI;

} while (n != 0);

}

#endif /* NOT Cortex-M0/M0+/M1(v6-M, v6S-M)? */

这一部分的接口文件在我们的真实应用中是不需要自己移植的,当然如果你选用的MCU在qp的板级支持中没有找到,那就要你真的自己移植了。以上需要移植的文件总结下:

接下来使我们真正需要自己手动移植的部分,这一部分一般都是放在bsp.c文件中:

/* ISRs used in this project ===============================================*/

void SysTick_Handler(void) {

/* state of the button debouncing, see below */

static struct ButtonsDebouncing {

uint32_t depressed;

uint32_t previous;

} buttons = { 0U, 0U };

uint32_t current;

uint32_t tmp;

#ifdef Q_SPY

{

tmp = SysTick->CTRL; /* clear SysTick_CTRL_COUNTFLAG */

QS_tickTime_ += QS_tickPeriod_; /* account for the clock rollover */

}

#endif

QF_TICK_X(0U, &l_SysTick); /* process time events for tick rate 0 */

/* QF callbacks ============================================================*/

void QF_onStartup(void) {

/* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */

SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC);

/* assign all priority bits for preemption-prio. and none to sub-prio. */

NVIC_SetPriorityGrouping(0U);

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

* Assign a priority to EVERY ISR explicitly, see NOTE00.

* DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE!

*/

/* kernel UNAWARE interrupts, see NOTE00 */

NVIC_SetPriority(USART2_IRQn, 0U);

/* ... */

/* kernel AWARE interrupts, see NOTE00 */

NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI);

/* ... */

/* enable IRQs... */

#ifdef Q_SPY

NVIC_EnableIRQ(USART2_IRQn); /* USART2 interrupt used for QS-RX */

#endif

}

/*..........................................................................*/

void QF_onCleanup(void) {

}

/*..........................................................................*/

void QV_onIdle(void) { /* CATION: called with interrupts DISABLED, NOTE01 */

LED_GPIO_PORT->BSRRL = LED6_PIN; /* turn LED on */

__NOP(); /* wait a little to actually see the LED glow */

__NOP();

__NOP();

__NOP();

LED_GPIO_PORT->BSRRH = LED6_PIN; /* turn LED off */

#ifdef Q_SPY

QF_INT_ENABLE();

QS_rxParse(); /* parse all the received bytes */

if ((USART2->SR & USART_FLAG_TXE) != 0) { /* TXE empty? */

uint16_t b;

QF_INT_DISABLE();

b = QS_getByte();

QF_INT_ENABLE();

if (b != QS_EOD) { /* not End-Of-Data? */

USART2->DR = (b & 0xFFU); /* put into the DR register */

}

}

#elif defined NDEBUG

/* Put the CPU and peripherals to the low-power mode.

* you might need to customize the clock management for your application,

* see the datasheet for your particular Cortex-M MCU.

*/

/* !!!CAUTION!!!

* The WFI instruction stops the CPU clock, which unfortunately disables

* the JTAG port, so the ST-Link debugger can no longer connect to the

* board. For that reason, the call to __WFI() has to be used with CAUTION.

*

* NOTE: If you find your board "frozen" like this, strap BOOT0 to VDD and

* reset the board, then connect with ST-Link Utilities and erase the part.

* The trick with BOOT(0) is that it gets the part to run the System Loader

* instead of your broken code. When done disconnect BOOT0, and start over.

*/

//QV_CPU_SLEEP(); /* atomically go to sleep and enable interrupts */

QF_INT_ENABLE(); /* just enable interrupts */

#else

QF_INT_ENABLE(); /* just enable interrupts */

#endif

}

/*..........................................................................*/

Q_NORETURN Q_onAssert(char_t const * const module, int_t const loc) {

/*

* NOTE: add here your application-specific error handling

*/

(void)module;

(void)loc;

QS_ASSERTION(module, loc, 10000U); /* report assertion to QS */

NVIC_SystemReset();

}

/*以下为QS部分*/

uint8_t QS_onStartup(void const *arg) {

void QS_onCleanup(void) {

}

QSTimeCtr QS_onGetTime(void) { /* NOTE: invoked with interrupts DISABLED */

void QS_onFlush(void) {

/*..........................................................................*/

/*! callback function to reset the target (to be implemented in the BSP) */

void QS_onReset(void) {

void QS_onCommand(uint8_t cmdId,

uint32_t param1, uint32_t param2, uint32_t param3)

掌握bsp这一部分是关键,其实学习完qp移植,掌握bsp.c的必要配置也就足够了,但是QP带给我的并不止于此,真正有意思的课题是,离开了IDE的支持,你如何使用编译器来构建整个代码?

现在找客户用哪个软件
妇道的意思
最新文章
  • 电路串联和并联图解_判断串联并联电路图口诀串并联电路,电路实物图画法口诀:首首连接,尾尾相连,首进尾出。并联电路:并联电路是使在构成并联的电路元件间电流有一条以上的相互...
  • 氪金推荐榜游戏中心 | 帐号安全 | 找回密码 | 家长监控 | 用户协议 本网络游戏适合年满18岁(含)以上的玩家使用 抵制不良游戏 拒绝盗版游戏 注意自我保...
  • 南京电信最低套餐2023:5元起,满足基本需求南京电信最低套餐2023年最新资费为: 5元套餐:语音100分钟,流量1GB 10元套餐:语音200分钟,流量2GB 15元套餐:语音300分钟,流量3GB 这三个套餐...
  • 【渣滓 SCUM】快速認識 19 種全藥品功能,中文翻譯介紹彙整!《渣滓》為多人開放世界生存遊戲,擁有客製化角色系統,玩家為了生存必須進行角色知識與技能的進化,玩家必須要管理個人的營養、代謝率...
  • 大龙网值得去吗,大龙网跨境电商大龙网公司怎么样? 大龙网中国有限公司,简称大龙网,于2010年由冯剑峰先生带领一批海外精英团队创办。 大龙网是全球领先的跨境电商B2B商机...
  • 725天使数字–含义和象征意义500-999 725天使数字–含义和象征意义 数字无处不在,但您是否想知道它们的特殊功能? 确实,数字不仅仅是我们用来表达计算结果的符号;数字...
  • aht电机怎么样,了解aht电机的性能和特点AHT电机怎么样?了解AHT电机的性能和特点 AHT电机是一种高效、低噪音、低能耗的电机。它的独特设计和制造工艺使其成为许多工业应用领域中的...
  • 英语国家和地区列表关于英语的地理分布,请见“英语圈”。 下列是一个以英语作为官方语言的国家、领土及地区的目录,按人口次序排列。 英语在各个国家及地...
  • 阿凯为什么叫凯皇声明: 本站所有内容均只可用于学习参考,信息与图片素材来源于互联网, 如发现有侵权与违规内容, 请联系邮箱:yy1316@foxmail.com Copyright 2025 ...
  • 买大众CC车怎么做分期付款,首付多少月供多少1、大众CC车型的首付金额为10万,每月需还款3591元。对于0T的CC尊贵型,其售价起始为267800元。若选择首付三成的方案,则需支付80340元作为首付...