2017年11月23日

STM32のMicroPythonでlwIPを使う

lwip-wiznet5500.png
現在のSTM32用のMicroPythonでは、TCP/IPとして利用できるのはWIZnetやCC3000などのTCP/IPモジュールだけです。
これに対して、以前の記事で、WIZnetのTCP/IPモジュールをイーサネットインタフェースとして使い、TCP/IP実装はlwIPを用いるような実装が進められていることを書きました。(lwIPはオープンソースの軽量なTCP/IP実装です。)
ただし、現時点ではこのコードはESP32/ESP8266のMicroPythonでないと動かないと思います。
urequestsは内部でsocket.readline()を使用していますが、CC3100やWIZnet5Kなど、上記以外のNICではreadline()が実装されていないからです。

そのため、WIZnet5Kに関してはTCP/IP実装はlwIPを使用し、WIZnet5Kは単なるイーサネットインタフェースとして使用するようなMicroPython側のドライバ実装が現在テスト中のようです。

stm32: Incorporate lwip stack and use Wiznet in MACRAW mode by dpgeorge ・ Pull Request #3379 ・ micropython/micropython

ただ、TCP/IPをメインCPUで処理するため、WIZnet5Kのソケット機能を使う場合よりも速度は低下するようです。

上記を書いた後、チューニングが進んでかなり高速化されたようなので、試してみることにしました。
この方式だと、WIZnetを使う場合と比べて、socketの機能がフル実装されますので、上に書いたようにurequestsなどの便利なモジュールが利用できるようになるというメリットがあります。

この実装はDamien George本人が行っていますが、現時点ではマスターブランチへのマージは行われていません。そのため、このブランチをダウンロードしてコンパイルする必要があります。
手順は以下の通りです。

まず、本家ではなくDamien GeorgeのMicroPythonリポジトリをcloneします。
mkdir micropython-lwip
cd micropython-lwip/
git clone https://github.com/dpgeorge/micropython.git


このリポジトリは沢山のブランチがありますので、ブランチの一覧を見ます。
cd micropython/
git branch -r


表示された中から、stm32-lwip-wiznetブランチを選択します。
git checkout -b stm32-lwip-wiznet origin/stm32-lwip-wiznet


ビルドします。
git submodule update --init
make -C mpy-cross
make -C ports/stm32 MICROPY_PY_WIZNET5K=5500 BOARD=NUCLEO_F401RE CROSS_COMPILE=~/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-


追記:以下の事象をリポートしたところ、速攻で修正されたので、現在は以下の修正は必要なくなっています。

すると、以下のようなエラーが出ました。
LINK build-NUCLEO_F401RE/firmware.elf
build-NUCLEO_F401RE/main.o: In function `rand':
main.c:(.text.rand+0x0): undefined reference to `rng_get'
build-NUCLEO_F401RE/lib/lwip/src/core/dhcp.o: In function `dhcp_create_msg':
dhcp.c:(.text.dhcp_create_msg+0x30): undefined reference to `rng_get'
build-NUCLEO_F401RE/lib/lwip/src/core/ipv4/igmp.o: In function `igmp_delaying_member':
igmp.c:(.text.igmp_delaying_member+0x1e): undefined reference to `rng_get'
build-NUCLEO_F401RE/lib/lwip/src/core/ipv4/igmp.o: In function `igmp_joingroup':
igmp.c:(.text.igmp_joingroup+0x72): undefined reference to `rng_get'
Makefile:447: ターゲット 'build-NUCLEO_F401RE/firmware.elf' のレシピで失敗しました

リンクに失敗しているようです。rng_getが見つからないと言われています。

ということでちょっと調べたところ、以下のことが分かりました:

