Kernel

Main header file for the QRT kernel.

This file contains the main declarations and macros for the QRT kernel. It includes function prototypes for initializing and starting the kernel, as well as various utility macros for time conversions and MPU configurations.

Defines

QRT_US_TO_TICKS(t)

Convert microseconds to ticks.

Parameters:
  • t – Time in microseconds.

Returns:

Time in ticks.

QRT_MS_TO_TICKS(t)

Convert milliseconds to ticks.

Parameters:
  • t – Time in milliseconds.

Returns:

Time in ticks.

QRT_TICKS_TO_US(t)

Convert ticks to microseconds.

Parameters:
  • t – Time in ticks.

Returns:

Time in microseconds.

QRT_TICKS_TO_MS(t)

Convert ticks to milliseconds.

Parameters:
  • t – Time in ticks.

Returns:

Time in milliseconds.

Typedefs

typedef qrt_u32_t (*qrt_syscall_extension_t)(void*)

Type definition for System Call Extension.

Functions

void qrt_syscall_register(qrt_u32_t (**syscalls)(void*), qrt_u32_t count)

Initialize the System Call Extensions.

Parameters:
  • syscalls – Pointer to the System Call Extensions.

  • count – Number of System Call Extensions.

    qrt_u32_t MyHardwareRead(void *param)
    {
        // Simulated hardware read operation
        return *((volatile qrt_uptr_t *)param);
    }
    
    qrt_u32_t MyHardwareWrite(void *param)
    {
        // Simulated hardware write operation
        *((volatile qrt_uptr_t *)param) = 0xDEADBEEFu;
        return 0u;
    }
    
    qrt_u32_t MyHardwareControl(void *param)
    {
        // Simulated peripheral control operation
        return 1u; // Example success response
    }
    
    void *thread(void *arg)
    {
        (void)arg;
        qrt_u32_t result;
        volatile qrt_uptr_t hardwareRegister = 0x40000000u; // Example hardware register
        qrt_syscall_extension_t syscalls[] =
        {
            MyHardwareRead,
            MyHardwareWrite,
            MyHardwareControl
        };
    
        // Initialize System Call Extensions
        qrt_syscall_register(syscalls, sizeof(syscalls) / sizeof(syscalls[0u]));
    
        for (;;)
        {
            // Invoke System Call Extensions
            result = qrt_syscall_invoke(0u, (void *)&hardwareRegister);
    
            qrt_syscall_invoke(1u, (void *)&hardwareRegister);
    
            result = qrt_syscall_invoke(2u, NULL);
        }
    
        return NULL;
    }
    

qrt_u32_t qrt_syscall_invoke(qrt_u32_t f, void *param)

Call a custom System Call.

See also

qrt_syscall_register for the use of System Call Extensions.

Parameters:
  • f – Function ID.

  • param – Pointer to the function parameter.

Returns:

Return value from the function passed as parameter.

void qrt_mpu_init(void *rom, qrt_u32_t romSize, void *ram, qrt_u32_t ramSize, void *osRom, qrt_u32_t osRomSize, void *osRam, qrt_u32_t osRamSize)

Initialize the MPU. Must be called before the kernel is started with qrt_kernelstart().

Parameters:
  • rom – Pointer to the ROM memory.

  • romSize – Size of the ROM memory in bytes.

  • ram – Pointer to the RAM memory.

  • ramSize – Size of the RAM memory in bytes.

  • osRom – Pointer to the kernel ROM memory.

  • osRomSize – Size of the kernel ROM memory in bytes.

  • osRam – Pointer to the kernel RAM memory.

  • osRamSize – Size of the kernel RAM memory in bytes.

    // Define memory regions (typically set by linker script).
    extern qrt_u32_t     __ROM_BASE;
    extern qrt_u32_t     __RAM_BASE;
    extern qrt_u32_t     __ROM_SIZE;
    extern qrt_u32_t     __RAM_SIZE;
    extern qrt_u32_t     __ROM_PRIV_BASE;
    extern qrt_u32_t     __ROM_PRIV_SIZE;
    extern qrt_u32_t     __RAM_PRIV_BASE;
    extern qrt_u32_t     __RAM_PRIV_SIZE;
    
    int main(void)
    {
        ...
    
        // Initialize MPU with predefined memory regions.
        qrt_mpu_init(&__ROM_BASE,        (qrt_u32_t)&__ROM_SIZE,
                     &__RAM_BASE,        (qrt_u32_t)&__RAM_SIZE,
                     &__ROM_PRIV_BASE,   (qrt_u32_t)&__ROM_PRIV_SIZE,
                     &__RAM_PRIV_BASE,   (qrt_u32_t)&__RAM_PRIV_SIZE);
    
        // MPU initialized, start kernel next.
        qrt_kernelstart();
    
        ...
    }
    

qrt_u32_t qrt_mpu_regionadd(pthread_t *tcb, qrt_u32_t executability, qrt_u32_t permissions, qrt_u32_t shareability, qrt_u32_t attributes, qrt_u32_t address, qrt_u32_t size)

Add a memory region to threads region table.

Parameters:
  • tcb – Pointer to the Thread Control Block.

  • executability – Executability of the region.

  • permissions – Permissions of the region.

  • shareability – Shareability of the region.

  • attributes – Attributes of the region.

  • address – Base address of the region. Must be aligned by its size.

  • size – Size of the region in bytes.

Returns:

