Kode pembuka tanpa-logam untuk inisialisasi wilayah Cortex M3 .bss

10

Saya telah mengembangkan terinspirasi dari sini kode start-up logam telanjang untuk arm cortex M3. Namun, saya menghadapi masalah berikut: misalkan saya mendeklarasikan variabel global yang tidak diinisialisasi, misalnya tipe unsigned char di main.c

#include ...
unsigned char var; 
...
int main()
{
 ...
}

ini membuat wilayah .bss di STM32 f103 mulai dari _BSS_START = 0x20000000 dan berakhir di _BSS_END = 0x20000001. Sekarang, kode mulai

    unsigned int * bss_start_p = &_BSS_START; 
    unsigned int * bss_end_p = &_BSS_END;

    while(bss_start_p != bss_end_p)
    {
        *bss_start_p = 0;
        bss_start_p++;
    }

mencoba menginisialisasi ke nol seluruh wilayah .bss. Namun, di dalam itu sementara loop pointer meningkat dengan 4 byte, oleh karena itu setelah satu langkah bss_start_p = 0x20000004 maka itu akan selalu berbeda dari bss_end_p yang mengarah ke loop infinite dll.

Apakah ada solusi standar untuk ini? Apakah saya seharusnya "memaksa" entah bagaimana dimensi wilayah .bss menjadi kelipatan 4? Atau haruskah saya menggunakan pointer ke unsigned char untuk berjalan melalui wilayah .bss? Mungkin sesuatu seperti:

    unsigned char * bss_start_p = (unsigned char *)(&_BSS_START); 
    unsigned char * bss_end_p = (unsigned char *)(&_BSS_END);

    while(bss_start_p != bss_end_p)
    {
        *bss_start_p = 0;
        bss_start_p++;
    }
