Armadilloフォーラム

A410で70pin EXT_IO17 GPIOの初期値を変更したい

funayama

2015年2月14日 21時15分

お世話になっております。

A410のpin70はハードウェアマニュアルによりますと
70 EXT_IO17 GPIO In - Disable 100kΩPU1 Slow

と入力ポートとなっております。

これを、出力ポート、初期値Highで設定したいと考えております。
make menuconfigでの設定で可能でしょうか。
可能である場合、どのConfigration設定となりますでしょうか。
ご教授下さい。
よろしくお願い致します。

コメント

中村です。

> A410のpin70はハードウェアマニュアルによりますと
> 70 EXT_IO17 GPIO In - Disable 100kΩPU1 Slow
>
> と入力ポートとなっております。

表6.10のブートローダ起動後の状態ですね。

> これを、出力ポート、初期値Highで設定したいと考えております。
> make menuconfigでの設定で可能でしょうか。
> 可能である場合、どのConfigration設定となりますでしょうか。

ブートローダのソースを修正する必要があります。

hermit-atのソースのsrc/target/armadillo4x0/board.cに
次のような配列があります。

static struct iomux_info gpio_pins[] = {
        /* CON9 */
        { MX25_PIN_CSI_MCLK, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
        { MX25_PIN_CSI_VSYNC, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
        { MX25_PIN_CSI_HSYNC, MUX_ALT5, MUX_ALT5, 0x00e0, 0x00e0 },
        { MX25_PIN_CSI_PIXCLK, MUX_ALT5, MUX_ALT5, 0x01e0, 0x01e0 },
        { MX25_PIN_CSPI1_SS0, MUX_ALT5, MUX_ALT5, -1, -1 },
        { MX25_PIN_CSPI1_RDY, MUX_ALT5, MUX_ALT5, -1, -1 },
        { MX25_PIN_CLKO, MUX_ALT5, MUX_ALT5, 0x0000, 0x0000 },
        { MX25_PIN_EXT_ARMCLK, MUX_ALT5, MUX_ALT5, -1, -1 },
        ...
        { MX25_PIN_BOOT_MODE1, MUX_ALT5, MUX_ALT5, -1, -1 },
        { },
};

EXT_IO17は、CSI_PIXCLKです。
(410のハードウェアマニュアルの表9.10などを参照)

このgpio_pins[]を使っているのは、その下の方にある次の関数です。

static void armadillo4x0_setup_gpio(struct platform_info *pinfo)
{
        int i;
 
        mx25_iomux_config(gpio_pins, 1);
 
        for (i=0; ; i++) {
                if (!gpio_pins[i].pin)
                        break;
 
                if (gpio_pins[i].pin == MX25_PIN_CLKO ||
                    gpio_pins[i].pin == MX25_PIN_EXT_ARMCLK)
                        mx25_gpio_output(gpio_pins[i].pin, 0);
                else
                        mx25_gpio_input(gpio_pins[i].pin);
        }
}

このarmadillo4x0_setup_gpio()の処理を見ればおわかりと思いますが、
gpio_pins[]にあるポートのうち、CLKOとEXT_ARMCLKはoutputでLow、
それ以外はすべてinputにしています。

あとは説明不要と思います。

あ、ブートローダ(hermit-at)をビルドする方法は、
400シリーズのソフトウェアマニュアルに書いてあったと思います。

--
なかむら

中村さん

お世話様です。
以前もお世話になりました。

早速のコメントありがとうございます。
修正を行ってみます。

中村です。

どのような外部回路を接続するのかわかりませんが、
修正前はinputで100kΩプルアップですから、
ブートローダでoutput/Highになるように変更するのではなく、
OS起動が終わった後にアプリでoutput/Highにしても
いいのではないでしょうか?

--
なかむら

中村さん

お世話様です。

ご推察の通り、もともとはアプリ初期設定でOutput/Highの設定を
行っていました。

ポート機能はPowerON/OFFです。
回路上の都合で回路が変更となり、
その際、アプリでOutputのdirection変更を行うと200usec
Lowが出力されてしまう現象があり、これを回避するための
対策となっています。
ハードウェアの詳細についてはコメントを控えさせて頂きたいと
思います。

中村です。

> ポート機能はPowerON/OFFです。
> 回路上の都合で回路が変更となり、
> その際、アプリでOutputのdirection変更を行うと200usec
> Lowが出力されてしまう現象があり、これを回避するための
> 対策となっています。

瞬間的にLowが出力されるのは、/sys/class/gpio/XXX/directionへ
"out"を出力してdirection変更したときでしょうか?
その直後にvalueに"1"を出力。

directionに"high"を出力してoutputに変更しても瞬間的にLowになります?
実際に自分でハードウェアを確認したことはないですが、
ソースを見ると、linux-2.6.26/drivers/gpio/gpiolib.c

static ssize_t gpio_direction_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
{
        else if (sysfs_streq(buf, "high"))
                status = gpio_direction_output(gpio, 1);
        else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
                status = gpio_direction_output(gpio, 0);
        else if (sysfs_streq(buf, "in"))
                status = gpio_direction_input(gpio);
}

また、linux-2.6.26/arch/arm/mach-mx25/gpio.c

static int mx25_gpio_direction_output(struct gpio_chip *chip,
                                      unsigned offset, int val)
{
        struct mxc_gpio_chip *mxc_gpio = to_mxc_gpio_chip(chip);
        u32 pin = GPIO_TO_IOMUX(mxc_gpio->port_num, offset);
 
        mxc_set_gpio_dataout(pin, val);      // <== 先に値をセットして
        mxc_set_gpio_direction(pin, 0);      // <== 後から方向をセット(0でoutput)
 
        return 0;
}

となっていて、"high"でdirectionをoutputにすれば、
先に値を1にして、後から方向をoutputにしてます。

ついでにブートローダーの方もチェックしてみました。
hermit-at/src/target/armadillo4x0/board.cで
mx25_gpio_output(gpio_pins[i].pin, 1);を実行すると
(今回の要件outputでHighにする、です)
hermit-at/src/target/driver/mx25_iomux.cの次の部分が
実行されます。

void mx25_gpio_output(int pin, int mode)
{
        u32 val;
 
        val = read32(gpio_base[PIN_TO_GPIOPORT(pin)] + GPIO(GDIR));
        val |= (1 << PIN_TO_GPIOBIT(pin));                   // 先にGDIR=1で方向をセット(1でoutput)
        write32(gpio_base[PIN_TO_GPIOPORT(pin)] + GPIO(GDIR), val);
 
        val = read32(gpio_base[PIN_TO_GPIOPORT(pin)] + GPIO(DR));
        if (mode)                                            // 後からDRに値をセット
                val |= (1 << PIN_TO_GPIOBIT(pin));
        else
                val &= ~(1 << PIN_TO_GPIOBIT(pin));
        write32(gpio_base[PIN_TO_GPIOPORT(pin)] + GPIO(DR), val);
}

カーネルと違って、ブートローダでoutput/Highにすると、
先に方向をoutputにして、後から値を設定してます。
データレジスタ(DR)のリセット時の値は0(Low)です。

もしかしたら、ブートローダでoutput/Highにしても、
この瞬間にLowが一瞬出力されるかもしれません。

--
なかむら