0 if success, -1 otherwise.

pthread_t tcb;   // Thread Control Block for this thread.

void *thread(void *arg)
{
     qrt_mpu_regionadd(
         &tcb,                   // Pointer to the thread
         QRT_MPU_EXECUTE,        // Executable
         QRT_MPU_AP_FULL,        // Full access (Privileged + Unprivileged)
         QRT_MPU_SHAREABLE,      // Region is shareable
         QRT_MPU_NORM_WB_WRA,    // Cacheable, write-back, write allocate
         0x20000000u,            // Base address
         0x1000u);               // 4KB region

     for (;;)
     {
         ...
     }

     return NULL;
}

void qrt_mpu_setfaultcallback(void (*callback)(pthread_t*, qrt_u32_t, qrt_u32_t, qrt_u32_t))

Set an optional callback function that is invoked when a Memory Protection Unit (MPU) fault occurs. The registered callback allows the application to handle MPU faults, such as invalid memory accesses.

The registered callback will be called in the fault handler context, so it must be minimal and should avoid blocking operations.

Parameters:
  • callback

    Pointer to the callback function. The function must match the signature void (*callback)(

    pthread_t *thread,

    qrt_u32_t address,

    qrt_u32_t pc,

    qrt_u32_t status).
    void MyMPU_FaultHandler(pthread_t *tcb)
    {
        // Handle the MPU fault (e.g., log error, reset system, etc.).
    }
    
    int main(void)
    {
        ...
    
        qrt_mpu_setfaultcallback(MyMPU_FaultHandler);
    
        ...
    }
    

void qrt_mpu_faulthandler(void)

MPU fault handler called when a Memory Protection Unit (MPU) fault occurs.

Must be called from the Memory Management interrupt handler.

void MemManage_Handler(void)
{
   qrt_mpu_faulthandler();
}
void qrt_fpu_ctxenable(void)

Enables FPU usage for the current thread.

Marks the current thread as an FPU-using thread. Once enabled, the kernel will include the full floating-point context (S0–S31 and FPSCR) in context switching for this thread.

void *thread(void *arg)
{
    ...

    // Enable FPU context tracking for this thread.
    qrt_fpu_ctxenable();

    do_floating_point_work();

    // FPU no longer needed, disable FPU context tracking for this thread.
    qrt_fpu_ctxdisable();

    ...

    return NULL;
}

void qrt_fpu_ctxdisable(void)

Mark the current thread as not using the FPU.

This function clears the internal FPU usage flag in the thread’s TCB. When this flag is cleared, the kernel will skip saving and restoring the FPU registers (S16–S31, FPSCR) during context switches involving this thread.

See also

qrt_fpu_ctxenable for example usage.

Warning

After calling this function, the thread must not use any FPU instructions unless FPU access is explicitly re-enabled using qrt_fpu_ctxenable(). Failing to do so may result in data corruption or undefined behavior.

void qrt_kernelstart(void)

Starts the kernel.

This function transitions the system from initialization to multithreading mode, allowing the scheduler to begin executing threads. Once the kernel is started, this function does not return.

Once the kernel is started, further modifications to system initialization should not be attempted.

// Example: System initialization before starting the kernel

void *Thread(void *arg)
{
   for (;;)
   {
      // Thread work here
   }
   return NULL;
}

int main(void)
{
    ...

    // Initialize board-specific hardware
    BSP_Init();

    // Configure the System Timer with BSP-provided timer functions.
    qrt_systimer_configure(bsp_systickreload, bsp_systickgetcount, QRT_TRUE, BSP_SYSTICK_IRQN);

    // Start the kernel
    qrt_kernelstart();

    // Main turned into main thread

    // Now we can create threads, kernel objects, etc.

    // Create application threads
    pthread_create(NULL, NULL, Thread, NULL);
    
    ...
}

Note

This function must be called after all necessary system initialization is complete.

void qrt_systimer_configure(void (*reloadPtr)(qrt_u32_t), qrt_u32_t (*getCountPtr)(void), qrt_bool_t isDownCounting, qrt_s32_t irqn)

Configure the System Timer to use external source. Must be called before the kernel is started.

See also

qrt_kernelstart for example usage.

Parameters:
  • reloadPtr – Pointer to the reload function.

  • getCountPtr – Pointer to the get count function.

  • isDownCounting – QRT_TRUE if the timer counts down. QRT_FALSE if the timer counts up.

  • irqn – IRQ number of the System Timer.

void qrt_defercall(void (*deferredFunction)(qrt_u32_t), qrt_u32_t parameter)

Defer a function call to the kernel.

Parameters:
  • deferredFunction – Pointer to the deferred function.

  • parameter – Parameter to the deferred function.

    void MyDeferredFunction(qrt_u32_t param)
    {
        // Process the deferred action.
        do_some_work(param);
    
        // Kernel calls can be made here.
        sem_post(&sem);
    }
    
    void ISR_Handler(void)
    {
        // Defer function execution to kernel context.
        qrt_defercall(MyDeferredFunction, 3);
    }
    

void qrt_systimer_handler(void)

System Timer Handler. Must be called from the host timer interrupt handler.

void SysTick_Handler(void)
{
   qrt_systimer_handler();
}
void qrt_basetimer_handler(void)

Base Timer Handler. Must be called from the host timer interrupt handler.

void Timer_Handler(void)
{
   qrt_basetimer_handler();
}