目次
図3に示すように、位置に関係なくコードのコードの位置を詳細に説明します
参考記事:https://blog.csdn.net/lizuobin2/article/details/52049892#
1、コード起動処理の簡単な分析
質問1:ダウンロード行きますか?
そこデータシート上の命令とすることが、我々はどこダウンロードして、彼は内のコードを見つけることができなかったときに、間違った位置のダウンロードを開始するには、ダウンロードに出て行きたい場所、場所ではない、次のように一般的にストレージデバイスにダウンロードされます:1、内部が来ますFLASH、図2は、フレアNANDFLASH(EMMC) 、図3は、拡張NORFLASH、 4、SDカード(メモリアドレス)
1は、最もマイクロコントローラ(STM32)が内蔵され、内部フラッシュメモリにダウンロードされ、厳密にはスタートアドレスで指定されている(例えば、0x08000000)
図2に示すように、ランのほとんどのAndroidまたはLinuxの、典型的にダウンロードARM SDカードやフレアFLASH(EMMC)は、さただし、SDカードまたはEMMCにおける開始位置が厳密に定義され、このような出発格納された第0ブロックとして(またはa)第一の位置から格納されたスキップ
質問2:コードをロードするためにどの位置からは、実行中の負荷行きますか?
二つ以上の記憶装置と一つの記憶装置に分割1は、直接デバイスを直接操作コードアドレッシングされていない実行コード(自身の内部フラッシュ、外部拡張NORFLASH)である(SDカード、NANDFLASH、EMMC)
2、一般的にチップを持っているピンを有効に、我々は、ダウンロードコードの位置を修正する必要があるコンフィギュレーション・スタート・ピンのハイとローのように、正しいスタートアップコードに電源こと、
図3は、のためのコードの直接操作、記憶装置、事前ロードするコードは、必要はない、それだけにとして直接、装置の開始位置からのコードを実行する他の所望の動作位置アドレスプログラマを参照するコードのニーズが遅くランにロードされるかどうか(リンク内部のスクリプトで書かれたリンクアドレス)、実際の操作のデフォルトのリンクアドレス翻訳ソフト、翻訳ソフトとデフォルトリンクアドレスとアドレスで(何もしたくない場合には、コード、実行するためにゼロからコードをコピーして任意のアクションを必要としない)と同じです最後に(STM32マイクロコントローラおよび他のチップなどがそうである、) 、プリコードの後半でコードをコピーして、プログラマが別の場所で実行するコードの一部を望んでいる場合は、システムはデフォルトのアドレスとなっているのではなく、ポストコードリンクアドレスを変更する必要があります所望の位置へ、そして位置への長いジャンプが(これは以下の通りである:私達は時々遅すぎるFLASH、実行するためにRAMにコードをコピーする必要性を感じて)上で実行する(再配置)
4、のために直接コードを実行しない記憶装置を、コードの内部ファームウェアチップ初期部分を実行するデフォルトのメモリ位置(内蔵RAM)にロードされるようなLinuxを実行して、この状態は、一般的に大きいためのコードであるので、なぜ、それの一部です(限られたシステム)内蔵RAMのリソース、コードのように一部のみが内部RAMにロードされ、コードのほとんどの他の部分は、実行するためにRAMの外部拡張にロードする必要があるプログラマはリンカスクリプト(自分の書き込みにしてリンクアドレスを使用すると、コードの後ろの部分を載せていきたいと思います)彼は実行することを望むアドレスにロードされ、書き込みコード(にプリプログラマを実行することができる位置独立コードのコードの後部には、(所望の位置へコピー機能コピー、コピー機能に含まれる)再配置後)、事前に完成し、実行時にコード達成の長いジャンプを、リンクを実行するために、目的の場所にジャンプ
要約:
初期および後期のポイントにロードされた場所のコードを実行するコードは、基本的な場所、負荷へのポストコードを実行し、最も自分たちのニーズ位置(ほとんどのマイクロコントローラやシステムのデフォルト、に応じて実行するデフォルトの実行に予めロードされ、指定されたピンに応じて開始する場所からロードされますARMは後半に)大規模なシステムは、再配置を必要と実行します
2、メモリアドレス、実行アドレス、リンクアドレス
2.1、メモリアドレス
コードの位置メモリ(FLASH)であります
2.2、リンクアドレス
このアドレスは、リンカスクリプトの場所が指定されたコード内で実行することです(実行アドレスにプログラマが期待されます)
例えば、我々はコードたい将来的には、(指定された電気システム上だけで実行する立場に常にではない)を実行するために私たちの拡張メモリにロードされました
2.3、実行アドレス
現在のプログラムがされている実行中のアドレス(PC)を
私たちは、コード内のどこにでも置くことができる理論的用語は、メモリにロードしてから実行するために適切な場所にジャンプし、私たちのリンクアドレスが現在実行してアドレスされて参照するには問題は、同じですし、位置のコードまたは場所を実行しているとされます無関係コード、アドレスがある場合、コードの位置が矛盾しているとエラーが発生する可能性があり(コードと無関係なコードの位置の背後にある説明を参照)
チップマイコン等(STM32)
ほとんどのハーバードアーキテクチャ(STM32を含む)シングルチップを実行するためのRAMへのコード追加の負荷ではありません、消費電力は、位置コードのダウンロード当社から実行している直接(FLASH)です
一般的には、マイクロコントローラのコードを話す:メモリアドレス=アドレスリンクアドレス=実行
2.4のリンクと実行アドレスの違い
分解我々はリンクアドレスを参照してくださいという事実を、内部コードの実際の動作のアドレスは、コードがロードされている方法を確認すると、ロードされたGoが実行されています、
リンクアドレスがあることを私達を仮定0x33f800000我々はコードを置く場合にロード0x00000000に示すように、アドレス実際の動作:
最後に、変数や関数のアドレスを含むマシンコードは、現在の位置に応じてPCにリンクアドレスまたはジャンプアドレスの絶対値またはオフセット値を加算またはジャンプであるコードと位置独立コードの位置:
1は、私の理解によると、位置独立コードは絶対にこのコードとリンクアドレスには何もありません、またはジャンプ値は、現在のPC +オフセットアドレスに対処するために必要とされているので、常に正しい位置を見つけることができるので、そこのアドレスです相対アドレスは、アドレスが変更されたことをダイナミックアドレス、アドレスの変更操作として理解することができ、あなたが変更したと私は、いわゆる変更しました
図2に示すように、絶対リンクアドレスでコードの位置、リンクアドレス値に応じてそれぞれの一方、または変数がリンクに格納されているだけのアドレスの関数である場合は、変数または関数場合、ジャンプの値を実現以上に正確な位置を見つけることができラム位置にロードされ、私たちの位置が同じリンクアドレスではありませんされ、その後、リンクアドレス値に行くか、エラーは確かにジャンプします
質問1:リンクアドレスをアドレスと等しくなると、それを実行する必要がありますか?
回答:按前面的分析,前期代码(一般是些基本的硬件初始化代码,如果需要重定位还包括拷贝函数代码)运行地址和链接地址可以不相等后期代码的链接地址必须要等于运行地址,也就是说后期代码当前的实际运行地址和链接地址不相等就有可能出错,因为:前期代码大部分是位置无关码,而位置无关码无论加载到RAM中的什么位置都可以正常运行,后期的代码中有些代码是位置有关码,位置有关码的实际运行地址和我们的期望运行地址(链接地址)不一样就有可能出错,
举两个例子说明一下:
1、比如在一个函数中读取一个全局变量的值,读取时会根据变量的链接地址而不是实际存放地址去取值,如果实际存放的地址=链接地址那么取到的值肯定是正确的,如果链接地址和实际的存放地址不一样那么取出的值肯定是错误的。
2、再比如:一个c语言函数调用另外c语言一个函数,如果两个函数的运行地址相差很大(大于32M)编译器就会生成位置有关码的跳转指令跳转到那个被调用的函数位置,如果那个函数的此时不在我们链接指定的位置处,那么跳转肯定出现错误
总结:前期代码运行地址可以和链接地址不一样,后期代码运行地址必须和链接地址一样
3、位置有关码,位置无关码详细解释
4、代码重定位
我们希望后期代码在我们指定的位置运行(比如为了加快代码运行速度,把代码从FLASH上面加载到外部RAM中运行),我们会在前期代码中用位置无关码拷贝代码到链接地址处,然后长跳转到链接地址处运行,这样一个过程就是代码重定位
问题1:为什么一开始不直接把代码加载到RAM运行呢?
回答:一般我们外扩的RAM是需要通过代码初始化才能正常工作的,所以前期是不能直接加载到RAM中运行的
问题2:stm32可不可以偏要把代码放到内部RAM运行呢?
回答:肯定是可以的,但是要设置好链接地址让编译器按你的链接地址编译,并且在前期编写拷贝函数把代码拷贝到链接地址(RAM)中运行