Le module kernel contient les fonctions permettant de configurer et initialiser le noyau. Cette page décrit ces fonctions et leur utilisation.
1. Synthèse des fonctions
L'ensemble de ces fonctions est déclaré dans le fichier d'en-tête mk_kernel.h :
| Fonction | Description |
|---|---|
| mk_init | Initialise le noyau. |
| mk_createIdle | Initialise les attributs de la tâche de repos. |
| mk_start | Démarre le noyau. |
| mk_stop | Arrête le noyau puis charge de nouveau le contexte de démarrage. |
| mk_restart | Redémarre le noyau. |
| mk_getTick | Renvoie le nombre de ticks écoulés depuis le démarrage du noyau. |
2. Utilisation
L'initialisation du noyau s'effectue par l'appel des fonctions mk_init, mk_createIdle et mk_start. L'extrait de code ci-dessous montre l'utilisation de ces fonctions.
#include "mk_kernel_api.h" /* ... */ /* La stack g_mkProcessStack est déclarée dans */ /* le fichier mk_system_stack.c */ /* Stack de la tâche de repos */ K_MK_UNPRIVILEGED_MEMORY uint32_t g_mkIdleStack [ K_MK_TASK_IDLE_STACK_SIZE ]; /* ... */ void mk_main ( void ) { /* Déclaration de la variable de retour */ T_mkCode l_result = K_MK_OK; /* Initialisation du noyau */ l_result = mk_init ( K_MK_MODE_FLOATING, g_mkProcessStack, K_MK_PROCESS_STACK_SIZE ); /* Initialisation de la tâche de repos */ l_result |= mk_createIdle ( g_mkIdleStack, K_MK_TASK_IDLE_STACK_SIZE, mk_task_idle, ( T_mkAddr ) "I" ); /* Lancement du noyau avec un tick de 1 ms */ l_result |= mk_start ( 27000 ); /* Après l'appel de mk_start(), le noyau est démarré. */ /* Le compteur de programme (PC) ne revient ici que suite à l'appel de la fonction mk_stop(). */ for ( ;; ) ; }
La fonction mk_init configure l'intégralité des structures du noyau ainsi que la priorité des 3 exceptions utilisées par celui-ci. Si cette fonction est exécutée avec le paramètre K_MK_MODE_FLOATING, la FPU est activée, autorisant ainsi la création de tâches flottantes.
Cette fonction reçoit aussi en paramètre l'adresse de fin (stack descendante) et la taille de la stack de démarrage. Le noyau enregistre ces caractéristiques et pourra par la suite revenir au programme principal lors de l'appel de la fonction mk_stop.
Suite à l'exécution de la fonction mk_init, l'utilisateur doit préciser au noyau les caractéristiques de la tâche de repos avec la fonction mk_createIdle. Il précise l'adresse de la stack, sa taille, sa fonction de démarrage et son argument. La tâche de repos est de type non privilégié non flottant.
void mk_task_idle ( T_mkAddr p_param ) { /* Ici p_param contient 'I' */ ( void ) p_param; /* Boucle pour toujours */ for ( ;; ) ; }
Enfin, le noyau se lance avec la fonction mk_start. Cette fonction prend en argument la valeur de comptage représentant un tick. La fréquence du timer système (SysTick) étant de 27 MHz, un tick de 1ms est configuré avec la valeur 27000 dans l'exemple ci-dessus.
Une fois le noyau lancé, l'utilisateur peut utiliser la fonction mk_getTick pour récupérer le nombre de ticks écoulés depuis le démarrage du noyau.
uint32_t l_tick = mk_getTick ( );
Le noyau peut ensuite être arrêté depuis n'importe quelle tâche en utilisant la fonction mk_stop. La fonction mk_restart pourra être appelée depuis le programme principal pour redémarrer le noyau avec une nouvelle valeur de tick.
void mk_main ( void ) { /* Some code here ... */ /* Lancement du noyau avec un tick de 1ms */ l_result |= mk_start ( 27000 ); /* Après l'appel de mk_start(), le noyau est démarré. */ /* le PC ne revient ici que suite à l'appel de la fonction mk_stop(). */ /* Redémarrage du noyau avec un tick de 10ms. */ l_result |= mk_restart( 270000 ); for ( ;; ) ; } void mk_task ( T_mkAddr p_param ) { /* Some code here ... */ /* Arrêt du noyau. */ /* Le tickRegister sera réinitialisé après cette fonction. */ l_result = mk_stop(); for ( ;; ) ; }
3. API
3.1. La fonction mk_init()
Cette fonction initialise le noyau.
Prototype :
T_mkCode mk_init ( uint32_t p_mkType, uint32_t* p_mkStack, uint32_t p_mkStackSize );
Paramètres :
- p_mkType [in]
Mode d'initialisation du noyau. Les valeurs possibles sont les suivantes :
- K_MK_MODE_DEFAULT : le noyau est initialisé en mode classique (sans calcul flottant). L'unité FPU n'est pas initialisée et aucun espace dédié n'est alloué dans la pile des tâches pour sauvegarder ses registres.
- K_MK_MODE_FLOATING : le noyau est initialisé en mode flottant, l'unité FPU est initialisée et un espace dédié est réservé dans la pile des tâches pour la sauvegarde de ses registres.
- p_mkStack [in]
Adresse de la pile du programme principal (alignée sur 32 bits).
- p_mkStackSize [in]
Taille de la pile du programme principal (en multiple de mots 32bits).
Retour :
- K_MK_OK : le noyau a été initialisé.
- K_MK_ERROR_PARAM : le noyau n'a pas été initialisé car au moins un paramètre est invalide.
Note :
- Cette fonction ne peut pas être exécutée dans un vecteur d'interruption.
3.2. La fonction mk_createIdle()
Cette fonction initialise les attributs de la tâche de repos. Cette tâche est de type non privilégié non flottant
Prototype :
T_mkCode mk_createIdle ( uint32_t* p_mkStack, uint32_t p_mkStackSize, T_mkAddress p_mkFunction, T_mkAddr p_mkArg );
Paramètres :
- p_mkStack [in]
Adresse de la pile du programme de repos (alignée sur 32 bits).
- p_mkStackSize [in]
Taille de la pile du programme de repos (en multiple de mots 32 bits).
- p_mkFunction [in]
Point d'entrée du programme de repos.
- p_mkArg [in]
Argument du programme de repos.
Retour :
- K_MK_OK : les attributs de la tâche de repos ont été initialisés.
- K_MK_ERROR_PARAM : les attributs de la tâche de repos n'ont pas été initialisés car au moins un paramètre est invalide.
- K_MK_ERROR_INIT : les attributs de la tâche de repos n'ont pas été initialisés car le noyau n'est pas initialisé.
Note :
- Cette fonction ne peut pas être exécutée dans un vecteur d'interruption.
- La tâche de repos ne peut être configurée que si le noyau n'est pas en fonctionnement.
3.3. La fonction mk_start()
Cette fonction démarre le noyau.
Prototype :
T_mkCode mk_start ( uint32_t p_mkTick );
Paramètres :
- p_mkTick [in]
Période d'un « Tick » du noyau. Si ce paramètre est nul, le timer système est inhibé.
Retour :
- K_MK_OK : le noyau a été démarré.
- K_MK_ERROR_INIT : le noyau n'a pas démarré car il n'est pas initialisé, la tâche de repos n'a pas été configurée ou le noyau est déjà lancé.
- K_MK_ERROR_RIGHT : le noyau n'a pas démarré car le niveau d'exécution du processeur n'est pas suffisant.
Note :
- Cette fonction ne peut pas être exécutée dans un vecteur d'interruption.
- Si cette fonction réussit, le résultat ne sera connu qu'après l'appel de la fonction mk_stop.
Attention :
3.4. La fonction mk_restart()
Cette fonction est identique à la fonction mk_start() à la différence qu'elle permet de redémarrer l'activité du noyau après un appel de la fonction mk_stop().
Prototype :
T_mkCode mk_restart ( uint32_t p_mkTick );
Paramètres :
- p_mkTick [in]
Période d'un « Tick » du noyau. Si ce paramètre est nul, le timer système est inhibé.
Retour :
- K_MK_OK : le noyau a été redémarré.
- K_MK_ERROR_INIT : le noyau n'a pas été redémarré car il n'est pas initialisé, la tâche de repos n'a pas été configurée ou le noyau est déjà lancé.
- K_MK_ERROR_RIGHT : le noyau n'a pas été redémarré car le niveau d'exécution du processeur n'est pas suffisant.
Note :
- Cette fonction ne peut pas être exécutée dans un vecteur d'interruption.
- Si cette fonction réussit, le résultat ne sera connu qu'après un appel de la fonction mk_stop().
Attention :
⚠️
- Cette fonction entre dans une section critique lors de son exécution. Elle masque temporairement les interruptions de priorité numérique supérieure ou égale à K_MK_SCHEDULER_MASK_PRIORITY. Le masque est automatiquement levé avant d'en sortir.
3.5. La fonction mk_stop()
Cette fonction arrête le noyau. Suite à l'arrêt, le contexte de la tâche principale est chargé en mémoire.
Prototype :
T_mkCode mk_stop ( void );
Retour :
- K_MK_OK : le noyau a été arrêté.
- K_MK_ERROR_INIT : le noyau n'a pas été arrêté car il n'est pas en fonctionnement.
- K_MK_ERROR_RIGHT : le noyau n'a pas été arrêté car le niveau d'exécution du processeur n'est pas suffisant.
Note :
- Cette fonction ne peut pas être exécutée dans un vecteur d'interruption.
- Si cette fonction réussit, le résultat ne sera connu qu'après un appel de la fonction mk_restart().
Attention :
⚠️
- Cette fonction entre dans une section critique lors de son exécution. Elle masque temporairement les interruptions de priorité numérique supérieure ou égale à K_MK_SCHEDULER_MASK_PRIORITY. Le masque est automatiquement levé avant d'en sortir.
3.6. La fonction mk_getTick()
Cette fonction retourne la valeur du tick système.
Prototype :
uint32_t mk_getTick ( void );
Retour :
- Cette fonction retourne la valeur du tick système. En raison des mécanismes de préemption, la valeur renvoyée par cette fonction n'est pas forcément égale à la valeur stockée dans l'ordonnanceur.
3.7. Les définitions
L'utilisateur peut personnaliser la configuration du noyau à l'aide des définitions suivantes :
| Définition | Description | Valeur |
|---|---|---|
| K_MK_ |
Cette constante configure le masque du registre BASEPRI pour les appels système. Elle masque les interruptions de priorité supérieure ou égale à la valeur définie. Elle doit être comprise entre 1 et 15. | 8 |
| K_MK_ |
Cette constante fixe la priorité du vecteur d'interruption SVC (valeur de 0 à 14, obligatoirement inférieure à K_MK_SCHEDULER_MASK_PRIORITY). | 7 |
| K_MK_ |
Cette constante configure le nombre de priorités gérées par l'ordonnanceur. Sa valeur peut varier de 1 à 32. | 10 |
⚠️