質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.62%

マイコンのスタートアップルーチン書き方(C言語)

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 4,065

ElecDove

score 257

いつもお世話になっております。

今まで多少マイコンは触ってきたのですが、スタートアップルーチンについては先人の作成されたものをそのまま使うのみでした

今回、できればこのあたりまで理解を深めたいと思い、いろいろスタートアップルーチンを覗いたり、アプリケーションシートを読んだりしているのですが、到底1からかくのは難しそうです

Arduinoなんかは、スタートアップルーチンは完全に隠されており、存在すら知らない人も多いイメージです

組み込みの皆様は、何を参照しながら、どのようにしてスタートアップルーチンを書いていらっしゃるのでしょうか

もちろん、アプリケーションシートなどを参照されているとは思いますが、具体的にどの項目を観ればよいのでしょうか

尚、マイコンはR8Cマイコン、AVRマイコン、RXマイコン、STM32マイコンで考えています。
R8C M12A、ATMega328Pで実例を交えながら回答いただけると大変ありがたい(使ったことがあるため)ですが、一般論でもかまいません
手がかりがほしい、という状況です

また、STM32についてはこれから手を出したいと考えているところです

よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

昔(20年以上前)に、マイコンの仕事をやり始めた者です。
その時代は、まだコンパイラーがイマイチで、スタートアップは、
基本アセンブラ言語で書いていました。

近年では、C言語でも、CPU内の特殊レジスタ(スタックポインタや、
割り込みの禁止や許可のビット)にアクセスできる、
関数などが用意されていて、アセンブラを使わないで書けるようになって
きていますね。

自分が思うには、昔のCPUは機能が単純だったので、自分で手書きしても、
大変ではありませんでしがた、最近では、機能が色々と増えてきていて、
結構大変になってきています。

まずは、CPUメーカーのサンプルや、人が書いたルーチンを見て、そこに
書いてある内容を、CPU(や周辺ICの)データシートを見て、何をしているか
理解する事が大切だと思います。

理解するには、ソフトだけではなく、ハードウェアの知識が、必要になって
来ることも多々あります。

例えば、外部バスにSD-RAM等が接続されている場合は、そのSD-RAMの
仕様も、知っていないと、バスコントローラーの初期化もできませしね。

理解が進むと、必要に応じて、修正したり、自分で一から作る事も、
できるようになるとおもいますよ。

がんばって下さい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/13 00:12

    回答ありがとうございます

    確かにC言語からより低レベルなアクセスを提供する関数はありますね

    しかし、いずれにせよ、どのような命令がアセンブラに存在し、
    それをどんな方法で(C言語から)呼び出してやればいいのか、ってのは
    やはりコンパイラによって変わってくると思いますし、
    アセンブラならどんな命令が用意されてるかも知らないといけないですよね・・・

    やはり、ハードの知識がさらに必要です・・・
    今でもある程度知っているつもりでしたが全然そうではないということを思い知らされました

    キャンセル

checkベストアンサー

+1

一般論としてはスタックポインタの設定、ベクターテーブルの設定、.bssセクションを0クリア、.dataセクションをROMからRAMにコピー、その他ペリフェラルの初期化、エントリーポイントへのジャンプとかでしょうか?

必要なのはメモリーマップとペリフェラル、あとはCで書こうとするなら割り込みハンドラの設定にattributeディレクティブを使うのでコンパイラのドキュメント。

私は一から書いたはありません。ベクターテーブルの設定をしたり、リンカースクリプトをいじる程度です。開発環境で用意されたもの以外使ってません。HEWとかCS+とかでは生成されますよね。

 2017/04/04追記

あまりピンと来てないようなので実例としてSTM32F103についてみてみました。
結構時間をかけたのでめんどくさがらずに見てもらえると嬉しいです。
間違いがあったらごめんなさい。

STM32F103データシート

