Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using qpc on armv7 processor. #47

Open
andy27182 opened this issue Dec 25, 2024 · 2 comments
Open

Using qpc on armv7 processor. #47

andy27182 opened this issue Dec 25, 2024 · 2 comments

Comments

@andy27182
Copy link

andy27182 commented Dec 25, 2024

Hi, I am learning the qpc framework and trying to apply it on the ARM v7 processor. By studying the bsp.c and port files on different processors, I can understand the core content of qpc transplantation.
I noticed that the main difference between transplanting the qv and qk kernels on the arm cortex-R series processor is the processing of interrupts. The qv kernel uses the interrupt service function provided by HAL, while the qk kernel uses a custom interrupt processing process, and emphasizes __stackless __arm, what is the reason for this design? Can I use similar code to apply on arm v7.

#ifdef __ARMVFP__
#define QK_IRQ_BEGIN(name_)              \
    __stackless __arm void name_(void) { \
    __asm(" SUB LR, LR, #4\n"            \
    " SRSDB #31!\n"                      \
    " CPS #31\n"                         \
    " PUSH {R0-R3, R12}");               \
    __asm(" FMRX R12, FPSCR\n"           \
    " STMFD SP!, {R12}\n"                \
    " FMRX R12, FPEXC\n"                 \
    " STMFD SP!, {R12}\n"                \
    " FSTMDBD SP!, {D0-D7}");            \
    __asm(" AND R3, SP, #4\n"            \
    " SUB SP, SP, R3\n"                  \
    " PUSH {R3, LR}\n");                 \
    ++QK_priv_.intNest; {
#else
#define QK_IRQ_BEGIN(name_)              \
    __stackless __arm void name_(void) { \
    __asm(" SUB LR, LR, #4\n"            \
    " SRSDB #31!\n"                      \
    " CPS #31\n"                         \
    " PUSH {R0-R3, R12}");               \
    __asm(" AND R3, SP, #4\n"            \
    " SUB SP, SP, R3\n"                  \
    " PUSH {R3, LR}\n");                 \
    ++QK_priv_.intNest; {
#endif

// QK-specific Interrupt Request handler END
#ifdef __ARMVFP__
#define QK_IRQ_END()                  \
    } --QK_priv_.intNest;             \
    if (QK_priv_.intNest == 0U) {     \
        if (QK_sched_() != 0U) {      \
            QK_activate_();           \
        }                             \
    }                                 \
    __asm(" POP {R3, LR}\n"           \
    " ADD SP, SP, R3");               \
    __asm(" FLDMIAD SP!, {D0-D7}\n"   \
    " LDMFD SP!, {R12}\n"             \
    " FMXR FPEXC, R12 \n"             \
    " LDMFD SP!, {R12} \n"            \
    " FMXR FPSCR, R12");              \
    __asm(" POP {R0-R3, R12}\n"       \
    " RFEIA SP!");                    \
}
#else
#define QK_IRQ_END()                  \
    } --QK_priv_.intNest;             \
    if (QK_priv_.intNest == 0U) {     \
        if (QK_sched_() != 0U) {      \
            QK_activate_();           \
        }                             \
    }                                 \
    __asm(" POP {R3, LR}\n"           \
    " ADD SP, SP, R3");               \
    __asm(" POP {R0-R3, R12}\n"       \
    " RFEIA SP!");                    \
}
#endif
@quantum-leaps
Copy link
Contributor

Hi Andy,
First, what do you mean by "arm v7"? If you mean ARMv7-M, then the right ports to look will be "qpc/ports/arm-cm". If you mean ARMv7-R, then perhaps "qpc/ports/arm-cr". But in general, this low-level is NOT the right way to get started with the QP frameworks. The right way is to build and run one of the provided examples ("qpc/examples" directory).

Now, regarding the differences between QV and QK kernels: QV is non-preemptive and works similar to the "superloop" (a.ka. main+ISRs). Therefore ISRs can be generated by the compiler. QK is a preemptive kernel, and therefore the scheduler must be activate at the end of every ISR. The assembly code for ISR prolog and epilogue (for ARM Cortex-R that you're referencing) create a particular stack layout and therefore is marked as __stackless__. All this is only necessary for ARMv7-R and unnecessary for ARMv7-M.

I hope that my comments make sense to you.

--MMS

@andy27182
Copy link
Author

andy27182 commented Dec 26, 2024

Thank you for your reply. I've just finished reading "Practical UML Statecharts in C/C++". Combined with your answer, I've understood the differences in the processing between the QV kernel and the QK kernel. The QV kernel schedules tasks after the context of a task has completely ended, while the QK kernel hopes to schedule tasks according to the task prio when an interrupt ends. This may disrupt the original stack arrangement of the compiler, so it's necessary to manually save and restore the task context when the task is switched back.

I'm sorry that I didn't describe my question clearly. I'm currently using a multi - core processor with an ARMv7 - A architecture and programming for one of the CPU cores. The traditional working mode is still the foreground - background mode. After learning about the QPC framework, I think the QPC framework is applicable in many scenarios, including the use of A - series processors. I would like to ask you whether the interrupt handling of the ARMv7 - R architecture is applicable to ARMv7 - A.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants