2017-09-12 3 views
1

J'exécute le code C pour arm cortex-m3 pour la carte de découverte stm32l152C mais j'ai observé que l'appel de fonction de main n'est pas poussé dans la pile. J'ai analysé le code asm de cette source mais je trouve que c'est OK. Pour mieux comprendre, s'il vous plaît regarder le code asm généré pour le code C ici:La fonction C de la main ne pousse pas sur la pile dans le bras

main.elf:  file format elf32-littlearm 

*SYMBOL TABLE: 
00000010 l d .text 00000000 .text 
00000000 l d .debug_info 00000000 .debug_info 
00000000 l d .debug_abbrev 00000000 .debug_abbrev 
00000000 l d .debug_aranges 00000000 .debug_aranges 
00000000 l d .debug_line 00000000 .debug_line 
00000000 l d .debug_str 00000000 .debug_str 
00000000 l d .comment 00000000 .comment 
00000000 l d .ARM.attributes 00000000 .ARM.attributes 
00000000 l d .debug_frame 00000000 .debug_frame 
00000000 l df *ABS* 00000000 main.c 
00000000 l df *ABS* 00000000 clock.c 
20004ffc g  .text 00000000 _STACKTOP 
**00000028 g  F .text 000000e0 SystemClock_Config** 
20000000 g  .text 00000000 _DATA_BEGIN 
20000000 g  .text 00000000 _HEAP 
**00000010 g  F .text 00000016 main** 
20000000 g  .text 00000000 _BSS_END 
00000108 g  .text 00000000 _DATAI_BEGIN 
20000000 g  .text 00000000 _BSS_BEGIN 
00000108 g  .text 00000000 _DATAI_END 
20000000 g  .text 00000000 _DATA_END 
Disassembly of section .text: 
00000010 <main>: 

#define LL_GPIO_MODE_OUTPUT 1 

void SystemInit() ; 
int main() 
{ 
    10: b580  push {r7, lr} 
    12: b082  sub sp, #8 
    14: af00  add r7, sp, #0 
    int i = 0; 
    16: 2300  movs r3, #0 
    18: 607b  str r3, [r7, #4] 
    SystemClock_Config(); 
    **1a: f000 f805 bl 28 <SystemClock_Config> 
    for(;;) 
     i++; 
    1e: 687b  ldr r3, [r7, #4] 
    20: 3301  adds r3, #1** 
    22: 607b  str r3, [r7, #4] 
    24: e7fb  b.n 1e <main+0xe> 

} 
00000028 <SystemClock_Config>: 
    *   PLLDIV       = 3 
    *   Flash Latency(WS)    = 1 
    * @retval None 
    */ 
void SystemClock_Config(void) 
{ 
    28: b480  push {r7} 
    2a: af00  add r7, sp, #0 
    SET_BIT(FLASH->ACR, FLASH_ACR_ACC64); 
    2c: 4a33  ldr r2, [pc, #204] ; (fc <SystemClock_Config+0xd4>) 
    2e: 4b33  ldr r3, [pc, #204] ; (fc <SystemClock_Config+0xd4>) 
    30: 681b  ldr r3, [r3, #0] 
    32: f043 0304 orr.w r3, r3, #4 
    36: 6013  str r3, [r2, #0] 
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, LL_FLASH_LATENCY_1); 
    38: 4a30  ldr r2, [pc, #192] ; (fc <SystemClock_Config+0xd4>) 
    3a: 4b30  ldr r3, [pc, #192] ; (fc <SystemClock_Config+0xd4>) 
    3c: 681b  ldr r3, [r3, #0] 
    3e: f043 0301 orr.w r3, r3, #1 
    42: 6013  str r3, [r2, #0]* 
} 

l'exécution des boucles autour 0x1a, 0x1c, 0x1E, 0x20 dans le registre PC.

halted: PC: 0x0000001a 
halted: PC: 0x0000001c 
halted: PC: 0x0000001e 
halted: PC: 0x00000020 
halted: PC: 0x0000001a 
halted: PC: 0x0000001c 
halted: PC: 0x0000001e 
halted: PC: 0x00000020 
halted: PC: 0x0000001a 
halted: PC: 0x0000001c 
halted: PC: 0x0000001e 
halted: PC: 0x00000020 

Il devrait passer à 0x28 (SystemClock_Config) à 0x1a.

+1

Quel est le probelem? Qu'est-ce qui ne pousse pas sur la pile? paramètres - ils sont passés si possible via les registres. 'bl' - appelle la fonction. –

+1

PS Arrête d'analyser le code généré. Premièrement parce que vous ne le comprenez pas, d'autre part parce que le compilateur est très bon dans la génération de code et vous pouvez être sûr que le code généré est correct. Si quelque chose ne fonctionne pas - c'est votre code, pas le compilateur –

+1

Vous compilez avec des optimisations désactivées, donc l'asm est moche et difficile à lire (beaucoup de stocker/recharger). Utilisez au moins «-Og» ou «-O1». –

Répondre

1

Il manque une table d'interruption à votre application. Par conséquent, le processeur lit des instructions en tant que vecteurs d'interruption et les erreurs sont répétées car ces instructions ne peuvent pas être interprétées comme des adresses invalides.

Utilisez les fichiers de support du STM32L1xx standard peripheral library pour générer un script d'éditeur de liens et un tableau d'interruption appropriés.

+0

Je ne vois pas encore que nous n'avons pas les valeurs pour l'adresse 0x00000000, 0x00000004 qui sont tout ce qui est nécessaire pour démarrer. (techniquement 0x00000004 est tout ce qui est nécessaire) .. Main commence à 0x10 ce qui est intéressant, mais le mot clé pour le succès de démarrage ou non n'est pas montré. –

+0

@old_timer Avec aucune donnée explicitement placée sur le vecteur de réinitialisation, il y a de fortes chances qu'elle ne pointe pas vers la fonction 'main'. Il pourrait pointer vers l'adresse '0x0000_001a' impliquée dans la trace du PC, par exemple. – duskwuff

+0

compris, mais il n'y a pas assez d'informations pour savoir exactement ce qui se passe réellement. –

3

Un exemple de travail tout à fait très simple:

vectors.s

.thumb 

.globl _start 
_start: 

.word 0x20001000 
.word reset 

.thumb_func 
reset: 
    bl centry 
done: b done 

so.c

unsigned int fun (unsigned int); 
unsigned int centry (void) 
{ 
    return(fun(5)+1); 
} 

fun.c

unsigned int fun (unsigned int x) 
{ 
    return(x+1); 
} 

flash.ld

MEMORY 
{ 
    rom : ORIGIN = 0x00000000, LENGTH = 0x1000 
} 

SECTIONS 
{ 
    .text : { *(.text*) } > rom 
    .rodata : { *(.rodata*) } > rom 
} 

build

arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 vectors.s -o vectors.o 
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 -mthumb -c so.c -o so.o 
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 -mthumb -c fun.c -o fun.o 
arm-none-eabi-ld -o so.elf -T flash.ld vectors.o so.o fun.o 
arm-none-eabi-objdump -D so.elf > so.list 
arm-none-eabi-objcopy so.elf so.bin -O binary 

tout le programme

00000000 <_start>: 
    0: 20001000 andcs r1, r0, r0 
    4: 00000009 andeq r0, r0, r9 

00000008 <reset>: 
    8: f000 f802 bl 10 <centry> 

0000000c <done>: 
    c: e7fe  b.n c <done> 
    ... 

00000010 <centry>: 
    10: b510  push {r4, lr} 
    12: 2005  movs r0, #5 
    14: f000 f802 bl 1c <fun> 
    18: 3001  adds r0, #1 
    1a: bd10  pop {r4, pc} 

0000001c <fun>: 
    1c: 3001  adds r0, #1 
    1e: 4770  bx lr 

une simulation du programme:

read32(0x00000000)=0x20001000 
read32(0x00000004)=0x00000009 
--- 0x00000008: 0xF000 
--- 0x0000000A: 0xF802 bl 0x0000000F 
--- 0x00000010: 0xB510 push {r4,lr} 
write32(0x20000FF8,0x00000000) 
write32(0x20000FFC,0x0000000D) 
--- 0x00000012: 0x2005 movs r0,#0x05 
--- 0x00000014: 0xF000 
--- 0x00000016: 0xF802 bl 0x0000001B 
--- 0x0000001C: 0x3001 adds r0,#0x01 
--- 0x0000001E: 0x4770 bx r14 
--- 0x00000018: 0x3001 adds r0,#0x01 
--- 0x0000001A: 0xBD10 pop {r4,pc} 
read32(0x20000FF8)=0x00000000 
read32(0x20000FFC)=0x0000000D 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 
--- 0x0000000C: 0xE7FE b 0x0000000B 

-vous qu'il est un programme un peu inutile, mais il démontre Amorçage et appelant fonctions (l'adresse de la fonction ne s'affiche pas sur la pile, quand vous faites un appel (bl), le r14 reçoit l'adresse de retour et r15 l'adresse à laquelle se connecter. si vous avez des fonctions imbriquées comme centry (le point d'entrée C principal() n'est pas un nom de fonction important, vous pouvez appeler votre point d'entrée comme vous voulez tant que votre bootstrap correspond) appelant fun, alors vous devez conserver l'adresse de retour choisissez, enregistrez-le généralement sur la pile. r4 est poussé juste pour garder la pile alignée sur une limite de 64 bits par abi. Pour votre système, vous devez définir le script de liaison pour 0x08000000 normalement (stm32). Ce qui nous manque est le début de votre binaire, pouvez-vous faire un hexdump de l'image mémoire/binaire montrant les poignées d'octet avant principal y compris les premières instructions de main? Si un programme bare metal ne fait pas les étapes de démarrage les plus simples, la première chose à faire est d'examiner le binaire où le point d'entrée ou la table vectorielle dépend de l'architecture et de voir que vous l'avez construit correctement.Dans ce cas, dans mon exemple, il s'agit d'une cortex-m, la valeur d'initialisation du pointeur de pile (si vous choisissez de l'utiliser) est 0x00000000, vous pouvez y mettre n'importe quoi et ensuite écrire simplement sur le sp si vous le souhaitez. votre choix ... alors l'adresse 0x00000004 est le vecteur de réinitialisation qui est l'adresse du code pour gérer la réinitialisation avec l'ensemble de bits pour indiquer le mode du pouce.

donc 0x00000008 | 1 = 0x00000009.

Si vous n'avez pas

0x2000xxxx 0x00000011

alors votre processeur ne va pas démarrer à droite. Je ai tellement l'habitude d'utiliser 0x08000000 que je ne me souviens pas si 0x00000000 fonctionne pour un STM, il devrait en théorie ... mais dépend de la façon dont vous chargez le flash et quel mode/état de la puce est à ce moment-là.

vous pourriez avoir besoin de créer un lien pour 0x08000000 et au moins si rien d'autre a changé

0x2000xxxx 0x08000011

comme les deux premiers mots dans votre image binaire/mémoire.

EDIT

note que vous pouvez faire un seul binaire qui peut être saisi à la fois avec un vecteur ou un bootloader

.thumb 

.thumb_func 
.global _start 
_start: 
bl reset 
.word _start 
reset: 
    ldr r0,stacktop 
    mov sp,r0 
    bl notmain 
    b hang 
.thumb_func 
hang: b . 
.align 
stacktop: .word 0x20001000 

placer une branche (bien bl pour remplir l'espace) dans l'adresse de la pile place puis chargement du pointeur de la pile plus tard.

Ou utilisez une branche

.thumb 

.thumb_func 
.global _start 
_start: 
b reset 
nop 
.word _start 
reset: 
    ldr r0,stacktop 
    mov sp,r0 
    bl notmain 
    b hang 
.thumb_func 
hang: b . 
.align 
stacktop: .word 0x20001000 
+0

la logique stm32 correspond 0x08000000 à 0x00000000 afin que votre programme d'application clignote le 0x08000011 ou quel que soit votre vecteur de réinitialisation, puis vous amène à l'adresse réelle. pas rare dans les microcontrôleurs d'avoir la zone de démarrage/vecteur remappable ... –