99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

程序小白
認證:優質創作者
所在專題目錄 查看專題
【第十篇】QF框架之事件管理——事件派發機制
【第十一篇】QF框架之事件管理——事件內存(上)
【第十二篇】QF框架之事件管理——事件內存(中)
【第十三篇】QF框架之事件管理——事件內存(下)
【第十四篇】QP移植與配置
【第十五篇】利用QM逆向分析ship活動對象
作者動態 更多
基于stm32采用PWM驅動伺服控制器學習筆記
05-13 15:25
基于STM32驅動TM1638學習筆記——軟件篇
04-19 12:42
基于TM1638驅動8位數碼管設計分享
02-24 11:26
RT-Thread驅動之路: Studio創建FAL分區⑤
01-02 08:30
RT-Thread驅動之路: Studio 掛載通用SPI flash④
2024-12-23 13:41

【第十四篇】QP移植與配置

   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 <stdint.h>  /* Exact-width types. WG14/N843 C99 Standard */
#include <stdbool.h> /* 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的支持,你如何使用編譯器來構建整個代碼?

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 4
收藏 5
關注 151
成為作者 賺取收益
全部留言
0/200
  • chaochao1545 2021-01-18 09:18
    講的真好!
    回復
主站蜘蛛池模板: 8x8ⅹ永久免费视频 精品无人码麻豆乱码1区2区 | 久久精品一二区 | 97国产情侣爱久久免费观看 | 久久的色 | 爆乳3把你榨干哦ova在线观看 | 欧美交换配乱吟粗大 | 免费A级毛片无码A∨中文字幕 | 国产激情视频一区二区 | 日韩精品视频在线观看视频 | 国产午夜在线播放 | 一本一道波多野结衣av黑人 | 日产中文字幕在线观看 | xxxxx亚洲 | 国产精品福利一区 | 女人和拘做受全程看免费软件 | 熟妇的奶头又大又粗视频 | 久久精品国产99久久99久久久 | 日韩午夜视频免费 | 一区二区三区四区影院 | 欧美秋霞 | 久久99精品国产麻豆宅宅 | 多人调教到高潮失禁h重口文 | 国产理论一区二区三区 | 亚洲尺码欧洲尺码有哪些品牌好 | gogo大胆无码免费视频列表 | 亚洲欧美日韩专区 | YW尤物AV无码国产在线观看 | 爆乳无码中文字幕在线观看 | AV人摸人人人澡人人超碰手机版 | 中文字幕第31页 | 国产一区二区三区18 | 欧美一区二区三区a | 男人猛躁女人免视频 | 久久久亚洲精品中文字幕 | 日本少妇高潮正在线播放 | 在线观看你懂的网址 | 日本成片区免费久久 | 一本一本久久A久久综合精品蜜桃 | av国产精品| 日欧在线 | 国产在线va|