2

モーターコントローラーを作成し、Arch ArmLinuxディストリビューションを使用してrespberrypiでテストし、制御信号の計算に約0.4msかかったので、リアルタイムOSを使用すると改善できると考えたので、ChibiOSから始めました。しかし、実行時間は約2.5ミリ秒でした。最初は、linaroに切り替えるよりもCrossfireクロスコンパイラを使用しました。linaroを使用すると、実行時間は約2.7ミリ秒悪くなりました。何が問題になる可能性がありますか?HWを最適な方法で初期化していない可能性はありますか?

     /*
     * Stack pointers initialization.
     */
    ldr     r0, =__ram_end__
    /* Undefined */
    msr     CPSR_c, #MODE_UND | I_BIT | F_BIT
    mov     sp, r0
    ldr     r1, =__und_stack_size__
    sub     r0, r0, r1
    /* Abort */
    msr     CPSR_c, #MODE_ABT | I_BIT | F_BIT
    mov     sp, r0
    ldr     r1, =__abt_stack_size__
    sub     r0, r0, r1
    /* FIQ */
    msr     CPSR_c, #MODE_FIQ | I_BIT | F_BIT
    mov     sp, r0
    ldr     r1, =__fiq_stack_size__
    sub     r0, r0, r1
    /* IRQ */
    msr     CPSR_c, #MODE_IRQ | I_BIT | F_BIT
    mov     sp, r0
    ldr     r1, =__irq_stack_size__
    sub     r0, r0, r1
    /* Supervisor */
    msr     CPSR_c, #MODE_SVC | I_BIT | F_BIT
    mov     sp, r0
    ldr     r1, =__svc_stack_size__
    sub     r0, r0, r1
    /* System */
    msr     CPSR_c, #MODE_SYS | I_BIT | F_BIT
    mov     sp, r0

    mov r0,#0x8000
    mov r1,#0x0000
    ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
    stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
    ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
    stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}


    ;@ enable fpu
    mrc p15, 0, r0, c1, c0, 2
    orr r0,r0,#0x300000 ;@ single precision
    orr r0,r0,#0xC00000 ;@ double precision
    mcr p15, 0, r0, c1, c0, 2
    mov r0,#0x40000000
    fmxr fpexc,r0
    mov     r0, #0
    ldr     r1, =_bss_start
    ldr     r2, =_bss_end

そしてメモリ設定:

__und_stack_size__  = 0x0004;
__abt_stack_size__  = 0x0004;
__fiq_stack_size__  = 0x0010;
__irq_stack_size__  = 0x0080;
__svc_stack_size__  = 0x0004;
__sys_stack_size__  = 0x0400;
__stacks_total_size__   = __und_stack_size__ + __abt_stack_size__ + __fiq_stack_size__ + __irq_stack_size__ + __svc_stack_size__ + __sys_stack_size__;

MEMORY
{
    ram : org = 0x8000, len = 0x06000000 - 0x20
}

__ram_start__       = ORIGIN(ram);
__ram_size__        = LENGTH(ram);
__ram_end__     = __ram_start__ + __ram_size__;

SECTIONS
{
    . = 0;

    .text : ALIGN(16) SUBALIGN(16)
    {
        _text = .;
        KEEP(*(vectors))
        *(.text)
        *(.text.*)
        *(.rodata)
        *(.rodata.*)
        *(.glue_7t)
        *(.glue_7)
        *(.gcc*)
        *(.ctors)
        *(.dtors)
    } > ram

    .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > ram

    __exidx_start = .;
    .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > ram
    __exidx_end = .;

    .eh_frame_hdr : {*(.eh_frame_hdr)}

    .eh_frame : ONLY_IF_RO {*(.eh_frame)}

    . = ALIGN(4);
    _etext = .;
    _textdata = _etext;

    .data :
    {
        _data = .;
        *(.data)
        . = ALIGN(4);
        *(.data.*)
        . = ALIGN(4);
        *(.ramtext)
        . = ALIGN(4);
        _edata = .;
    } > ram 

    .bss :
    {
        _bss_start = .;
        *(.bss)
        . = ALIGN(4);
        *(.bss.*)
        . = ALIGN(4);
        *(COMMON)
        . = ALIGN(4);
        _bss_end = .;
    } > ram    
}

PROVIDE(end = .);
_end = .;

__heap_base__              = _end;
__heap_end__               = __ram_end__ - __stacks_total_size__;
__main_thread_stack_base__ = __ram_end__ - __stacks_total_size__;

どこで間違いを犯しますか?

4

1 に答える 1

3

ずっと前に(そう、前の千年紀のいつかを意味します)、私は古いPCスピーカーpcspデバイスドライバーここではもう少し新しいパッチ)を使用して、パラレルポートのデータラインに接続されたリレーを介してステッピングモーターを制御しました。現在のドライバーと同じドライバーではない
ことに 注意してください(パラレルポートではなく、実際のスピーカーにのみ書き込みます)。の並列出力対応部分は、2.6オーディオアーキテクチャに移植されることはありませんでした。pcspkrpcsp

そこにある秘訣は、ドライバーが実際のデバイスレジスタ/ IOポートの書き込みを行ってライン状態を変更する(必要に応じて優先度の高い)割り込みルーチンを登録できることです。その結果、単純ioctl()にドライバーにサンプルレートを送信し、メモリ内に作成された「ランプ」(特定の速度にステップアップ/ステップダウンする、またはいくつかのステップを実行するデータ信号のランプ)を非同期的に書き込みます。ドライバーは、追加のタイミング/スケジュールに敏感なコードを必要とせずに、それらをスプールします。

最終的に、パラレルポートのデータピンに8ビットのデジタル信号が得られ、タイマー割り込みが許す限り高いタイミング精度が得られます。
ステッパーを駆動するのに十分なラインがありました。所定のステップ数で回転させたい場合は、次のことを行う必要があります。

  • 「ランプアップ」を作成して、静止状態から最速にスピードアップします
  • 「長方形」を作成して回転を維持します
  • 「ランプダウン」を作成して、さらにスローダウンします

ステップ数が少ない場合は、すべてを一度に書き込みます。そうでない場合は、ランプアップを書き込み、必要な数の整流波ブロックを書き込んでから、ランプダウンします。一度に数千のステップをプログラムする可能性がありますが、memの3つのブロックをそれぞれ数kBだけ書き込むだけで、残りはドライバーの割り込みハンドラーが行います。

抵抗アレイDACコンバーターを取り付けた場合はかなりおかしいように聞こえました;-)

このアプローチは、RaspPIに一般化できます。割り込みルーチンから、GPIO制御レジスタを書き込むだけです(ARMでは、デバイスレジスタは常にメモリマップされているため、単にメモリアクセスです)。

「ランプ」/「制御信号」の生成をタイミングに敏感な状態変化(実際には「制御信号アプリケーション」)から切り離し、後者をデバイスドライバの割り込み部分に委任することで、このようなタスクを「通常」で実行できます。 Linux。

ここでも、タイミング精度はタイマー割り込みのレートとジッターによって制限されます。RaspPIは、i386よりも高いタイマー割り込みレートを実行できます。1msはこのアプローチでは難しいことではないと確信しています(1995年にはそうではありませんでした)。方法論は、前述のように、信号を事前に作成する能力に依存します。

于 2012-12-10T14:34:39.190 に答える