・lwIPは、移植の際に32bitの乱数を得る関数LWIP_RAND()を#defineで与える必要がある。乱数がいいかげんだと脆弱性につながるので、あまり適当な関数を与えないほうが良い。
・今回のMicroPythonの実装では、LWIP_RANDは ports/stm32/lwip-include/lwipopts.h の中で与えており、その定義は以下のようである。
extern uint32_t rng_get(void);
#define LWIP_RAND() rng_get()

・このrng_get()の実体は ports/stm32/rng.c で定義されており、その実装はHAL_RNG_GetRandomNumber()を呼び出すだけである。
・ただし、rng.cの中身全体が #if MICROPY_HW_ENABLE_RNG で囲われているので、rng_get()がリンクエラーになったということはMICROPY_HW_ENABLE_RNGが設定されていない可能性が高い。

ということで、ports/stm32/boardsの各ボードでどのようになっているか調べてみます。
cd ports/stm32/boards/
grep MICROPY_HW_ENABLE_RNG */mpconfigboard.h

結果を見ると、ESPRUINO_PICO、PYBLITEV10、STM32F411DISCで値が0になっているほか、F401REでは値の設定もされていません。
F401REがハードウェア乱数発生器を持っているのであれば1、持っていないのであれば0に設定すべきです。
ハードウェア乱数発生器の有無は、STM32のHALの実装を見ると分かります。
micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src の中にある、stm32f4xx_hal_rng.c を見てみます。
すると
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defi
ned(STM32F417xx) ||\
defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defi
ned(STM32F439xx) ||\
defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defi
ned(STM32F469xx) ||\
defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defi
ned(STM32F412Rx) ||\
defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)

となっていて、残念ながらF401REは対象外のようです。
STMicroのアプリケーションノート「AN4230」を見ても、やはりF401REにはハードウェア乱数発生器は載っていないように見えます。(このアプリケーションノート自体は、生成された乱数が暗号学的乱数になっているかテストしたレポートです。)

従って、F401REではLWIP_RAND()に用いる乱数発生器をソフトウェアで実装する必要があります。もちろん暗号学的乱数であることが望ましいですが、MicroPythonにそこまで求めるのはどうかという気もします。

そもそも、乱数生成のソフトはMicroPythonにもともと入っている可能性が高いのではないか? と思い、調べてみたところ、以下が見つかりました。

Pseudo-random number generator ・ Issue #965 ・ micropython/micropython

yasmarangという乱数生成の関数が、MicroPythonのurandomモジュールで実装されていますので、これをLWIP_RAND()の実体として使うことにします。
まず、ports/stm32/rng.cの最後のほうにコードを追加して、ハードウェア乱数生成器が無い場合はyasmarang()を使うようにします。

追記:このやり方だとurandomモジュールが生成する乱数列の再現性が失われてしまうため、修正されたコードではrng.cの内部にyasmarangのコードを複製して使っています。

ports/stm32/rng.c:
#if MICROPY_HW_ENABLE_RNG
//途中省略
MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);

#else

extern uint32_t yasmarang(void);

uint32_t rng_get(void) {
return yasmarang();
}

#endif // MICROPY_HW_ENABLE_RNG

また、yasmarang()はstatic宣言されていますので、これを外部から呼び出せるようにstaticを外します。

