PY32F002A を使ってみた その2
PY32F002A つづきとひみつ
USART 経由で書き込んでみる
前回は SWDIO 経由でフラッシュを書き込みましたが、PY32F002A には USART 経由で書き込みできるブートローダが出荷時に書き込まれているので、 何処のご家庭にもある USB-シリアル変換機を使って書き込むことができます。ただし、現状 Windows にしか対応していません。
PUYA のサイトの Downloadの “Tool & Softwares” の中から、 “PY32_IspTool” をダウンロードします。“Document” としか書かれていませんが、書き込みプログラムも含まれています。
展開するとドキュメントや実行ファイルがありますので、PY32IspIool_x64.exe
を実行します。
マイコン側もブートローダを起動する必要があります。
いつもの STM32 のお約束通り、BOOT0
ピンで制御できますので、BOOT0
を Hi にして Reset します。
PY32F002A でも USART1 は PA2(TX) と PA3(RX) なので、ここに USB-シリアルをつなぎます。
ブートローダモードにしたら、接続されているシリアルポートを指定して Connect
を押します。
ちゃんと認識されるとこんな画面になります。
(ぉゃぉゃ……メモリサイズが……)
接続されたら、書き込む “.hex” ファイルを指定して Download
します。
BOOT0
を元にもどして Reset すれば、書き込んだコードが実行されます。
CH32V003 には、せっかくブートローダ領域が存在するにもかかわらず出荷時に IAP 対応ブートローダが書き込まれていないため、 専用の書き込み機が必要でしたが、PY32F002A では必要ないので使い勝手が良い製品だと思います。
なお、現状 ISP 書き込みプログラムは Windows 版しか提供されていませんが、ドキュメントにプロトコルが公開されているので、 他の OS の方は自分で書き込みプログラムを作ることもできるようにはなっています。(そこは面倒だが…)
STM32 の LL API のコードをそのまま持ってきてみる
STM32C011 で試した、「ドラクエのアレ」を PY32F002A に持ってきます。 元のコードは STM32CubeMX でチップの設定をおこない、LL API を使って書かれています。
- 動作クロック 48MHz
- TIM3 で 48KHz 周期割り込み
- TIM1CH4 で PWM 出力
main.c
はそのまま、stm32c011_it.c
の割り込みハンドラを py32fxx_it.c
の中にコピーします。
- マイコン関係ファイルが違う
Example
の中の適当な LL API の例から main.h
py32assert.h
py32fxx_it.h
py32fxx_it.c
の 4つのファイルを持ってきます。
main.h
の中身は、STM32 の main.h
を参考に編集します。
STM32 でこうなっていた場合
#include "stm32c0xx_ll_rcc.h"
#include "stm32c0xx_ll_bus.h"
#include "stm32c0xx_ll_system.h"
#include "stm32c0xx_ll_exti.h"
#include "stm32c0xx_ll_cortex.h"
#include "stm32c0xx_ll_utils.h"
#include "stm32c0xx_ll_pwr.h"
#include "stm32c0xx_ll_dma.h"
#include "stm32c0xx_ll_tim.h"
#include "stm32c0xx_ll_gpio.h"
PY32 ではこうなります。
#include "py32f0xx_ll_rcc.h"
#include "py32f0xx_ll_bus.h"
#include "py32f0xx_ll_system.h"
#include "py32f0xx_ll_exti.h"
#include "py32f0xx_ll_cortex.h"
#include "py32f0xx_ll_utils.h"
#include "py32f0xx_ll_pwr.h"
#include "py32f0xx_ll_dma.h"
#include "py32f0xx_ll_tim.h"
#include "py32f0xx_ll_gpio.h"
- ペリフェラルパワー関連が違う
STM32 では AHB1/APB1/APB2 となっていましたが、PY32F002A では AHB1/APB1/IOP です。
例えば、
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
は
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM1);
になります。
- ピン配置が違う
TIM1CH4 はデフォルトでは PA11 ですが、PY32F002AF15 には PA11 はありません。 したがって、PA1 にリマップします。
GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_2;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
は、こうなります。
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_13;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- クロック設定が違う
めんどいので BSP のクロック設定をそのまま使いました。
SystemClock_Config();
BSP_RCC_HSI_PLL48MConfig();
その他細かい修正はありますが、大体これくらいで動きました。メインのコードは一切触っていません。
ハードウェアに密接な LL API でもこのくらいの修正でうごくので、HAL ならもっと修正箇所少なくていけるのではないかと思います。 ほぼ STM32 そのままの HAL や LL API があるということで、移植はかなり楽に行えます。
PY32F002A のひみつ
すでにお気づきの方もいるかもしれませんが、PY32F002A には Timer3 も 48MHz PLL も公式には載っていません。 しかしながら、実際には PY32F030Fx6 と同じダイを使っているようで、データシート上存在しない機能を使うことができます。
PY32F002A(実際) | PY32F002A(公称) | CH32V003 | |
---|---|---|---|
Core | Cortex M0+ | Cortex M0+ | RV32EC |
MaxClock | 48MHz | 24MHz | 48MHz |
Flash | 32KB | 20KB | 16KB |
SRAM | 4KB | 3KB | 2KB |
Timer | 6 | 3 | 2 |
SPI | 2 | 1 | 1 |
I2C | 2 | 1 | 1 |
USART | 2 | 1 | 1 |
DMA | 3 | 0 | 7 |
ADC | 12bit 10ch | 12bit 8ch | 10bit 8ch |
なかったはずの DMA もちゃんと存在します。
CH32V003 の DMA は 7ch ありますが、ch とペリフェラルの割り当てが固定なのに対して、PY32F030 の DMA は自由に割り当てできますので、実用上は問題ないかと思います。
PY32F030 では、DMA の割り当てを SYSCFG->CFGR3 を使って自由に変更できますが、PY32F002A ではこのレジスタが存在せず常に 0 になっています。
よってメモリ間の DMA しかできません。(ひょっとしたら ADC は 0 に設定するので DMA できるかも?)
DMA の割り当ては、SYSCFG->CFGR3 を通して行います。例えば、CH1 に SPI1_TX からの要求を割り当てるには、LLライブラリでは以下のようになります。
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
LL_SYSCFG_SetDMARemap_CH1(LL_SYSCFG_DMA_MAP_SPI1_TX);
SYSCFG もペリフェラル扱いなので、クロックを供給しないと動作しません。
フラッシュサイズについては、ISP の画面
を見ていただければ、“Flash size 32KB, Sram size 4KB” とあるのがわかるかと思います。
というわけで、実質的には PY32F030Fx6 の機能を使える「20円マイコン」PY32F002A を使ってみませんか?