このマイコンは内蔵でFlashとSRAMがあるので、とりあえず内蔵Flashからブートさせることを考えます。
P39のメモリマップをみるとSRAMが0x20000000 - 0x20017FFF、FLASHが0x08080000 - 0x080FFFFF, 0x08000000 - 0x0807FFFF, 0x00000000 - 0x000FFFFFにあります。

Power on reset時の挙動を確認します。CortexM3のドキュメントを見ます。(適当に拾ったドキュメントなので最新版かはわかりません)

5-20にReset時の挙動が書いてあります。ベクターテーブルのoffset0番地を読んでSP(スタックポインタ)とSP_main(メインスタックポインタ)を設定。PC(プログラムカウンタ)をベクターテーブルのoffsetから読み出す、LR(リンクレジスタ)を0xFFFFFFFFに。

5.9.1にベクターテーブルの記述例が書かれてます。先の説明通りスタックポインタのトップ番地(をスタックサイズから計算してる)次にPowerISR(リセット時の割り込みハンドラ, スタートアップルーチン)、その他割り込みハンドラの記述。

ついでに5.9.2にブート時の処理が書かれてます。
変数の初期化。.bss(初期値が0の変数が割り付けられる)セクションを0クリアして.data(初期値が0でない変数が割り付けられる)をRAMにコピーします。
その他もろもろをして割り込み許可。main関数へジャンプ。

つづいてリンカースクリプトの記述。メモリマップ見ながら適当に。(といいつつ他人のを拝借)

ソース

はじめに定数定義をして、ENTRY()でエントリーポイントの指定。あとはベクターテーブル分があって、.text, .rodataを>flashに。あとは.data, .bss, .stackを >ramに割り付けます。
LMAコメントしてあるところがありますが、変数なのでRAM上に割り付けますが、初期値があるのでflashからコピーしてこないとプログラムが誤動作します。のでこれをスタートアップルーチンで初期化してやります。

ようやくスタートアップルーチンの記述。
Cで書くならコンパイラにリンカースクリプトで書いたように配置してもらう必要があるのでディレクティブを使います。

5-59にattribute((section("name"))) 関数属性というのがありますこれを使ってそれぞれ書いていきます。
あとattribute((used))をつけておくと安心みたいです。(詳しいことは知りません)

//リンカースクリプトで定義した変数
extern unsigned long _sidata, _sdata, _edata, _sbss, _ebss, _stack_size;

//スタック
unsigned char stack_base[_stack_size] __attribute__ ((section ("._stack")));

//main関数
extern int main();

//リセットハンドラ
void ResetISR(void);

/* ベクターテーブル */
void (* const vectors[])(void) __attribute__ ((section(".isr_vector"))) = {
    stack_base + sizeof(stack_base),
    ResetISR,
    NmiSR,
    FaultISR,
    0,            // Populate if using MemManage (MPU)
    0,             // Populate if using Bus fault
    0,            // Populate if using Usage Fault
    0, 0, 0, 0,         // reserved slots
    SVCallISR,
    0,            // Populate if using a debug monitor
    0,            // Reserved
    0,            // Populate if using pendable service request
    0,            // Populate if using SysTick
    // external interrupts start here
    Timer1ISR,
    GpioInISR
    GpioOutISR,
    I2CIsr
};

/* スタートアップルーチン */
void ResetISR() __attribute__ ((used)) {
    //clear BSS
    for (unsigned long *dest=&_sbss; dest<&_ebss;) *(dest++) = 0;

    //copy initialized data
    for (unsigned long *dst=&_sdata, *src=&_sidata; dst<&_edata;) *(dst++) = *(src++);

    //call main
    main();
}

これだけやれば最低限動きますし、ここに割り込み許可とかCPUの機能の有効化、ペリフェラルの設定を入れてもいいですし、main関数でやってもいいです。

