LoginSignup
7
10

More than 1 year has passed since last update.

RISC Vマイコン K210の開発エコシステム

Last updated at Posted at 2021-05-21

 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搭載ボード

  1. Maixduino(Arduino互換ピンヘッダ,ESP32搭載,LCD付き,カメラ付き(秋月電子,Sigezone)
  2. MAix M1((Sigezone))
  3. Maix Bit Suit(LCD付き,カメラ付き(秋月電子))
  4. Maixcube((Switch Science))
  5. Sipeed Maix M1 Dock((Switch Science))
  6. M1 Dock(LCD付き,カメラ付き(秋月電子))
  7. M5StickV(カメラ内蔵,バッテリ,LCD内蔵,(M5Stack,Switch Science))
  8. M5UnitV(カメラ内蔵(M5Stack,Switch Science))
  9. Maix Amigo(カメラ内蔵×2,タッチパネル3.5インチLCD,520mAhリポ・バッテリ,スピーカ,マイク)

ボード1:Maixduino

1630.jpg

K210に加え,ESP32も載っているので無線通信機能が使える.国内の販売店でも手に入りやすい.ピンソケットはArduino Uno互換.

ボード7:M5StickV

 IMU,液晶,バッテリ, microSDカードスロット付き.ケースに入っているのでPOCやホビーに使いやすい.IMG_20220113_204207_1.jpg
IMG_20220113_204220_1.jpg

ボード8:M5UnitV

163678.jpg

 M5StickVからLCDとバッテリを無くした製品.その分厚みが薄くなっている.とてもコンパクト.

ボード9:Maix Amigo

1636.jpg
 当初$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/

フレームワーク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

  1. CMakeをインストール(Download cmake-3.14.1-win64-x64.msi)
  2. 最新版のツールチェインをインストール(Download kendryte-toolchain-win-i386-8.2.0-20190409.tar.xz)
  3. 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の関数が使えるので楽.
 ボードマネージャに登録されているボードであれば環境構築が非常に簡単である.登録がないボードは自分で登録するか,似ているボードの設定を利用しつつソースコード上で対処するしかない.
無題.png
※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で動作確認した際の設定は次の通り.

  1. board:sipeeed maixduino board(現状Maix Amigoは無い)
  2. 書込装置: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つ.

  1. Arduino(Maixduino)
  2. Kendryte Standalone SDK
  3. 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

  1. VS Codeをインストール
  2. PlatfomrIOをインストール
  3. K210ツールチェーンをインストール(「PIO Home」-「Platforms」からKeydryte k210をインストール)
  4. サンプルプロジェクトを読み込み(「PIO HOME」-「Project Example」からkendryte-standalone-sdk_helloを選ぶ)
  5. platformio.iniでboardはmaix-maix-goに設定(maix-amigo用のボード定義は無い)
  6. platformio.iniで正しいportに設定(k210とESP32で2ポートあるのでk210側のポートを指定)
  7. サンプルプロジェクトをビルド/書き込み

その2:Kendryte-standalone-sdk-demo

  1. GitHubからリポジトリ https://github.com/kendryte/kendryte-standalone-demo を取得.
  2. 実行したいデモを「やり方1」のsrcディレクトリにコピー
  3. MaixAmigoに合わせてI/Oなどの設定を変更
  4. ビルド/書き込み

サンプルプログラム

 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モジュールは次の機能を持っています.

  1. 割り込みの有効化/無効化
  2. 割り込みハンドラの設定
  3. 割り込みプライオリティの調整
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デバイス&チャネルの対応は下表の通り.TOGGLE1CHANNEL0に対応するところに注意

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以上の場合に使用できます.
 次の機能を持っています.

  1. 現在のデータと時間の取得
  2. 現在のデータと時間を設定
  3. 時間間隔の設定
  4. アラーム間隔の設定

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_PLL0SYSCTL_PLL2まで3つあります.

機能

  1. PLLとCPUクロックの設定
  2. それぞれのクロックの分割値を設定
  3. それぞれの現在のクロックを取得
  4. 各モジュールの有効化/無効化とリセット
  5. DMAリクエストソースを設定
  6. システム割り込みを有効化/無効化

 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.hDEFINE LICHEEDAN 1する).
 lcd.hで画面サイズが定義されているので,320×480にするとよいでしょう.

プログラム1

main.c
/* 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)の初期化シーケンス.

lcd.c
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

7
10
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
10