2015-02-27 5 views
2

J'utilise IAR Embedded Workbench pour ARM 6.50.4 Sécurité fonctionnelle version 6.50 et je n'arrive pas à faire fonctionner une instruction en ligne. Pour l'arrière-plan: J'essaie d'implémenter un commutateur de contexte sur un ARM7TDMI en utilisant l'interruption PIT. Lorsque vous enregistrez le contexte actuel, je dois obtenir l'adresse de la pile de la fonction interrompue, ce qui est enregistré dans une variable globale C, qui est déclaré dans le même fichier c:Assemblage en ligne IAR utilisant la variable C globale

unsigned int* ptTask_CurrentTask; 

__irq void SysIrqHandler(void) 
{ 
// ... saving registers 
__asm volatile("LDR R0, %0\n\t" ::"r"(ptTask_CurrentTask)    );  
//... save the new top of stack 
//select new task and restore associated registers 
} 

D'après ce que je pouvais rassembler à partir de EWARM_DevelopmentGuide.ENU.pdf, l'instruction ci-dessus doit utiliser la syntaxe correcte. J'ai aussi essayé différentes manières de former l'instruction mais tout ce que j'ai obtenu est:

Error[og006]: Syntax error in inline assembly: "Error[401]: Operand syntax error". Maintenant, lorsque j'exporte la routine complète d'assemblage de sauvegarde de contexte dans un fichier .s séparé et appelle la fonction de c, l'instruction suivante fonctionne très bien. Depuis les instructions d'assemblage sur leur propre travail, il doit y avoir un problème avec la façon dont je fais l'instruction d'assemblage en ligne, mais je ne peux pas voir ce qui ne va pas.

+0

Juste une supposition: avez-vous essayé '=% 0' au lieu de'% 0'? – TonyK

Répondre

2

La contrainte "r" indique un registre d'usage général, donc elle finit par émettre LDR R0, Rx qui est en effet une syntaxe invalide. Si vous voulez vraiment faire le pointeur réelle déréférencement dans le code assembleur, soit intégrer la syntaxe correcte directement:

__asm volatile("LDR R0, [%0]\n\t" ::"r"(ptTask_CurrentTask)); 

Ou, mieux, utiliser la contrainte pour indiquer qu'il est un opérande de mémoire (pointeur) et laisser la syntaxe du compilateur:

__asm volatile("LDR R0, %0\n\t" ::"m"(ptTask_CurrentTask)); 

ou déchets une instruction supplémentaire et laisser le souci du compilateur de la charge:

__asm volatile("MOV R0, %0\n\t" ::"r"(*ptTask_CurrentTask)); 

Quelle que soit la façon, toucher r0 directement sans le déclarer sur la liste de clobber est probablement une mauvaise idée ...

0

Le compilateur charge déjà la valeur dans un registre pour vous en raison de la contrainte r, vous n'avez pas besoin de faire le LDR vous-même. %0 fait référence à un registre qui contient déjà la valeur ptTask_CurrentTask. Vous pouvez vérifier en utilisant l'option -S ou désassembler qu'en effet, le compilateur fait la charge pour vous:

__asm volatile("" ::"r"(ptTask_CurrentTask)); 

Devient:

ldr  r3, .L3  # these two are generated by the compiler 
    ldr  r3, [r3, #0] # for loading the operand 
    ... # here comes your asm code 
.L3: 
    .word ptTask_CurrentTask 

Dans ce cas, le compilateur choisi r3. Si vous en avez spécifiquement besoin dans r0, vous pouvez utiliser une variable de registre.