```
C Marius
sumber
gunakan kurang dari. bootstraps ditulis dalam rakitan karena suatu alasan. pertama sekarang Anda telah membuat masalah data. itu hal ayam dan telur untuk menggunakan / menganggap bahwa C bekerja Anda bergantung pada .text, .bs dan. Data minimal, tetapi Anda menulis kode C yang memastikan kode C akan bekerja, menggunakan hal-hal dalam kode C yang membutuhkan bootstrap mungkin ditulis dalam kode C yang mengandalkan kerja C.
old_timer
kode untuk menyalin. data lebih sangat mirip dengan .bss, tetapi jika Anda menulisnya seperti kode di atas maka Anda perlu. data disalin untuk menyalin. data berakhir.
old_timer

Jawaban:

15

Seperti yang Anda duga, ini terjadi karena tipe data int yang tidak ditandatangani berukuran 4 byte. Setiap *bss_start_p = 0;pernyataan sebenarnya membersihkan empat byte dari area bss.

Rentang memori bss perlu disejajarkan dengan benar. Anda cukup mendefinisikan _BSS_START dan _BSS_END sehingga ukuran totalnya adalah kelipatan empat, tetapi ini biasanya ditangani dengan memungkinkan skrip tautan untuk menentukan lokasi mulai dan berhenti.

Sebagai contoh, inilah bagian tautan di salah satu proyek saya:

.bss (NOLOAD) : ALIGN(4)
{
    __bss_start__ = .;
    *(.bss)
    . = ALIGN(4);
    __bss_end__ = .;
} >RAM

The ALIGN(4)pernyataan mengurus hal-hal.

Juga, Anda mungkin ingin berubah

while(bss_start_p != bss_end_p)

untuk

while(bss_start_p < bss_end_p).

Ini tidak akan mencegah masalah (karena Anda mungkin menghapus 1-3 byte lebih banyak dari yang Anda inginkan), tetapi itu bisa meminimalkan dampak :)

bitmack
sumber
@ CMarius Setelah refleksi, saya pikir ide pointer char Anda akan bekerja dengan baik, meskipun itu akan membutuhkan lebih banyak siklus. Tapi saya tidak yakin apakah akan ada masalah berikutnya dengan area memori berikutnya yang tidak selaras, jadi saya tidak akan menyebutkannya dalam jawaban saya ...
bitsmack
1
while(bss_start_p < bss_end_p - 1)diikuti oleh kliring byte-bijaksana dari sisa memori yang tersisa akan menghilangkan kekhawatiran terakhir.
glglgl
4

Solusi standar adalah memset():

#include <string.h>
memset(&_BSS_START, 0, &_BSS_END - &_BSS_START)

Jika Anda tidak dapat menggunakan pustaka standar, maka Anda harus memutuskan apakah tidak masalah dalam kasus Anda untuk membulatkan ukuran area memori hingga 4 byte dan terus menggunakan unsigned int *; atau jika Anda harus tegas tentang hal itu, dalam hal ini Anda harus menggunakannya unsigned char *.

Jika Anda benar-benar mengumpulkan ukuran, seperti pada putaran pertama Anda, maka bss_start_pmemang mungkin berakhir lebih besar dari bss_end_ptetapi itu mudah untuk berurusan dengan perbandingan yang lebih rendah daripada <tes ketidaksetaraan.

Tentu saja, Anda juga dapat mengisi sebagian besar area memori dengan transfer 32-bit, dan hanya beberapa byte terakhir dengan transfer 8-bit, tetapi itu lebih berfungsi untuk mendapatkan sedikit keuntungan, terutama di sini jika hanya sepotong kode startup.

ilkkachu
sumber
1
Setuju sangat banyak dengan penggunaan memset(). Tapi penyelarasan ke 4 byte lebih atau kurang harus. Jadi mengapa tidak melakukannya?
Codo
3
sama sekali tidak bentuk atau bentuk adalah solusi standar untuk bootstrap untuk menggunakan memset, itu gila.
old_timer
Anda tidak menggunakan bahasa yang sama untuk
mem
2
kode bootstrap dan skrip linker sudah sangat banyak menikah, Anda akan menemukan bahwa skrip linker umum dan ukuran .bss setidaknya pada batas 4 byte untuk meningkatkan isi (dalam bootstrap) dengan 4x lebih byte pada suatu waktu instruksi (dengan asumsi (minimum) 32 bit bus yang tipikal untuk arm tetapi ada pengecualian)
old_timer
3
@old_timer, fungsi C standar untuk mengatur memori ke nilai tertentu adalah memset(), dan C adalah apa yang tampaknya mereka pemrograman. Implementasi sederhana memset()juga cukup banyak hanya loop itu, tidak seperti itu tergantung pada banyak hal lain. Karena itu adalah mikrokontroler, saya juga berasumsi bahwa tidak ada tautan dinamis atau semacamnya yang terjadi (dan melihat tautannya, tidak ada, itu hanya panggilan untuk main()setelah pengulangan zeroing), sehingga kompiler harus mampu menjatuhkan memset()di sana bersama dengan àny fungsi lain (atau untuk mengimplementasikannya sebaris).
ilkkachu
4

Ubah saja !=ke <. Itu biasanya pendekatan yang lebih baik, karena ini berhubungan dengan masalah seperti ini.

Elliot Alderson
sumber
3

Ada banyak situs dan contoh lainnya. Ribuan jika tidak puluhan ribu. Ada c library yang terkenal dengan skrip linker dan kode boostrap, newlib, glibc khususnya tetapi ada yang lain yang dapat Anda temukan. Bootstraping C dengan C tidak masuk akal.

Pertanyaan Anda telah dijawab, Anda mencoba melakukan perbandingan tepat pada hal-hal yang mungkin tidak tepat, mungkin tidak dimulai pada batas yang diketahui atau berakhir pada batas yang diketahui. Jadi Anda dapat melakukan hal yang kurang dari itu tetapi jika kode tidak bekerja dengan perbandingan yang tepat maka itu berarti Anda mem-posting .bss ke bagian berikutnya yang mungkin atau mungkin tidak menyebabkan hal-hal buruk terjadi, jadi cukup ganti dengan yang kurang dari bukan solusinya.

Jadi begini TL; DR baik-baik saja. Anda tidak mem-bootstrap bahasa dengan bahasa itu, Anda bisa lolos dengan itu, tetapi Anda bermain dengan api saat melakukannya. Jika Anda baru belajar bagaimana melakukan ini, Anda harus berhati-hati, bukan keberuntungan bodoh atau fakta yang belum Anda temukan.

Script linker dan kode bootstrap memiliki hubungan yang sangat intim, mereka menikah, bergabung di pinggul, Anda tidak mengembangkan satu tanpa yang lain yang menyebabkan kegagalan besar. Dan sayangnya skrip linker ditentukan oleh linker dan bahasa assembly didefinisikan oleh assembler sehingga Anda mengubah toolchain berharap harus menulis ulang keduanya. Mengapa bahasa assembly? Tidak perlu bootstrap, bahasa yang dikompilasi umumnya dilakukan. C tidak jika Anda tidak ingin membatasi penggunaan langauge, saya akan mulai dengan sesuatu yang sangat sederhana yang memiliki persyaratan spesifik toolchain minimal, Anda tidak menganggap. , cobalah untuk menghindarinya, ini tidak berlaku untuk variabel lokal, jadi Anda harus tahu kapan Anda menggunakannya. jadi mengapa kita berbicara tentang .bs dan .data ??? (global bagus untuk pekerjaan level ini tapi itu topik lain)) aturan lain untuk solusi sederhana adalah jangan menginisialisasi variabel dalam deklarasi, lakukan dalam kode. ya membakar lebih banyak flash, Anda biasanya memiliki banyak, tidak semua variabel diinisialisasi dengan konstanta pula yang akhirnya menghabiskan instruksi.

Anda dapat mengetahui dari desain cortex-m bahwa mereka mungkin berpikir tidak ada kode bootstrap sama sekali sehingga tidak ada .data atau .bss yang mendukung. Kebanyakan orang yang menggunakan global tidak dapat hidup tanpa hal ini:

Saya bisa membuat ini lebih minimal tetapi contoh fungsional minimal untuk semua korteks-ms menggunakan gnu toolchain, saya tidak ingat versi apa yang bisa Anda mulai dengan 5.xx atau lebih hingga 9.xx saat ini. Saya mengganti skrip linker di suatu tempat sekitar 3. xx atau 4.xx ketika saya belajar lebih banyak dan ketika gnu mengubah sesuatu yang merusak yang pertama saya.

bootstrap:

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done

.thumb_func
reset:
    bl centry
    b done

.thumb_func
done:   b .

.thumb_func
.globl bounce
bounce:
    bx lr

titik masuk ke dalam kode C:

void bounce ( unsigned int );

unsigned int a;

int centry ( void )
{
    a = 7;
    bounce(a);
    return(0);
}

skrip tautan.

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

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

Semua ini bisa lebih kecil dan masih berfungsi, menambahkan beberapa hal tambahan di sini hanya untuk melihatnya di tempat kerja.

build dan tautan yang dioptimalkan.

00000000 <_start>:
   0:   20001000
   4:   00000015
   8:   0000001b
   c:   0000001b
  10:   0000001b

00000014 <reset>:
  14:   f000 f804   bl  20 <centry>
  18:   e7ff        b.n 1a <done>

0000001a <done>:
  1a:   e7fe        b.n 1a <done>

0000001c <bounce>:
  1c:   4770        bx  lr
    ...

00000020 <centry>:
  20:   2207        movs    r2, #7
  22:   b510        push    {r4, lr}
  24:   4b04        ldr r3, [pc, #16]   ; (38 <centry+0x18>)
  26:   2007        movs    r0, #7
  28:   601a        str r2, [r3, #0]
  2a:   f7ff fff7   bl  1c <bounce>
  2e:   2000        movs    r0, #0
  30:   bc10        pop {r4}
  32:   bc02        pop {r1}
  34:   4708        bx  r1
  36:   46c0        nop         ; (mov r8, r8)
  38:   20000000    andcs   r0, r0, r0

Disassembly of section .bss:

20000000 <a>:
20000000:   00000000    andeq   r0, r0, r0

untuk beberapa vendor Anda ingin menggunakan 0x08000000 atau 0x01000000 atau alamat serupa lainnya saat flash dipetakan di sana dan dicerminkan ke 0x00000000 dalam beberapa mode boot. beberapa hanya memiliki banyak flash yang dicerminkan pada 0x00000000 sehingga Anda ingin memiliki titik tabel vektor pada ruang flash aplikasi bukan nol. karena ini adalah tabel vektor semua bekerja.

Catatan pertama, korteks-ms adalah mesin ibu jari saja dan untuk alasan apa pun mereka menerapkan alamat fungsi ibu jari, yang berarti lsbit aneh. Ketahui alat Anda, arahan .thumb_func memberi tahu assembler gnu bahwa label berikutnya adalah alamat fungsi ibu jari. melakukan hal +1 dalam tabel akan menyebabkan kegagalan, jangan tergoda untuk melakukannya, lakukan dengan benar. ada cara assembler gnu lain untuk menyatakan fungsi ini adalah pendekatan minimal.

   4:   00000015
   8:   0000001b
   c:   0000001b
  10:   0000001b

itu tidak akan boot jika Anda tidak mendapatkan tabel vektor dengan benar.

bisa dibilang hanya perlu stack pointer vector (bisa meletakkan apa saja di sana jika Anda ingin mengatur stack pointer sendiri dalam kode) dan reset vektor. Saya menempatkan empat di sini tanpa alasan tertentu. Biasanya menempatkan 16 tetapi ingin mempersingkat contoh ini.

Jadi, apa yang minimal yang perlu dilakukan bootstrap C? 1. mengatur penunjuk tumpukan 2. nol .bss 3. menyalin. Data 4. cabang ke atau memanggil titik entri C

titik masuk C biasanya disebut main (). tetapi beberapa toolchain melihat main () dan menambahkan sampah tambahan ke kode Anda. Saya sengaja menggunakan nama yang berbeda. YMMV.

salinan data tidak diperlukan jika ini semua berbasis ram. menjadi mikrokontroler korteks-m secara teknis dimungkinkan tetapi tidak mungkin sehingga salinan data diperlukan ..... jika ada. data.

Contoh pertama saya dan gaya pengkodean adalah untuk tidak bergantung pada data atau .bss, seperti dalam contoh ini. Arm menangani stack pointer sehingga satu-satunya yang tersisa adalah memanggil titik masuk. Saya suka memilikinya sehingga titik masuk dapat kembali, banyak orang berpendapat Anda tidak boleh melakukan itu. Anda bisa melakukan ini:

.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word centry
.word done
.word done
.word done

dan tidak kembali dari centry () dan tidak memiliki kode reset handler.

00000020 <centry>:
  20:   2207        movs    r2, #7
  22:   b510        push    {r4, lr}
  24:   4b04        ldr r3, [pc, #16]   ; (38 <centry+0x18>)
  26:   2007        movs    r0, #7
  28:   601a        str r2, [r3, #0]
  2a:   f7ff fff7   bl  1c <bounce>
  2e:   2000        movs    r0, #0
  30:   bc10        pop {r4}
  32:   bc02        pop {r1}
  34:   4708        bx  r1
  36:   46c0        nop         ; (mov r8, r8)
  38:   20000000    andcs   r0, r0, r0

Disassembly of section .bss:

20000000 <a>:
20000000:   00000000

linker telah meletakkan hal-hal di mana kita bertanya Dan secara keseluruhan kami memiliki program yang berfungsi penuh.

Jadi pertama-tama kerjakan skrip tautan:

MEMORY
{
    bob : ORIGIN = 0x00000000, LENGTH = 0x1000
    ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > bob

    .rodata : { *(.rodata*) } > bob

   __data_rom_start__ = .;
   .data : {
    __data_start__ = .;
    *(.data*)
   } > ted AT > bob
   __data_end__ = .;
   __data_size__ = __data_end__ - __data_start__;

   .bss  : {
   __bss_start__ = .;
   *(.bss*)
   } > ted
   __bss_end__ = .;
   __bss_size__ = __bss_end__ - __bss_start__;

}

menekankan bahwa nama rom dan ram tidak berarti mereka hanya menghubungkan titik-titik untuk penghubung antar bagian.

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done

.thumb_func
reset:
    bl centry
    b done

.thumb_func
done:   b .

.thumb_func
.globl bounce
bounce:
    bx lr

.align
.word __data_rom_start__
.word __data_start__
.word __data_end__
.word __data_size__

tambahkan beberapa item sehingga kita dapat melihat apa yang dilakukan alat

void bounce ( unsigned int );

unsigned int a;

unsigned int b=4;
unsigned char c=5;

int centry ( void )
{
    a = 7;
    bounce(a);
    return(0);
}

tambahkan beberapa item untuk ditempatkan di bagian tersebut. dan dapatkan

Disassembly of section .text:

00000000 <_start>:
   0:   20000800    andcs   r0, r0, r0, lsl #16
   4:   00000015    andeq   r0, r0, r5, lsl r0
   8:   0000001b    andeq   r0, r0, r11, lsl r0
   c:   0000001b    andeq   r0, r0, r11, lsl r0
  10:   0000001b    andeq   r0, r0, r11, lsl r0

00000014 <reset>:
  14:   f000 f80c   bl  30 <centry>
  18:   e7ff        b.n 1a <done>

0000001a <done>:
  1a:   e7fe        b.n 1a <done>

0000001c <bounce>:
  1c:   4770        bx  lr
  1e:   46c0        nop         ; (mov r8, r8)
  20:   0000004c    andeq   r0, r0, r12, asr #32
  24:   20000000    andcs   r0, r0, r0
  28:   20000008    andcs   r0, r0, r8
  2c:   00000008    andeq   r0, r0, r8

00000030 <centry>:
  30:   2207        movs    r2, #7
  32:   b510        push    {r4, lr}
  34:   4b04        ldr r3, [pc, #16]   ; (48 <centry+0x18>)
  36:   2007        movs    r0, #7
  38:   601a        str r2, [r3, #0]
  3a:   f7ff ffef   bl  1c <bounce>
  3e:   2000        movs    r0, #0
  40:   bc10        pop {r4}
  42:   bc02        pop {r1}
  44:   4708        bx  r1
  46:   46c0        nop         ; (mov r8, r8)
  48:   20000008    andcs   r0, r0, r8

Disassembly of section .data:

20000000 <c>:
20000000:   00000005    andeq   r0, r0, r5

20000004 <b>:
20000004:   00000004    andeq   r0, r0, r4

Disassembly of section .bss:

20000008 <a>:
20000008:   00000000    andeq   r0, r0, r0

inilah hal-hal yang kami cari dalam percobaan itu (perhatikan tidak ada alasan untuk benar-benar memuat atau menjalankan kode apa pun ... ketahui alat Anda, pelajari)

  1c:   4770        bx  lr
  1e:   46c0        nop         ; (mov r8, r8)
  20:   0000004c    andeq   r0, r0, r12, asr #32
  24:   20000000    andcs   r0, r0, r0
  28:   20000008    andcs   r0, r0, r8
  2c:   00000008    andeq   r0, r0, r8

jadi apa yang kita pelajari di sini adalah bahwa posisi variabel sangat sensitif dalam skrip gnu linker. perhatikan posisi data_rom_start vs data_start tetapi mengapa data_end berfungsi? Aku akan membiarkan kamu mencari tahu itu. Sudah mengerti mengapa orang mungkin tidak mau harus mengacaukan dengan skrip linker dan hanya mendapatkan pemrograman sederhana ...

jadi hal lain yang kami pelajari di sini adalah bahwa linker menyelaraskan data_rom_start bagi kami, kami tidak memerlukan ALIGN (4) di sana. Haruskah kita berasumsi bahwa itu akan selalu berhasil?

Perhatikan juga bahwa padded pada jalan keluar ke, kita memiliki 5 byte. Data tetapi padded ke 8. Tanpa ALIGN () kita sudah bisa melakukan copy menggunakan kata-kata. Berdasarkan apa yang kita lihat dengan rantai alat ini di komputer saya hari ini, mungkinkah itu benar untuk masa lalu dan masa depan? Siapa tahu, bahkan dengan ALIGNs perlu memeriksa secara berkala untuk mengonfirmasi beberapa versi baru yang tidak merusak, mereka akan melakukannya dari waktu ke waktu.

dari percobaan itu mari kita beralih ke ini hanya untuk aman.

MEMORY
{
    bob : ORIGIN = 0x00000000, LENGTH = 0x1000
    ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > bob

    .rodata : { *(.rodata*) } > bob

   . = ALIGN(4);
   __data_rom_start__ = .;
   .data : {
    __data_start__ = .;
    *(.data*)
   . = ALIGN(4);
   __data_end__ = .;
   } > ted AT > bob
   __data_size__ = __data_end__ - __data_start__;

   . = ALIGN(4);
   .bss  : {
   __bss_start__ = .;
   *(.bss*)
   . = ALIGN(4);
   __bss_end__ = .;
   } > ted
   __bss_size__ = __bss_end__ - __bss_start__;

}

memindahkan ujung ke dalam agar konsisten dengan apa yang dilakukan orang lain. Dan itu tidak mengubahnya:

0000001c <bounce>:
  1c:   4770        bx  lr
  1e:   46c0        nop         ; (mov r8, r8)
  20:   0000004c    andeq   r0, r0, r12, asr #32
  24:   20000000    andcs   r0, r0, r0
  28:   20000008    andcs   r0, r0, r8
  2c:   00000008    andeq   r0, r0, r8

satu lagi tes cepat:

.globl bounce
bounce:
    nop
    bx lr

memberi

0000001c <bounce>:
  1c:   46c0        nop         ; (mov r8, r8)
  1e:   4770        bx  lr
  20:   0000004c    andeq   r0, r0, r12, asr #32
  24:   20000000    andcs   r0, r0, r0
  28:   20000008    andcs   r0, r0, r8
  2c:   00000008    andeq   r0, r0, r8

tidak perlu mengisi antara bouncing dan tanda

Ohh, benar, saya ingat sekarang mengapa saya tidak memasukkan _end__ di dalamnya. karena TIDAK BEKERJA.

MEMORY
{
    bob : ORIGIN = 0x00000000, LENGTH = 0x1000
    ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > bob

    .rodata : { *(.rodata*) } > bob

   . = ALIGN(4);
   __data_rom_start__ = .;
   .data : {
    __data_start__ = .;
    *(.data*)
   } > ted AT > bob
   . = ALIGN(4);
   __data_end__ = .;
   __data_size__ = __data_end__ - __data_start__;

   . = ALIGN(4);
   .bss  : {
   __bss_start__ = .;
   *(.bss*)
   } > ted
   . = ALIGN(4);
   __bss_end__ = .;
   __bss_size__ = __bss_end__ - __bss_start__;

}

beberapa kode sederhana, tetapi sangat portabel untuk menikah dengan skrip linker ini

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done

.thumb_func
reset:

    ldr r0,blen
    cmp r0,#0
    beq bss_zero_done
    ldr r1,bstart
    mov r2,#0
bss_zero:
    stmia r1!,{r2}
    sub r0,#4
    bne bss_zero
bss_zero_done:

    ldr r0,dlen
    cmp r0,#0
    beq data_copy_done
    ldr r1,rstart
    ldr r2,dstart
data_copy:
    ldmia r1!,{r3}
    stmia r2!,{r3}
    sub r0,#4
    bne data_copy
data_copy_done:

    bl centry
    b done

.thumb_func
done:   b .

.thumb_func
.globl bounce
bounce:
    nop
    bx lr

.align
bstart: .word __bss_start__
blen:   .word __bss_size__
rstart: .word __data_rom_start__
dstart: .word __data_start__
dlen:   .word __data_size__

memberi

Disassembly of section .text:

00000000 <_start>:
   0:   20000800    andcs   r0, r0, r0, lsl #16
   4:   00000015    andeq   r0, r0, r5, lsl r0
   8:   0000003d    andeq   r0, r0, sp, lsr r0
   c:   0000003d    andeq   r0, r0, sp, lsr r0
  10:   0000003d    andeq   r0, r0, sp, lsr r0

00000014 <reset>:
  14:   480c        ldr r0, [pc, #48]   ; (48 <blen>)
  16:   2800        cmp r0, #0
  18:   d004        beq.n   24 <bss_zero_done>
  1a:   490a        ldr r1, [pc, #40]   ; (44 <bstart>)
  1c:   2200        movs    r2, #0

0000001e <bss_zero>:
  1e:   c104        stmia   r1!, {r2}
  20:   3804        subs    r0, #4
  22:   d1fc        bne.n   1e <bss_zero>

00000024 <bss_zero_done>:
  24:   480b        ldr r0, [pc, #44]   ; (54 <dlen>)
  26:   2800        cmp r0, #0
  28:   d005        beq.n   36 <data_copy_done>
  2a:   4908        ldr r1, [pc, #32]   ; (4c <rstart>)
  2c:   4a08        ldr r2, [pc, #32]   ; (50 <dstart>)

0000002e <data_copy>:
  2e:   c908        ldmia   r1!, {r3}
  30:   c208        stmia   r2!, {r3}
  32:   3804        subs    r0, #4
  34:   d1fb        bne.n   2e <data_copy>

00000036 <data_copy_done>:
  36:   f000 f80f   bl  58 <centry>
  3a:   e7ff        b.n 3c <done>

0000003c <done>:
  3c:   e7fe        b.n 3c <done>

0000003e <bounce>:
  3e:   46c0        nop         ; (mov r8, r8)
  40:   4770        bx  lr
  42:   46c0        nop         ; (mov r8, r8)

00000044 <bstart>:
  44:   20000008    andcs   r0, r0, r8

00000048 <blen>:
  48:   00000004    andeq   r0, r0, r4

0000004c <rstart>:
  4c:   00000074    andeq   r0, r0, r4, ror r0

00000050 <dstart>:
  50:   20000000    andcs   r0, r0, r0

00000054 <dlen>:
  54:   00000008    andeq   r0, r0, r8

00000058 <centry>:
  58:   2207        movs    r2, #7
  5a:   b510        push    {r4, lr}
  5c:   4b04        ldr r3, [pc, #16]   ; (70 <centry+0x18>)
  5e:   2007        movs    r0, #7
  60:   601a        str r2, [r3, #0]
  62:   f7ff ffec   bl  3e <bounce>
  66:   2000        movs    r0, #0
  68:   bc10        pop {r4}
  6a:   bc02        pop {r1}
  6c:   4708        bx  r1
  6e:   46c0        nop         ; (mov r8, r8)
  70:   20000008    andcs   r0, r0, r8

Disassembly of section .data:

20000000 <c>:
20000000:   00000005    andeq   r0, r0, r5

20000004 <b>:
20000004:   00000004    andeq   r0, r0, r4

Disassembly of section .bss:

20000008 <a>:
20000008:   00000000    andeq   r0, r0, r0

kita bisa berhenti di situ atau terus berjalan. Jika kita menginisialisasi dalam urutan yang sama dengan skrip linker tidak apa-apa jika kita masuk ke hal berikutnya karena kita belum sampai di sana. dan stm / ldm hanya diperlukan / diinginkan untuk menggunakan alamat yang selaras kata, jadi jika Anda berubah ke:

    ldr r0,blen
    cmp r0,#0
    beq bss_zero_done
    ldr r1,bstart
    mov r2,#0
    mov r3,#0
    mov r4,#0
    mov r5,#0
bss_zero:
    stmia r1!,{r2,r3,r4,r5}
    sub r0,#16
    ble bss_zero
bss_zero_done:

dengan bss pertama di skrip linker, dan ya Anda mau ble bukan bls.

Disassembly of section .text:

00000000 <_start>:
   0:   20000800    andcs   r0, r0, r0, lsl #16
   4:   00000015    andeq   r0, r0, r5, lsl r0
   8:   00000043    andeq   r0, r0, r3, asr #32
   c:   00000043    andeq   r0, r0, r3, asr #32
  10:   00000043    andeq   r0, r0, r3, asr #32

00000014 <reset>:
  14:   480d        ldr r0, [pc, #52]   ; (4c <blen>)
  16:   2800        cmp r0, #0
  18:   d007        beq.n   2a <bss_zero_done>
  1a:   490b        ldr r1, [pc, #44]   ; (48 <bstart>)
  1c:   2200        movs    r2, #0
  1e:   2300        movs    r3, #0
  20:   2400        movs    r4, #0
  22:   2500        movs    r5, #0

00000024 <bss_zero>:
  24:   c13c        stmia   r1!, {r2, r3, r4, r5}
  26:   3804        subs    r0, #4
  28:   ddfc        ble.n   24 <bss_zero>

0000002a <bss_zero_done>:
  2a:   480b        ldr r0, [pc, #44]   ; (58 <dlen>)
  2c:   2800        cmp r0, #0
  2e:   d005        beq.n   3c <data_copy_done>
  30:   4907        ldr r1, [pc, #28]   ; (50 <rstart>)
  32:   4a08        ldr r2, [pc, #32]   ; (54 <dstart>)

00000034 <data_copy>:
  34:   c978        ldmia   r1!, {r3, r4, r5, r6}
  36:   c278        stmia   r2!, {r3, r4, r5, r6}
  38:   3810        subs    r0, #16
  3a:   ddfb        ble.n   34 <data_copy>

0000003c <data_copy_done>:
  3c:   f000 f80e   bl  5c <centry>
  40:   e7ff        b.n 42 <done>

00000042 <done>:
  42:   e7fe        b.n 42 <done>

00000044 <bounce>:
  44:   46c0        nop         ; (mov r8, r8)
  46:   4770        bx  lr

00000048 <bstart>:
  48:   20000000    andcs   r0, r0, r0

0000004c <blen>:
  4c:   00000004    andeq   r0, r0, r4

00000050 <rstart>:
  50:   20000004    andcs   r0, r0, r4

00000054 <dstart>:
  54:   20000004    andcs   r0, r0, r4

00000058 <dlen>:
  58:   00000008    andeq   r0, r0, r8

0000005c <centry>:
  5c:   2207        movs    r2, #7
  5e:   b510        push    {r4, lr}
  60:   4b04        ldr r3, [pc, #16]   ; (74 <centry+0x18>)
  62:   2007        movs    r0, #7
  64:   601a        str r2, [r3, #0]
  66:   f7ff ffed   bl  44 <bounce>
  6a:   2000        movs    r0, #0
  6c:   bc10        pop {r4}
  6e:   bc02        pop {r1}
  70:   4708        bx  r1
  72:   46c0        nop         ; (mov r8, r8)
  74:   20000000    andcs   r0, r0, r0

Disassembly of section .bss:

20000000 <a>:
20000000:   00000000    andeq   r0, r0, r0

Disassembly of section .data:

20000004 <c>:
20000004:   00000005    andeq   r0, r0, r5

20000008 <b>:
20000008:   00000004    andeq   r0, r0, r4

loop itu akan berjalan lebih cepat. sekarang saya tidak tahu apakah bus ahb bisa lebar 64 bit atau tidak tetapi untuk lengan berukuran penuh Anda ingin menyelaraskan hal-hal ini pada batas 64 bit. empat register ldm / stm pada batas 32 bit tetapi bukan batas 64 bit menjadi tiga transaksi bus terpisah, di mana selaras pada batas 64 bit adalah transaksi tunggal yang menghemat beberapa jam per instruksi.

karena kita melakukan baremetal dan kita sepenuhnya bertanggung jawab untuk semua yang kita dapat katakan katakanlah bss pertama maka data maka jika kita menumpuk melakukan itu maka tumpukan tumbuh dari atas ke bawah, jadi jika kita nol bss dan menumpahkan beberapa selama kita mulai dari tempat yang tepat yang baik-baik saja kita belum menggunakan memori itu. lalu kita salin. data lebih dan dapat tumpah ke tumpukan itu baik-baik saja, tumpukan atau tidak ada banyak ruang untuk tumpukan sehingga kita tidak menginjak siapa pun / apa pun (selama kita memastikan dalam skrip linker kita melakukan itu. jika ada kekhawatiran membuat ALIGN () lebih besar sehingga area kami selalu berada dalam ruang kami untuk pengisian ini.

jadi solusi sederhana saya, ambil atau tinggalkan. selamat datang untuk memperbaiki bug, saya tidak menjalankan ini pada perangkat keras maupun simulator saya ...

MEMORY
{
    bob : ORIGIN = 0x00000000, LENGTH = 0x1000
    ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > bob

    .rodata : { *(.rodata*) } > bob

   . = ALIGN(8);
   .bss  : {
   __bss_start__ = .;
   *(.bss*)
   } > ted
   . = ALIGN(4);
   __bss_end__ = .;
   __bss_size__ = __bss_end__ - __bss_start__;

   . = ALIGN(8);
   __data_rom_start__ = .;
   .data : {
    __data_start__ = .;
    *(.data*)
   } > ted AT > bob
   . = ALIGN(4);
   __data_end__ = .;
   __data_size__ = __data_end__ - __data_start__;

}



.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done

.thumb_func
reset:

    ldr r0,blen
    cmp r0,#0
    beq bss_zero_done
    ldr r1,bstart
    mov r2,#0
    mov r3,#0
    mov r4,#0
    mov r5,#0
bss_zero:
    stmia r1!,{r2,r3,r4,r5}
    sub r0,#16
    ble bss_zero
bss_zero_done:

    ldr r0,dlen
    cmp r0,#0
    beq data_copy_done
    ldr r1,rstart
    ldr r2,dstart
data_copy:
    ldmia r1!,{r3,r4,r5,r6}
    stmia r2!,{r3,r4,r5,r6}
    sub r0,#16
    ble data_copy
data_copy_done:

    bl centry
    b done

.thumb_func
done:   b .

.thumb_func
.globl bounce
bounce:
    nop
    bx lr

.align
bstart: .word __bss_start__
blen:   .word __bss_size__
rstart: .word __data_rom_start__
dstart: .word __data_start__
dlen:   .word __data_size__


void bounce ( unsigned int );

unsigned int a;

unsigned int b=4;
unsigned char c=5;

int centry ( void )
{
    a = 7;
    bounce(a);
    return(0);
}

arm-none-eabi-as --warn --fatal-warnings flash.s -o flash.o
arm-none-eabi-ld -o hello.elf -T flash.ld flash.o centry.o
arm-none-eabi-objdump -D hello.elf > hello.list
arm-none-eabi-objcopy hello.elf hello.bin -O binary

kumpulkan semuanya dan Anda mendapatkan:

Disassembly of section .text:

00000000 <_start>:
   0:   20000800    andcs   r0, r0, r0, lsl #16
   4:   00000015    andeq   r0, r0, r5, lsl r0
   8:   00000043    andeq   r0, r0, r3, asr #32
   c:   00000043    andeq   r0, r0, r3, asr #32
  10:   00000043    andeq   r0, r0, r3, asr #32

00000014 <reset>:
  14:   480d        ldr r0, [pc, #52]   ; (4c <blen>)
  16:   2800        cmp r0, #0
  18:   d007        beq.n   2a <bss_zero_done>
  1a:   490b        ldr r1, [pc, #44]   ; (48 <bstart>)
  1c:   2200        movs    r2, #0
  1e:   2300        movs    r3, #0
  20:   2400        movs    r4, #0
  22:   2500        movs    r5, #0

00000024 <bss_zero>:
  24:   c13c        stmia   r1!, {r2, r3, r4, r5}
  26:   3810        subs    r0, #16
  28:   ddfc        ble.n   24 <bss_zero>

0000002a <bss_zero_done>:
  2a:   480b        ldr r0, [pc, #44]   ; (58 <dlen>)
  2c:   2800        cmp r0, #0
  2e:   d005        beq.n   3c <data_copy_done>
  30:   4907        ldr r1, [pc, #28]   ; (50 <rstart>)
  32:   4a08        ldr r2, [pc, #32]   ; (54 <dstart>)

00000034 <data_copy>:
  34:   c978        ldmia   r1!, {r3, r4, r5, r6}
  36:   c278        stmia   r2!, {r3, r4, r5, r6}
  38:   3810        subs    r0, #16
  3a:   ddfb        ble.n   34 <data_copy>

0000003c <data_copy_done>:
  3c:   f000 f80e   bl  5c <centry>
  40:   e7ff        b.n 42 <done>

00000042 <done>:
  42:   e7fe        b.n 42 <done>

00000044 <bounce>:
  44:   46c0        nop         ; (mov r8, r8)
  46:   4770        bx  lr

00000048 <bstart>:
  48:   20000000    andcs   r0, r0, r0

0000004c <blen>:
  4c:   00000004    andeq   r0, r0, r4

00000050 <rstart>:
  50:   20000008    andcs   r0, r0, r8

00000054 <dstart>:
  54:   20000004    andcs   r0, r0, r4

00000058 <dlen>:
  58:   00000008    andeq   r0, r0, r8

0000005c <centry>:
  5c:   2207        movs    r2, #7
  5e:   b510        push    {r4, lr}
  60:   4b04        ldr r3, [pc, #16]   ; (74 <centry+0x18>)
  62:   2007        movs    r0, #7
  64:   601a        str r2, [r3, #0]
  66:   f7ff ffed   bl  44 <bounce>
  6a:   2000        movs    r0, #0
  6c:   bc10        pop {r4}
  6e:   bc02        pop {r1}
  70:   4708        bx  r1
  72:   46c0        nop         ; (mov r8, r8)
  74:   20000000    andcs   r0, r0, r0

Disassembly of section .bss:

20000000 <a>:
20000000:   00000000    andeq   r0, r0, r0

Disassembly of section .data:

20000004 <c>:
20000004:   00000005    andeq   r0, r0, r5

20000008 <b>:
20000008:   00000004    andeq   r0, r0, r4

perhatikan bahwa ini bekerja dengan arm-none-eabi- dan arm-linux-gnueabi dan varian lainnya karena tidak ada hal jagoan ghee yang digunakan.

Anda akan menemukan ketika Anda melihat-lihat bahwa orang-orang akan menjadi gila dengan hal-hal jagoan ghee di skrip linker mereka, hal-hal besar wastafel dapur. Lebih baik hanya tahu bagaimana melakukannya (atau lebih baik cara menguasai alat sehingga Anda dapat mengontrol apa yang terjadi) daripada mengandalkan barang-barang orang lain dan tidak tahu di mana itu akan rusak karena Anda tidak mengerti dan / atau ingin meneliti Itu.

sebagai aturan umum jangan bootstrap bahasa dengan bahasa yang sama (bootstrap dalam arti ini menjalankan kode tidak mengkompilasi kompiler dengan kompiler yang sama) Anda ingin menggunakan bahasa yang lebih sederhana dengan lebih sedikit bootstrap. Itulah sebabnya C dilakukan dalam perakitan, tidak memiliki persyaratan bootstrap yang baru Anda mulai dari instruksi pertama setelah reset. JAVA, tentu Anda bisa menulis jvm di C dan bootstrap C dengan asm lalu bootstrap JAVA jika Anda mau dengan C tetapi juga menjalankan JAVA di C juga.

Karena kami mengontrol asumsi pada loop salinan ini, mereka secara definisi lebih ketat dan lebih bersih daripada memcpy / memset disetel dengan tangan.

Perhatikan masalah Anda yang lain adalah ini:

unsigned int * bss_start_p = &_BSS_START; 
unsigned int * bss_end_p = &_BSS_END;

jika ini denda lokal, tidak ada masalah, jika ini global maka Anda perlu. data diinisialisasi pertama untuk mereka untuk bekerja dan jika Anda mencoba trik itu untuk melakukan. data maka Anda akan gagal. Variabel lokal, baik itu akan berfungsi. jika Anda karena suatu alasan memutuskan untuk membuat penduduk lokal yang statis (global saya suka menyebutnya) maka Anda kembali dalam masalah lagi. Setiap kali Anda melakukan tugas dalam deklarasi meskipun Anda harus memikirkannya, bagaimana itu diterapkan dan apakah itu aman / waras. Setiap kali Anda menganggap suatu variabel adalah nol ketika tidak dideklarasikan, kesepakatan yang sama, jika variabel lokal tidak dianggap nol, jika global maka itu adalah. jika Anda tidak pernah menganggapnya nol maka Anda tidak perlu khawatir.

old_timer
sumber
luar biasa, ini adalah kedua kalinya saya melampaui jumlah karakter maks dalam sebuah jawaban ....
old_timer
Pertanyaan ini termasuk dalam stackoverflow, bukan teknik listrik.
old_timer
Juga mengandalkan tautan eksternal dalam pertanyaan Anda bukanlah bentuk yang baik, jika tautan tersebut hilang sebelum pertanyaan, maka pertanyaan itu mungkin tidak masuk akal.
old_timer
Dalam hal ini, judul dan konten Anda cukup untuk mengetahui bahwa Anda mencoba melakukan bootstrap C pada mikrokontroler tertentu dan berjalan ke inisialisasi .bs dan
.data
tetapi dalam kasus ini telah disesatkan oleh situs web yang sangat informatif.
old_timer