extmod/modurandom.c
//STATIC uint32_t yasmarang(void)
uint32_t yasmarang(void)
{


これでリンクが通るようになりました。
使い方ですが、以前のWIZNET5Kと結線は全く同じですが、ソフトウェアは完全互換ではなく微妙に違います。
サンプルが ports/stm32/wiznet_connect.py に入っているのでその通りやればOKです。
明示的にactiveにしたりdhcpでアドレス設定させたりという処理が必要になるようです。

SPI2を使う結線の場合のサンプルです。
例によってスターウォーズ視聴です。
DHCPのアドレス取得など、WIZnet側に任せる場合と比べて初期化にちょっと時間がかかる印象がありますが、F401REを使う場合は、通信速度自体はむしろこちらのほうが高速です。


ラベル:MicroPython
posted by boochow at 10:04| Comment(0) | stm32 | このブログの読者になる | 更新情報をチェックする

2017年10月23日

Nucleo-F401RE + W5500モジュール + MicroPythonでインターネット接続

w5500-nucleo.jpg

先日、Arduino用のイーサネットシールドを無理やりNucleo-F401REボードに接続しましたが、この状態だとやはり危なっかしいので、より小型のモジュールを入手しました。
前回使用したW5100の兄弟チップのW5500を使用したモジュールです。
W5100はSPI以外に8bitバスでも制御可能でしたが、W5500はSPI専用です。
購入したモジュールはフリスクケース程度の大きさでした。
価格はAmazonマーケットプレイスで1000円程度でしたが、Aliexpressからだと$6〜$8くらいで買えるようです。
w5500.jpg


使い方はほぼW5100と同じですが、MicroPythonにはW5500用のドライバを組み込む必要があります。
W5100と違って、W5500はMicroPythonでサポートされていますので、コードを書き換える必要はありません。
現時点のバージョンのMicroPythonでは、makeのオプションで「MICROPY_PY_WIZNET5K=5500」というようにWIZnet5Kのチップ種別を指定できるようになっていますので、gitでcloneするところからmakeのやり方を以下に載せておきます。

git clone https://github.com/micropython/micropython.git
cd micropython/
git submodule update --init
cd ports/unix
make deplibs
make
cd ../stm32/
make BOARD=NUCLEO_F401RE CROSS_COMPILE=~/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi- MICROPY_PY_WIZNET5K=5500
cp build-NUCLEO_F401RE/firmware.hex /mnt/hgfs/share/
#このあとST-Link Utilityでボードに書き込む


接続する端子も、SPIですので基本的には同じです。
購入したモジュールのピン配列(裏面)は下図のようになっていました。

w5500-pins.jpg


ちなみにですが、私の購入したモジュールはピンヘッダが下のように斜めになっていました・・・
実用上は問題ないですが、ちょっと気にはなりますね。

w5500module.jpg


Nucleo-F401REとの接続は以下のようになります(SPI2を使用する場合)。
リセットは自由に決められますが、あとは使用するSPIバスによって自動的に決まってしまいます。

W5500 Nucleo-F401RE
3.3V 3V3
MISO PB14(MISO)
MOSI PB15(MOSI)
SCS PB12(NSS)
SCLK PB13(CLK)
5V -
GND GND
RST PC8
INT -
NC -
表面から見た接続図
stm32-w5500-2.png

(W5500モジュールのfritzingデータはこちら

MicroPythonからの使い方は、W5100のときと全く同じです。
コードは完全に互換性があります。
例によってSTARWARSサイトに接続してみました。
w5500-starwars.png

STM32 + W5500の組み合わせは、Arduino + Ethernetシールドよりもパワフルで、サイズもコンパクトに納まり、有線で使用するにはなかなか良いのではないかと思います。
ラベル:MicroPython
posted by boochow at 23:18| Comment(0) | stm32 | このブログの読者になる | 更新情報をチェックする

2017年10月15日

Nucleo-F401RE + Ethernet(W5100) + MicroPythonでインターネット接続

stm32-w5100.jpg


MicroPythonが動くようになったNucleo-F401REですが、ESP32と比べるとネット接続がありません。
しかし、調べてみるとこのボードにArduino用のイーサネットシールドを接続できることが分かりました。

Adding ethernet connectivity to a STM32-Nucleo

実は、私も買ったまま使っていない(このパターン多いです)Arduino用イーサネットシールドを持っており、上記の記事と同じW5100というチップを使用しているものでした。

このチップはWIZnetというメーカーの製品で、単なるEthernetコントローラではなく、TCP/IPが実装されており、単体で通信ができます。
イメージとしてはESP8266のLANバージョンみたいなものでしょうか。
ESP8266よりもかなり以前からあるシリーズで、国内でもスイッチサイエンスさんなどで扱いがあります。

一方、MicroPythonについて調べてみると、このW5000シリーズがドライバとして組み込めることが分かりました。
ただ、現時点ではサポートされているのはW5200とW5500のみでした。

Ethernet Adapter for PyBoard Which? - MicroPython Forum

なおW5500とSTM32の組み合わせはごく最近バグフィックスされたようです。

drivers: WIP getting WizNet5500 working with stm32 port. by dpgeorge ・ Pull Request #3362 ・ micropython/micropython

残念ながらMicroPythonにはW5100のドライバは入っていませんでしたが、W5200やW5500のドライバを調べてみると、WIZnetが開発したドライバを利用していました。
そこで、WIZnetのGitHubをのぞいてみると、W5100のドライバも用意されていました。
また、これらチップの差分を吸収する抽象レイヤも用意されており、MicroPythonでもそれを使用しているようです。

ということで、「WIZnetのW5100用ドライバをMicroPythonへポーティングするのは簡単なのでは?」と思い、やってみることにしました。

利用したWIZnetのドライバは、現時点での最新版と思われるこちらのライブラリです。

Wiznet/ioLibrary_Driver: Create a repository of WIZnet ioLibrary.

ドライバの入っている「Ethernet」フォルダと、DNSなどのプロトコルを実装している「Internet」フォルダがありますが、Ethernetフォルダだけ使用しました。
MicroPythonではInternetフォルダのDNS実装を使っているようでしたので、最初はこちらも最新のものを使おうかと思ったのですが、最新のほうはコンパイルエラーが出る(というかバグが残っている)ので、使うのをやめました。

このEthernetフォルダを、micropython/drivers/wiznet5k/Ethernetに展開します。
そして、以下のように使用するチップの指定を変更します。
../../ioLibrary_Driver/Ethernet/wizchip_conf.h wizchip_conf.h 
64c64
< #define _WIZCHIP_ 5500 // 5100, 5200, 5300, 5500
---
> #define _WIZCHIP_ 5100 // 5100, 5200, 5300, 5500


また、ドライバの抽象レイヤであるwizchip_conf.cは構造体の初期化のところで文法エラーが出るので修正します。
../../ioLibrary_Driver/Ethernet/wizchip_conf.c wizchip_conf.c 
169,172c169,172
< wizchip_cris_enter,
< wizchip_cris_exit,
< wizchip_cs_select,
< wizchip_cs_deselect,
---
> {wizchip_cris_enter,
> wizchip_cris_exit},
> {wizchip_cs_select,
> wizchip_cs_deselect},
176,177c176,177
< wizchip_bus_readdata,
< wizchip_bus_writedata,
---
> {{wizchip_bus_readdata,
> wizchip_bus_writedata}},


WIZnetチップはソケットのインタフェースが実装されています。
関数名はconnect、listenなどよく知られたAPIが使われていますが、もともとMicroPythonに組み込まれていたものに倣って、ソケット関連の関数名を変更するマクロを導入しました。

../../ioLibrary_Driver/Ethernet/socket.h socket.h
87a88,90
> // use this macro for exported names to avoid name clashes
> #define WIZCHIP_EXPORT(name) wizchip_ ## name
>
162c165
< int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
---
> int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);


以下略しますが、関数名socket, close, listen, connect, disconnect, send, recv, sendto, recvfrom, ctlsocket, setsockopt, getsockoptについて全て上記の変更を行います。
また、socket.cについても同様の変更を行います。
関数の宣言部だけでなく、内部でclose()を呼び出しているところがあるのでそこも変更が必要です。

また、&演算子の使い方でコンパイル時にエラーが出るので、以下を修正しました。
520,521c520,521
< if((taddr == 0) && (getSn_MR(sn)&Sn_MR_MACRAW != Sn_MR_MACRAW)) return SOCKERR_IPINVALID;
< if((port == 0) && (getSn_MR(sn)&Sn_MR_MACRAW != Sn_MR_MACRAW)) return SOCKERR_PORTZERO;
---
> if((taddr == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_IPINVALID;
> if((port == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_PORTZERO;


W5100のドライバは全く変更する必要はありません。ただ、インクルードパスの都合でw5100.hを少しだけ修正します。
../../../../../ioLibrary_Driver/Ethernet/W5100/w5100.h w5100.h
44c44
< #include "wizchip_conf.h"
---
> #include "../wizchip_conf.h"


また、application/dns/フォルダのdns.hも同様に1行だけ修正します。
diff dns.c dns.c~
57c57
< #include "../../Ethernet/socket.h"
---
> #include "../../ethernet/socket.h"


ここでMicroPythonの内部構造を少し書いておきます。
STM32関連の実装は「ports/stm32」に集められています。
networkモジュールはmodnetwork.cで実装されていますが、種類の異なるNICごとの実装は別ファイルになります。
WIZnet5Kシリーズのための実装はmodnwwiznet5k.cにあり、この実装はSTM32のHALライブラリを介してSPIをたたいてWIZnet5Kのデバイスと通信しています。

WIZnet5KドライバのAPIが、もともとMicroPythonに含まれていたものと若干変わっているので、これらのドライバを呼び出すmodnwwiznet5k.c側の修正も必要になりました。
具体的には、SPIのコールバック関数として、1バイトずつの送受信を行うものが新たに必要になりましたので追加しました。
また、W5000シリーズのレジスタの呼び名が若干変更になっています。
diff modnwwiznet5k.c modnwwiznet5k.c.org 
41,42c41,42
< #include "Ethernet/wizchip_conf.h"
< #include "Ethernet/socket.h"
---
> #include "ethernet/wizchip_conf.h"
> #include "ethernet/socket.h"
74,87c74
< STATIC uint8_t wiz_spi_read(void) {
< uint8_t c;
< HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi, &c, 1, 5000);
< (void)status;
< return c;
< }
<
< STATIC void wiz_spi_write(uint8_t c) {
< HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi, &c, 1, 5000);
< (void)status;
< }
<
< //STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
< STATIC void wiz_spiburst_read(uint8_t *buf, uint16_t len) {
---
> STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
92,93c79
< //STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
< STATIC void wiz_spiburst_write(uint8_t *buf, uint16_t len) {
---
> STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
381d366
< reg_wizchip_spiburst_cbfunc(wiz_spiburst_read, wiz_spiburst_write);
424c409
< printf(" %02x", WIZCHIP_READ(WIZCHIP_OFFSET_INC(WIZCHIP_SREG_BLOCK(sn), i)));
---
> printf(" %02x", WIZCHIP_READ(WIZCHIP_SREG_ADDR(sn, i)));


最後にMakefileです。
こちらもW5200指定になっていたのでその修正と、インクルードパスの修正をします。
diff Makefile Makefile.org 
295,297c295,297
< Ethernet/W5100/w5100.c \
< Ethernet/wizchip_conf.c \
< Ethernet/socket.c \
---
> ethernet/w5200/w5200.c \
> ethernet/wizchip_conf.c \
> ethernet/socket.c \


以上で移植作業は完了です。
makeします。

cd micropython/ports/stm32/
make BOARD=NUCLEO_F401RE CROSS_COMPILE=~/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi- MICROPY_PY_WIZNET5K=1
cd build-NUCLEO_F401RE/
cp firmware.hex /mnt/hgfs/share/
#このあとST-Link Utilityで書き込み


実際にNucleo-F401REとW5100でインターネットアクセスしてみました。
結線は下図のようになります。
stm32-w5100.png

Adding ethernet connectivity to a STM32-Nucleoにも書かれていますが、このイーサネットシールドはSPIの信号が、Nucleoボードが持っていない6ピンの端子に出ているため、配線に工夫が必要です。
私のボードは6ピン端子の足元の部分に線が露出していたので、ICクリップを使って接続しました。
ethernet-shield-spi.jpg

まずはESP32のときと同様、アスキーアートSTAR WARSに接続してみます。
SPIオブジェクトがmachine.SPIだとクラスが違うというエラーが出てしまい、pyb.SPIを使う必要がありました。
このへんはMicroPythonの問題だと思います。



ちょっとカクカクしますが、一応表示されました。

starwars.png


以下の記事によると、W5kシリーズの通信速度は、最新のW5500でDMAを使用したとき4.4Mbps、使用しないとき1.7Mbpsくらい出るようです。

STM32F401REでSPI DMAを利用してW5500の送受信性能改善 | WIZnet JP Blog

HTTPでの通信も試してみました。
これまたESP32のときと同じネタです。
今回はLCDは使わず、とりあえず通信できるかどうかの確認です。
WIZNET5Kオブジェクトはreadline()が実装されていなかったので、コードは若干変わっています。



REPLの中で呼び出すと結果が表示されます。

>>> main()
2017-10-13
JPY/USD: 112.18
>>>


ラベル:MicroPython
posted by boochow at 01:11| Comment(0) | stm32 | このブログの読者になる | 更新情報をチェックする

2017年10月09日

Nucleo F401REにMicroPythonをインストールしてみた

f401re-ssd1306.jpg
最近、MicroPythonにだいぶ興味が高まっているのですが、先日動作だけ確認したNucleo-F401REにもMicroPythonが移植されていますので、試しにインストールしてみました。

ファームウェアはMicroPythonのダウンロードページからもダウンロードできますが、ファイル形式がdfuという形式で書き込み方がわかりませんでしたので、今回はソースからビルドしました。
ビルド手順はmicropython Wikiにも記載はありますが、あまり詳しく書かれていないので、フォーラムのこちらの記事を参考にしました。

How to build and run MicroPython on STM32F7-Disco board - MicroPython Forum

上記で解説されている手順では、ファームウェアの書き込みにWindows用のツール(STM32 ST-Link Utility)を使いますが、Linuxで書き込む場合には以下の記事が参考になりそうでした。

Running micropyton on STM32Nucleo-F4

ちなみにビルドに使った環境はESP32のときと同様、Ubuntu-16.04です。
手順を簡単にメモしておくとこんな感じです。
wget https://launchpad.net/gcc-arm-embedded/5.0/5-2016-q3-update/+download/gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2
tar xvfj gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2
sudo apt-get -y install lib32z1 lib32ncurses5
cd micropython/ports/stm32/
make BOARD=NUCLEO_F401RE CROSS_COMPILE=~/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-
cd build-NUCLEO_F401RE/
cp firmware.hex /mnt/hgfs/share/

最後のcpで指定している/mnt/hgfs/shareは私の環境でのWindows側との共有フォルダです。
適宜変更してWindows側へfirmware.hexを持ってきてください。

Windows側へ持ってきたファイルをST-LINKユーティリティでNucleoへ書き込みます。
ST-LINKユーティリティは以下からダウンロードできます。(メールアドレスと氏名の入力が必要です。)

STSW-LINK004 - STM32 ST-LINK utility - STMicroelectronics

MicroPythonが起動した後の操作は、uPyCraftが使えます。
ただ、残念ながらファイルのダウンロード機能が通信エラーでうまく働きませんでした。
ボード側のバッファのサイズ等、条件が違うのかもしれません。
C-eでコードを直接ペーストするぶんには問題ありません。

先日試したOLEDのSSD1306を接続してみました。
結線は以下の通りです。
OLED Nucleo-F401RE
GND GND
VCC 3V3
D0 PB13(CLK)
D1 PB15(MOSI)
RES PC5
DC PC6
CS PB12(NSS)

f401re-ssd1306.png

信号線はArduinoコネクタ(ピンソケット)ではなくMorphoコネクタ(ピンヘッダ)のほうに出ています。
ピン配置は以下のようになっています。
f401re-pins.png

Nucleo-F401REにはSPIが3つあり、SPI1はArduinoコネクタから接続できます。
しかし、SPI1はSCKを接続した時点でuPyCraftとの通信がうまくいかなくなってしまったので、SPI2を使っています。
SPI1のSCKはPA5ですが、ここにはLED2もつながっています。SPIで使うには何か設定が必要なのかもしれません。

SPI1〜SPI3に使う信号線はハードウェアで決まっており、ピンの指定はできません。
信号とピンの関係はports/stm32/boards/NUCLEO_F401RE/mpconfigboard.hを見ると分かります。
今回はSPI2なので、以下の部分が必要な情報です。
なお、NSSはCSの別名らしいです。
#define MICROPY_HW_SPI2_NSS     (pin_B12)   //              pin 16 on CN10
#define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10
#define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10
#define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10

以下が使い方の例です。
SPI2を使用するので、SPIのIDには2を指定します。
from machine import SPI,Pin
spi = SPI(2, baudrate=20000000, polarity=0, phase=0)
oled = SSD1306_SPI(128, 64, spi, res=Pin('PC5'), dc=Pin('PC6'), cs=Pin('PB12'))
oled.text('hello',0,0,1);oled.show()

実行結果が本記事の最初の写真です。
最初のMicroPythonはSTM32F405をターゲットとしていた(Micro Python: Python for microcontrollers by Damien George − Kickstarter)だけあって、動作としては何の問題もありません。
ただ、ホビイストにとっては、NucleoボードはESP32と比較すると大きいのと、WiFiが無いのが欠点ではあります。
ラベル:MicroPython
posted by boochow at 20:45| Comment(0) | stm32 | このブログの読者になる | 更新情報をチェックする

2017年09月18日

STM32専用の開発環境 STM32CubeMX + SW4STM32を試してみた

F401RE.jpg

昨年、スイッチサイエンスさんからNUCLEO-F401REというmbedが使えるボードを購入したのですが、あまり使い道も思いつかず、放置していました。
(単に安かったので買ってみたというのが正直なところです。)

mbedはコンセプトは良いですし、ボードもArduino系よりも強力なものが多いところは頼もしいと思うのですが、開発環境もシステム自体もmbedOS5になってガラリと変わってしまいましたし、手軽さ加減が若干中途半端というか、敷居が高いように思います。

というところに、下記の記事を見かけて面白そうだったので、mbedではない開発環境を試してみることにしました。

CubeMXでLチカ ≫ DSP空挺団

といっても、とりあえずは上記のページの通りにインストールしてLチカを動かしてみただけです。
この記事は大変親切な記事だと思います。

私の場合は使うボードが異なるのと、開発機のOSがWindows7だという点が違いますが、ほぼこの通りにやればうまくいきました。
差分は、NUCLEO-F401REではLEDのピンがPA5になりますので、LEDの点滅の部分のコードも以下のようになります。
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

cubemx.png

あと、一点引っかかったのがコードを実際にボードで実行する部分で、上記の記事では
SW4STM32のメニューバーからRun->Run As->Ac6 STM32 C/C++ Applicationを実行します。

CubeMXでLチカ ≫ DSP空挺団

とありましたが、最初の1度だけは、以下のようにする必要がありました。
書き込みに関しては最初だけ左側のプロジェクトツリーからプロジェクトを左クリックし Debug as -> Ac6 STM32 C/C++ Applicationを選ぶ必要があります。

System workbench for STM32 (2) - 電子工作専科


まだ機能がよく分かっていませんが、デバッグはmbedやArduinoよりも機能が充実しているように思われます。
posted by boochow at 18:10| Comment(0) | stm32 | このブログの読者になる | 更新情報をチェックする
人気記事