64ビットRISC-V RV64GC 400 MHzをデュアルコアで搭載する.8MBのオンチップSRAMと16MBの外部フラッシュを持つ.
マイコンとしては,大量のメモリを持つため,画像系のアプリケーションで存在感を発揮できると思われる.
K210の仕様
ハードウェア・アクセラレータによる画像認識
FPU付のデュアルコア・プロセッサ
RAM:8MB(6MB+2MB)
外部フラッシュ:16MB
CPU最高動作周波数:800MHz(ボードによりけり)
マイク アレイ(8個)
ハードウェアAES,SHA256
FPIOA (ペリフェラルIOのリマッピング)
ペリフェラルPeripherals: I2C,SPI,I2S,WDT,TIMER,RTC,UART,GPIOなど
K210搭載ボード
- Maixduino(Arduino互換ピンヘッダ,ESP32搭載,LCD付き,カメラ付き(秋月電子,Sigezone)
- MAix M1((Sigezone))
- Maix Bit Suit(LCD付き,カメラ付き(秋月電子))
- Maixcube((Switch Science))
- Sipeed Maix M1 Dock((Switch Science))
- M1 Dock(LCD付き,カメラ付き(秋月電子))
- M5StickV(カメラ内蔵,バッテリ,LCD内蔵,(M5Stack,Switch Science))
- M5UnitV(カメラ内蔵(M5Stack,Switch Science))
- Maix Amigo(カメラ内蔵×2,タッチパネル3.5インチLCD,520mAhリポ・バッテリ,スピーカ,マイク)
ボード1:Maixduino
K210に加え,ESP32も載っているので無線通信機能が使える.国内の販売店でも手に入りやすい.ピンソケットはArduino Uno互換.
ボード7:M5StickV
IMU,液晶,バッテリ, microSDカードスロット付き.ケースに入っているのでPOCやホビーに使いやすい.
ボード8:M5UnitV
M5StickVからLCDとバッテリを無くした製品.その分厚みが薄くなっている.とてもコンパクト.
ボード9:Maix Amigo
当初$39であったが,LCDがIPSに替り$49になったようだ.
ピン配置
https://github.com/sipeed/MaixPy_scripts/blob/master/board/config_maix_amigo.py
インターフェース
https://github.com/sipeed/Sipeed_HardWare/blob/master/en/maixpy_develop_kit_board/maix_Amigo.md
回路図(IPS版)
https://dl.sipeed.com/fileList/MAIX/HDK/Sipeed-Amigo/2970/Maix_Amigo_2970(Schematic).pdf
回路図(TFT版)
https://dl.sipeed.com/fileList/MAIX/HDK/Sipeed-Amigo/2960/Maix_Amigo_2960(Schematic).pdf
https://cn.maixpy.sipeed.com/maixpy/en/develop_kit_board/maix_amigo.html
開発フレームワーク
フレームワーク1:MaixPy
上記の開発ボードのほとんどに最初からMaixPyのファームウェアが書き込まれている.
Cで開発するために,消してしまった場合でも,公式ページから入手し,再度書き込めばMaxiPyを使用できる.
PythonのサブセットであるMicroPythonがベース.公式レファレンスのページは中国語・英語は情報が豊富.低レベルのフレームワークはKendryte standalone SDK(FreeRTOSも取り込まれているようである)のようである.
画像系ライブラリが豊富で,ライブラリの処理速度も十分速い(もちろんmicropythonで書いた部分は遅い).
MicroPythonベースなので,疑似的なファイルシステムを使用できる.
PCとUSBケーブルでつないでREPLで実行できる.
ルートディレクトリにboot.pyというファイル名でプログラムを保存しておくとデバイス起動時に実行される.
専用のIDEであるMaixPyIDEを使って開発する.このIDEは内蔵カメラの画像(フレームバッファ)をIDEのウィンドウに表示できて便利.画像のヒストグラムも表示されるので,画像処理アプリケーションの開発がやりやすい.
・maixpyのリポジトリ
https://github.com/sipeed/MaixPy
https://wiki.sipeed.com/soft/maixpy/en/api_reference/standard/index.html
アプリ例
画像処理で硬貨を判別
https://qiita.com/Lathe/items/07625e4759eac5eb0280
ファームウェアのリビルド
やり方は,以下のサイトに詳しい(M5StickVでのやり方).
ビルド環境にはpyserialが必要.pip3 install pyserial
すること.
大きな画像を扱うと,heapメモリが足りない場合がある.ファームウェアのリビルドでメモリの空きを増やせる.gc側のheap領域を増やすには,Maixパッケージのgc_heap_size()
を呼ぶ.詳細はアプリ例を参照の事.
https://raspberrypi.mongonta.com/howto-build-firmware-of-m5stickv/
現在では,SipeedのリポジトリがMaxiPy
からMaixpy-v1
に変わっています.(現在のMaixPyリポジトリはv4用)
フレームワーク2:Kendryte K210 standalone SDK
K210開発元のKendryteによるSDK.OSを使わないシステム.C言語で開発する.
Linux,Windows,macOSに対応.
FreeRTOSを取り込んだKendryte FreeRTOS SDKもある.
Kendryte FreeRTOSプログラミングガイト
https://dl.sipeed.com/MAIX/SDK/Document/kendryte_freertos_programming_guide_en.pdf
https://github.com/kendryte/kendryte-freertos-sdk
K210 Standalone SDK プログラミングガイド
https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_standalone_programming_guide_20190311144158_en.pdf
・SDKのリポジトリ
https://github.com/kendryte/kendryte-standalone-sdk
・デモのリポジトリ
https://github.com/kendryte/kendryte-standalone-demo
このリポジトリに複数のデモプロジェクトがありますが,そのままでは動かない物が多いです.I/Oポートの設定などを使用するボードに合わせる必要があります.
環境構築Windows
- CMakeをインストール(Download cmake-3.14.1-win64-x64.msi)
- 最新版のツールチェインをインストール(Download kendryte-toolchain-win-i386-8.2.0-20190409.tar.xz)
- Powershellで適当なフォルダを作って,コードをコピーして,ビルドする.
フレームワーク3:ArduinoCore-k210
Arduinoフレームワークを利用する.統合環境はArduino IDEである.
kendryte-standalone-sdkをベースに作られている.
https://github.com/Seeed-Studio/ArduinoCore-k210
[ファイル]-[環境設定]-「追加のボードマネージャのURL」に
https://raw.githubusercontent.com/Seeed-Studio/Seeed_Platform/master/package_seeeduino_boards_index.json
を追加する.
現状使えない.
フレームワーク4:Maixduino
Maixduinoは,Sipeed製のボードの名前でもあるが,フレームワークの名称でもある.
現状で最もまともに開発されているフレームワークだと思われる.Kendryte Standard SDKをベースにArduinoフレームワークに対応させたものだと思われる.リポジトリにはFreeRTOSのフォルダがあるので一部FreeRTOSを取り込んでいるのかも?
Arduino IDEやPlatformIOと組み合わせて使える.
名称が違うだけで,多分ArduinoCore-k210と同じもの.
何も考えなくてもArduinoの関数が使えるので楽.
ボードマネージャに登録されているボードであれば環境構築が非常に簡単である.登録がないボードは自分で登録するか,似ているボードの設定を利用しつつソースコード上で対処するしかない.
※MaixAmigo Boardは筆者が独自に登録したものだった気がする...
ライブラリのリポジトリ
https://github.com/sipeed/Maixduino/tree/master/libraries
ピン配置
https://github.com/sipeed/Maixduino/blob/master/variants/sipeed_maix_amigo/pins_arduino.h
IDE
IDE1:Arduino IDE
フレームワークはMaixduinoを使う.
環境構築
[ファイル]-[環境設定]-「追加のボードマネージャのURL」に,
http://dl.sipeed.com/MAIX/Maixduino/package_Maixduino_k210_index.json
を追加する.
・ターゲットボード用の設定(MaxiAmigoの場合)
現状ボードとして選べるものにMaix Amigoが無いので,maixduino(k210)を追加する.
9600でシリアル通信はできるが,Wiringライブラリすらうまく動かないようである.
現状では,Maix AmigoではLチカくらいしかできない.
Maix Amigoの場合,I2Cへ接続されている端子がSDA=27,SCL=24なので,wire.begin()で設定しなければI2Cが動かない(サンプルmsa_basic参照).
ピンの設定がMaxiduinoとはかなり違っている.MaixAmigo用のボード定義が提供されていないので,Maixduino用を元にして作る.
Maix Amigoで動作確認した際の設定は次の通り.
- board:sipeeed maixduino board(現状Maix Amigoは無い)
- 書込装置:k-flash
サンプル・スケッチ
サンプル1:Blinker
スケッチの抜粋を次に示す.LEDのGPIO番号を編集する.
#include <Arduino.h>
#include <Ticker.h>
// attach a LED to pPIO 13
#define LED_PIN 32 //for Maix Amigo
Ticker blinker(TIMER0);
Ticker toggler(TIMER1);
Ticker changer(TIMER2);
float blinkerPace = 0.1; //seconds
const float togglePeriod = 5; //seconds
void change() {
サンプル2:msa_basic
スケッチを次のように書き換え,ライブラリのMSA300.cppの中のbegin()の始めの方にあるWire.begin()をコメントアウトする.
(もしくはMaix Amigo用のボード定義を作り,I2Cのピンを正しく設定しておく)
void setup()
{
Serial.begin(9600);
Wire.begin((uint8_t)27,(uint8_t)24,100000);
msa.begin();
}
IDE2:VS Code+PlatformIO
PlatformIOから使えるフレームワークは,次の3つ.
- Arduino(Maixduino)
- Kendryte Standalone SDK
- Kendryte FreeRTOS SDK
platformIO Kendryte FreeRTOS SDK
https://docs.platformio.org/en/latest/frameworks/kendryte-freertos-sdk.html#framework-kendryte-freertos-sdk
PlatformIOのK210のページ
https://docs.platformio.org/en/latest/platforms/kendryte210.html
https://maixduino.sipeed.com/en/
実機での開発例
MaixAmigo + VS Code + PlatformIO + Kendryte Standard SDK
参考サイト
https://robopara.co.jp/setting_up_maixduino_on_platformio/
環境構築
その1:Kendryte-standalone-sdk_hello
- VS Codeをインストール
- PlatfomrIOをインストール
- K210ツールチェーンをインストール(「PIO Home」-「Platforms」からKeydryte k210をインストール)
- サンプルプロジェクトを読み込み(「PIO HOME」-「Project Example」からkendryte-standalone-sdk_helloを選ぶ)
- platformio.iniでboardはmaix-maix-goに設定(maix-amigo用のボード定義は無い)
- platformio.iniで正しいportに設定(k210とESP32で2ポートあるのでk210側のポートを指定)
- サンプルプロジェクトをビルド/書き込み
その2:Kendryte-standalone-sdk-demo
- GitHubからリポジトリ https://github.com/kendryte/kendryte-standalone-demo を取得.
- 実行したいデモを「やり方1」のsrcディレクトリにコピー
- MaixAmigoに合わせてI/Oなどの設定を変更
- ビルド/書き込み
サンプルプログラム
kendryte-standalone-sdkを使ったサンプルプログラムを幾つか示します.
####サンプル:Lチカ
#include <stdio.h>
#include "fpioa.h"
#include "sysctl.h"
#include "board_config.h"
#include "gpio.h"
#include "timer.h"
void timer1();
int8_t ledState = 0; //state of LED, ON/OFF
int main(void)
{
gpio_init();
fpioa_set_function(32, FUNC_GPIO3); //物理32番ピンを論理3番に割り当て
gpio_set_drive_mode(3,GPIO_DM_OUTPUT); //3番ピンを出力に設定
timer_init(TIMER_DEVICE_0);
timer_set_interval(TIMER_DEVICE_0, TIMER_CHANNEL_0, 1e9); //タイマインターバルを1秒に設定
timer_set_irq(TIMER_CHANNEL_0, TIMER_CHANNEL_0, timer1, 1);
timer_set_enable(TIMER_CHANNEL_0, TIMER_CHANNEL_0, 1);
sysctl_enable_irq();
while (1);
}
void timer1(){ //タイマ割り込みで呼ばれる関数
ledState = !ledState;
gpio_set_pin(3, ledState); //I/O 論理3番ピンに出力
}
####サンプル:Lチカ②
#include <stdio.h>
#include "fpioa.h"
#include "sysctl.h"
#include "board_config.h"
#include "gpio.h"
#include "timer.h"
#include <unistd.h>
#include "bsp.h"
int8_t ledState = 0; //state of LED, ON/OFF
int main(void)
{
gpio_init();
fpioa_set_function(32, FUNC_GPIO3); //物理32番ピンを論理3番に割り当て
gpio_set_drive_mode(3,GPIO_DM_OUTPUT); //3番ピンを出力に設定
while(1){
ledState = !ledState;
gpio_set_pin(3, ledState);
sleep(1); //bsp.h is needed
}
}
サンプル:UART
K210には通常のUART(最高5Mbps)と高速UART(最高5Mbps)があります.どう使い分けるんだろう?
#include <stdio.h>
#include "fpioa.h"
#include "uart.h"
#include "gpio.h"
#include "sysctl.h"
#define UART_NUM UART_DEVICE_1
int8_t sideLED_State = 1; //インジケータ用LEDのON/OFF状態
void io_mux_init(void)
{
fpioa_set_function(4, FUNC_UART1_RX + UART_NUM * 2); //物理4番ピンをUART1RXに設定
fpioa_set_function(5, FUNC_UART1_TX + UART_NUM * 2);
fpioa_set_function(15, FUNC_GPIO7); //サイドLED[物理pin15]をインジケータLED[論理7番]として使う
}
int main()
{
io_mux_init();
plic_init();
sysctl_enable_irq();
gpio_set_drive_mode(7, GPIO_DM_OUTPUT); //インジケータ用LED設定
gpio_set_pin(7, GPIO_PV_LOW); //インジケータLED ON
uart_init(UART_NUM); //UART初期化
uart_config(UART_NUM, 115200, UART_BITWIDTH_8BIT, UART_STOP_1, UART_PARITY_NONE); //UART設定[this method is diprecated, use uart_configure()]
char *mess = {"Interface\n"};
uart_send_data(UART_NUM, mess, strlen(mess)); //UARTにメッセージ出力
char rec = 0;
while (1)
{
while(uart_receive_data(UART_NUM, &rec, 1))
{
sideLED_State = !sideLED_State; //インジケータLED反転
gpio_set_pin(7, sideLED_State);
uart_send_data(UART_NUM, &rec, 1); //入力された文字をバック
}
}
}
サンプル:printf
#include <stdio.h>
#include <sysctl.h>
#include <unistd.h>
#include "bsp.h"
int main(void)
{
plic_init();
while(1){
printf("Interface Magazine\n"); //unistd.h is needed
sleep(1); //bsp.h is needed
}
}
サンプル:GPIO入力
#include <stdio.h>
#include <unistd.h>
#include "fpioa.h"
#include "gpio.h"
#include "bsp.h"
int main(void)
{
fpioa_set_function(20, FUNC_GPIO3);
fpioa_set_function(23, FUNC_GPIO4);
gpio_init();
gpio_set_drive_mode(3, GPIO_DM_INPUT); //FUNC_GPIO3を入力に設定
gpio_set_drive_mode(4, GPIO_DM_INPUT);
int8_t key1,key2;
while (1){
sleep(1);
key1 = gpio_get_pin(3); //ピンの値を読み取り
key2 = gpio_get_pin(4);
printf("key1: %d key2: %d\n", key1, key2);
}
return 0;
}
サンプル:割り込み
どのような外部割込みも,それぞれのCPUコアの外部割込みソースとして割り当てられるため,アプリケーションの要求に柔軟に対応できます.
機能
PLICモジュールは次の機能を持っています.
- 割り込みの有効化/無効化
- 割り込みハンドラの設定
- 割り込みプライオリティの調整
API
ヘッダファイルplic.h
により次のAPIが提供されます.
関数 | 機能 |
---|---|
plic_init |
plicの初期化 |
plic_irq_enable |
割り込み有効化 |
plic_irq_disable |
割り込み無効化 |
plic_set_priority |
プライオリティの設定 |
plic_get_priority |
プライオリティの取得 |
plic_irq_register |
割り込みハンドラの設定 |
plic_irq_deregister |
割り込みハンドラの削除 |
割込み元を示す主な定数
| 定数 | 内容
---|---|---
1 | IRQN_SPI0_INTERRUPT | SPI0
4 | IRQN_SPI3_INTERRUPT | SPI3
8 | IRQN_I2C0_INTERUPT | I2C0
10 | IRQN_I2C2_INTERRUPT | I2C2
11 | IRQN_UART1_INTERRUPT | UART1
13 | IRQN_UART3_INTERRUPT | UART3
14 | IRQN_TIMER0A_INTERRUPT | TIMER0 CHANNEL0か1
19 | IRQN_TIMER2B_INTERRUPT | TIMER2 CHANNEL2か3
20 | IRQN_RTC_INTERRUPT | RTC
21 | IRQN_WDT0_INTERRUPT | WDT0
22 | IRQN_WDT1_INTERRUPT | WDT1
27 | IRQN_DMA0_INTERRUTP | DMA channel0
32 | IRQN_DAM5_INTERRUPT | DAM channel5
34 | IRQN_GPIOHS0_INTERRUPT | HGPIO0
65 | IRQN_GPIOHS31_INTERRUPT | HGPIO31
プログラム
gpiohs.c
クラスに上記のAPIより高位の関数があります.割り込みハンドラへ引数を渡したい場合などに便利です.
#include <stdio.h>
#include <unistd.h>
#include "fpioa.h"
#include "gpiohs.h"
#include "bsp.h"
#include "plic.h"
#include "sysctl.h"
int8_t key1IRQ = 0;
int8_t key2IRQ = 0;
void key1_onchange_isr(void){
key1IRQ = 1;
}
void key2_onchange_isr(void){
key2IRQ = 1;
}
int main(void){
fpioa_set_function(20, FUNC_GPIOHS3);
fpioa_set_function(23, FUNC_GPIOHS4);
gpiohs_set_drive_mode(3, GPIO_DM_INPUT);
gpiohs_set_drive_mode(4, GPIO_DM_INPUT);
gpiohs_set_pin_edge(3, GPIO_PE_FALLING); //立下りエッジで割り込み
gpiohs_set_pin_edge(4, GPIO_PE_FALLING);
plic_init ();
gpiohs_irq_register(3, 1, key1_onchange_isr, NULL); //割り込みハンドラとプライオリティを登録
gpiohs_irq_register(4, 3, key2_onchange_isr, NULL);
sysctl_enable_irq ();
while (1){
if(key1IRQ){
printf("key1 is pressed\n");
key1IRQ = 0;
}
if(key2IRQ){
printf("key2 is pressed\n");
key2IRQ = 0;
}
}
return 0;
}
サンプル:PWM
K210にはタイマが3つ(TIMER_DEVICE_0~TIMER_DEVICE_2)あります.各タイマには4つのチャネルがあります(TIMER_CHANNEL_0~TIMERCHANEEL3).
PWM機能にはタイマを利用します.タイマ機能とPWM機能が競合しないようデバイスとチャネルを設定すること.
FPIOAで指定するデバイスと,PWMデバイス&チャネルの対応は下表の通り.TOGGLE1がCHANNEL0に対応するところに注意.
PWM(FPIOAでの指定) | PWMデバイス | PWMチャネル |
---|---|---|
FUNC_TIMER0_TOGGLE1 | PWM_DEVICE_0 | PWM_CHANNEL_0 |
FUNC_TIMER0_TOGGLE2 | PWM_DEVICE_0 | PWM_CHANNEL_1 |
FUNC_TIMER0_TOGGLE3 | PWM_DEVICE_0 | PWM_CHANNEL_2 |
FUNC_TIMER0_TOGGLE4 | PWM_DEVICE_0 | PWM_CHANNEL_3 |
FUNC_TIMER1_TOGGLE1 | PWM_DEVICE_1 | PWM_CHANNEL_0 |
FUNC_TIMER1_TOGGLE2 | PWM_DEVICE_1 | PWM_CHANNEL_1 |
FUNC_TIMER1_TOGGLE3 | PWM_DEVICE_1 | PWM_CHANNEL_2 |
FUNC_TIMER1_TOGGLE4 | PWM_DEVICE_1 | PWM_CHANNEL_3 |
FUNC_TIMER2_TOGGLE1 | PWM_DEVICE_2 | PWM_CHANNEL_0 |
以下同じ |
#####API1:pwm_set_frequency()のシグネチャ
double pwm_set_frequency (pwm_device_number_t pwm_number, pwm_channel_number_t channel, double frequency, double duty)
引数
pwm_number
PWMデバイスを番号で指定[PWM_DEVICE_0~PWM_DEVICE_2]
channel
PWMチャネルを番号で指定
frequency
PWM周波数を指定[Hz]
duty
デューティー比を指定[1が100%]
返値
PWM周期
次のサンプルは,タイマ1が50msecごとにtimerFunc
を呼び出します.このtimerFunc
関数の中でPWMのduty
を変更しています.
プログラム
#include <stdio.h>
#include <timer.h>
#include <pwm.h>
#include <plic.h>
#include <sysctl.h>
#include <fpioa.h>
float duty = 1.0;
void timerFunc(void){
duty -= 0.01;
if (duty <= 0.3) duty = 1;
pwm_set_frequency(PWM_DEVICE_0, PWM_CHANNEL_0, 20000, duty); //duty比を変更
}
int main(void)
{
fpioa_set_function(32, FUNC_TIMER0_TOGGLE1); //LED_W[pin32]をPWMのデバイス0・チャネル0に設定
plic_init();
pwm_init(PWM_DEVICE_0);
pwm_set_frequency(PWM_DEVICE_0, PWM_CHANNEL_0, 20000, duty);
pwm_set_enable(PWM_DEVICE_0, PWM_CHANNEL_0, 1);
timer_init(TIMER_DEVICE_1); //タイマ1を初期化
timer_set_interval(TIMER_DEVICE_1, TIMER_CHANNEL_2, 50000000); //タイマ1のチャネル2をインターバル50msecに設定
timer_set_irq(TIMER_DEVICE_1, TIMER_CHANNEL_2, timerFunc, 1);
timer_set_enable(TIMER_DEVICE_1, TIMER_CHANNEL_2, 1);
sysctl_enable_irq();
while(1){}
}
サンプル:RTC
リアルタイムクロックは時間に関する機能を提供します.PLL0がEnableかつ,CPUクロックが30MHz以上の場合に使用できます.
次の機能を持っています.
- 現在のデータと時間の取得
- 現在のデータと時間を設定
- 時間間隔の設定
- アラーム間隔の設定
API:int rtc_timer_set()
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second)
引数
返値
なし(関数の型がintなのになぜ?)
プログラム
Kendryte-standalone-sdk-demoのrtcがそのまま実行可能です.
サンプル:SYSCTL
システムコントロールは,SoC(マイコン・チップ)に関わる設定機能を提供します.
PLLは,SYSCTL_PLL0
~SYSCTL_PLL2
まで3つあります.
機能
- PLLとCPUクロックの設定
- それぞれのクロックの分割値を設定
- それぞれの現在のクロックを取得
- 各モジュールの有効化/無効化とリセット
- DMAリクエストソースを設定
- システム割り込みを有効化/無効化
17個の関数があります.主要なものを次に示します.
API:sysctl_cpu_set_freq():
CPUの動作周波数を設定します.これはPLL0の周波数を変更することで行われます.
uint32_t sysctl_cpu_set_freq(uint32_t freq)
引数
freq
設定するCPU周波数[Hz]
返値
設定されたCPU周波数
API:sysctl_pll_set_freq()
PLL周波数を設定します.
uint32_t sysctl_pll_set_freq(sysctl_pll_t pll, uint32_t pll_freq)
引数
pll
設定するPLLの番号
pll_freq
設定する周波数[Hz]
返値
設定後のPLL周波数
API:sysctl_clock_set_threshold()
各ペリフェラルへ供給するクロックの分割値を設定します.
void sysctl_clock_set_threshold(sysctl_threshold_t which, int threshold)
引数
which
対応するペリフェラルをsysctl_threshold_t型で指定
threshold
周波数の分割値
API:sysctl_clock_set_clock_select()
クロックソースを設定します.
int sysctl_clock_set_clock_select(sysctl_clock_select_t which, int select)
引数
which
設定したいペリフェラル
select
クロックソース
返値
成功した場合に0
API:sysctl_set_power_mode()
電源ドメインごとに供給電圧を設定します.
void sysctl_set_power_mode(sysctl_power_bank_t power_bank, sysctl_io_power_mode_t io_power_mode)
引数
power_bank
電源ドメインの番号[SYSCTL_POWER_BANK0~SYSCTL_POWER_BANK7]
io_power_mode
電圧の選択.[0:3.3V, 1:1.8V]
プログラム
サンプル:LCD
MaixAmigoのLCDコントローラはILI9486です.
デモに含まれるlcd
ですが,LICHEEDANをDEFINEすれば一応動きます.次のプログラムではIF DEF
を外してLICHEEDANをDEFINEした時と同じコードになるようにしてあります(もしくはboard_config.h
でDEFINE LICHEEDAN 1
する).
lcd.h
で画面サイズが定義されているので,320×480にするとよいでしょう.
プログラム1
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "fpioa.h"
#include "lcd.h"
#include "sysctl.h"
#include "nt35310.h"
#include "board_config.h"
uint32_t g_lcd_gram[LCD_X_MAX * LCD_Y_MAX / 2] __attribute__((aligned(128))); //画像保持用配列
static void io_set_power(void)
{
sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18);
}
static void io_mux_init(void)
{
fpioa_set_function(38, FUNC_GPIOHS0 + DCX_GPIONUM);
fpioa_set_function(36, FUNC_SPI0_SS3);
fpioa_set_function(39, FUNC_SPI0_SCLK);
fpioa_set_function(37, FUNC_GPIOHS0 + RST_GPIONUM);
sysctl_set_spi0_dvp_data(1);
}
int main(void)
{
printf("lcd test\n");
io_mux_init();
io_set_power();
lcd_init();
lcd_set_direction(DIR_XY_LRUD); //画面方向をLRUDに変更(上下鏡像)
lcd_clear(RED); //全画面を赤でクリア
lcd_draw_picture(0, 0, 240, 160, g_lcd_gram); //画像描画
lcd_draw_string(16, 40, "Canaan", RED); //文字描画
lcd_draw_string(16, 80, "Kendryte K210", BLUE);
while (1);
}
プログラム2
MaixPy(MicroPython)の実装から持ってきたLCD(ILI9486)の初期化シーケンス.
void lcd_init(void)
{
tft_hard_init();
//soft reset
tft_write_command(SOFTWARE_RESET);
usleep(100000);
//exit sleep
tft_write_command(SLEEP_OFF);
usleep(100000);
uint8_t t[15];
tft_write_command(0XF1); /* Unk */
t[0] = (0x36);
t[1] = (0x04);
t[2] = (0x00);
t[3] = (0x3C);
t[4] = (0X0F);
t[5] = (0x8F);
tft_write_byte(t, 6);
tft_write_command(0XF2); /* Unk */
t[0] = (0x18);
t[1] = (0xA3);
t[2] = (0x12);
t[3] = (0x02);
t[4] = (0XB2);
t[5] = (0x12);
t[6] = (0xFF);
t[7] = (0x10);
t[8] = (0x00);
tft_write_byte(t, 9);
tft_write_command(0XF8); /* Unk */
t[0] = (0x21);
t[1] = (0x04);
tft_write_byte(t, 2);
tft_write_command(0XF9); /* Unk */
t[0] = (0x00);
t[1] = (0x08);
tft_write_byte(t, 2);
tft_write_command(0x36); /* Memory Access Control */
t[0] = (0x28);
tft_write_byte(t, 1);
tft_write_command(0xB4); /* Display Inversion Control */
t[0] = (0x00);
tft_write_byte(t, 1);
tft_write_command(0xC1); /* Power Control 2 */
t[0] = (0x41);
tft_write_byte(t, 1);
tft_write_command(0xC5); /* Vcom Control */
t[0] = (0x00);
t[1] = (0x18);
tft_write_byte(t, 2);
tft_write_command(0xE0); /* Positive Gamma Control */
t[0] = (0x0F);
t[1] = (0x1F);
t[2] = (0x1C);
t[3] = (0x0C);
t[4] = (0x0F);
t[5] = (0x08);
t[6] = (0x48);
t[7] = (0x98);
t[8] = (0x37);
t[9] = (0x0A);
t[10] = (0x13);
t[11] = (0x04);
t[12] = (0x11);
t[13] = (0x0D);
t[14] = (0x00);
tft_write_byte(t, 15);
tft_write_command(0xE1); /* Negative Gamma Control */
t[0] = (0x0F);
t[1] = (0x32);
t[2] = (0x2E);
t[3] = (0x0B);
t[4] = (0x0D);
t[5] = (0x05);
t[6] = (0x47);
t[7] = (0x75);
t[8] = (0x37);
t[9] = (0x06);
t[10] = (0x10);
t[11] = (0x03);
t[12] = (0x24);
t[13] = (0x20);
t[14] = (0x00);
tft_write_byte(t, 15);
tft_write_command(0x3A); /* Interface Pixel Format */
t[0] = (0x55); //RGB565
tft_write_byte(t, 1);
/*display on*/
tft_write_command(DISPALY_ON);
lcd_polling_enable();
}
サンプル:SDカード
Kendryte-standalone-sdk-demoに含まれるsd_card_file
はI/Oの設定だけ替えればMaixAmigoで実行できます.
以下に変更部を示します.
プログラム
void io_mux_init(void)
{
fpioa_set_function(11, FUNC_SPI0_SCLK);
fpioa_set_function(10, FUNC_SPI0_D0);
fpioa_set_function(6, FUNC_SPI0_D1);
fpioa_set_function(26, FUNC_GPIOHS7);
//fpioa_set_function(12, FUNC_SPI0_SS3);
}
サンプル:I2S
MaixAmigoにはES8374が搭載されている(スピーカも).
ES8374に限った話ではないが,とにかくハードウェアの情報がない.しかたないのでMaixPyの実装から情報を拾ってくる.
割とES8374の初期化が面倒なので,こちら(https://github.com/shuichitakano/fmsx210)を使わせていただく.MSXをポーティングされているようだが,ペリフェラルがちゃんとライブラリっぽくなっているので流用できそう.おそらく作者の方もMaxiPyの実装を持ってきているっぽい.ライセンスがMITなのでありがたいですね.
プログラム
MaixAmigoのI/O
pin | 機能 | グループ |
---|---|---|
14 | LED_R(サイドのフルカラーLED) | LED |
15 | LED_G(サイドのフルカラーLED) | LED |
17 | LED_B(サイドのフルカラーLED) | LED |
32 | LED_W(カメラ横のLED) | LED |
24 | I2C_SCL | I2C |
27 | I2C_SDA | I2C |
19 | LCD_TEN | LCD |
36 | LCD_CS | LCD |
37 | LCD_RST | LCD |
38 | LCD_DC(RS) | LCD |
39 | LCD_WR | LCD |
11 | sclk | SD card |
10 | mosi | SD card |
6 | miso | SD card |
26 | cs | SD card |
22 | WIFI_TX | WIFI(ESP32) |
25 | WIFI_RX | WIFI(ESP32) |
31 | KEY3 | KEY |
23 | KEY1 | KEY |
20 | KEY2 | KEY |
41 | CAMERA_SCL | CAMERA |
40 | CAMERA_SDA | CAMERA |
13 | MCLK | Audio CODEC |
21 | SCLK(I2S2CK) | Audio CODEC |
18 | LRCK(I2S2WS) | Audio CODEC |
34 | DSDIN(I2S2SDO) | Audio CODEC |
35 | ASDOUT(I2S2SDI) | Audio CODEC |
参考文献
(1)Tutorial
https://platformio.org/platforms/kendryte210
(2)Project
https://github.com/sipeed/platform-kendryte210
(3)Project
https://github.com/sipeed/platform-kendryte210
(4)ArduinoフレームワークでMaixAmigoを使う
https://qiita.com/fukuebiz/items/59915590a124a83061f1
(5)Sipeed MaixPyのリポジトリ
https://github.com/sipeed/MaixPy
(6)Sipeed Maixduinoのリポジトリ
https://github.com/sipeed/Maixduino
(7)K210仕様の日本語
https://iothonpo.com/kendryte-k210-datasheet-jp/
(8)k210回路図
https://canaan-creative.com/wp-content/uploads/2020/03/Kendryte_test_board_V0_2.pdf