実際書いてみるとほとんど使い回せて、変更する部分ってスタックサイズだとかベースアドレス、あとはベクターテーブルくらいですよね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/02 22:42

    回答ありがとうございます

    なんとなく、やる内容はふわっとわかるのですが、じゃあどこまでやるべきなのか、とか、
    これは絶対にやらないといけない、とか、そういう定石みたいなものがやはりあるのでしょうか

    また、マイコンごとにやる内容や書く内容は異なってくると思いますが、
    このマイコンではこの処理が必要みたいなのはやはり、ドキュメントを読めばわかるのでしょうか

    例えば、スタートアップルーチンではないですが、
    あるタイマをある機能で動かしたい!と思ったら、ドキュメントの、あるタイマのある機能の部分を読んで、どのレジスタに何の値をセットすればよいかを見ればすぐに使い始められると思います

    しかし、スタートアップルーチンでは、「これをああする」みたいな決まりってあるのでしょうか

    自分がイメージできていないだけなのかもしれないですが・・・

    HEWは無償評価版を使ったことがあります
    自動生成されたスタートアップルーチンを何もいじらずに確かにとりあえずは動きました

    しかし、先人が書いたスクリプトと見比べてみると、かなり見た目が違うように感じました
    そんなものなのでしょうか

    先の例に挙げた、レジスタの例なら、順番こそ異なれども、だれが書いても同じものが出てくると思います

    キャンセル

  • 2017/04/13 00:08

    実例まで書いていただきありがとうございます
    お礼が遅くなり申し訳ありません

    回答いただいてから数日かけて何度も何度もソースと解説を読んでいました


    おかげで、現状の自分に足りない知識が見えてきた気がします
    まだまだ、スタートアップルーチンを書けるほどではありませんが、
    いろいろ調べながら勉強をしていきたいと思います

    もっともっと、ハードに近い部分でのマイコンへの理解が必要だと感じました。

    とはいえ、ここまでくると、使うマイコンごとにCPUの構造やアドレスマップが相当異なってくるのでそこはマニュアルとのにらめっこですね
    おなじ系統なら比較的やりやすいのでしょうけど。

    キャンセル

0

基本情報はデータシートから得ます。メーカにもよるでしょうがAVRなら秋月のここにあります。
電源投入時やリセットの動作は大抵書いてあるので、スタートアップに何が必要かわかると思います。
「追記」
残念ながら私は(マイコンは)アセンブラしか使ったことがないので、Cのスタートアップはわかりません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/02 22:42

    回答ありがとうございます

    「ここ」のリンク先をよく見てみたいと思います

    スタートアップはアセンブラで書くものなのでしょうか・・・

    キャンセル

  • 2017/04/03 23:33 編集

    (私見ですが)リセット、タイマや外部割込みなどのベクタ設定は、アセンブラで書いた方が短い分わかりやすい気がします。(話が飛んじゃいますが・・・AVRなら割り込みとかタイマ制御とかやってLED点滅ぐらいならアセンブラで十分ですd^^・・・ちょっとしたOSもどきなら、タイマで周期呼び出しをすれば出来ちゃいますね)また、nullbotさんが仰っているような動作もアセンブラで書いた方いい気がします。いずれにしても各マイコンの電源投入(リセット?)から初期設定までを参考にされたらいかがでしょう?

    キャンセル

0

以下一般論ですが、ゼロから自分で書いたことはないですね。かなり前(H8が出た頃)はアセンブラで他の方のを参考にして修正して使ったことはありますが、最近のワンチップマイコン(こういう言い方もしなくなりましたね)はメーカー側で用意してあるのでそのまま使っています。変更したいところだけ自分で設定し直す程度です。
やるとすればアセンブラで設定するのが早いかなと思います。もし取り組むならマイコンの仕組みをより理解できて応用がきくと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/13 00:09

    回答ありがとうございます

    ゼロから書いたことはないとのことで
    大変参考になります

    こういうのって全部自分で書かなければならないと思っておりましたので…。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る