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

　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）
1. MAix M1（（Sigezone））
1. Maix Bit Suit（LCD付き，カメラ付き（秋月電子））
1. Maixcube((Switch Science))
1. Sipeed Maix M1 Dock((Switch Science))
1. M1 Dock（LCD付き，カメラ付き（秋月電子））
1. M5StickV（カメラ内蔵，バッテリ，LCD内蔵，（M5Stack，Switch Science））
1. M5UnitV（カメラ内蔵（M5Stack，Switch Science））
1. Maix Amigo（カメラ内蔵×2，タッチパネル3.5インチLCD，520mAhリポ・バッテリ，スピーカ，マイク）

## ボード1：Maixduino
![1630.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369631/3d6536d4-e2f6-5167-f219-ad2dead98e77.jpeg)

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

https://jp.seeedstudio.com/Sipeed-Maixduino-for-RISC-V-AI-IoT-p-4046.html
## ボード7：M5StickV
　IMU，液晶，バッテリ, microSDカードスロット付き．ケースに入っているのでPOCやホビーに使いやすい．![IMG_20220113_204207_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369631/a871c2da-1a51-0688-4e58-bc9921ff3a8c.jpeg)
![IMG_20220113_204220_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369631/25df118c-05c5-14ee-22a6-4427a2dc2aaf.jpeg)

https://www.instagram.com/p/B3JYKJihCj2/?hl=ja

## ボード8：M5UnitV
![163678.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369631/03b4548e-cf83-a36d-ecf9-c0cecbb6f5dc.jpeg)

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

## ボード9：Maix Amigo
![1636.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369631/7e63d996-3141-1efd-ac50-e4d00974ad0a.jpeg)
　当初＄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もある．

<b>Kendryte FreeRTOSプログラミングガイト</b>
`https://dl.sipeed.com/MAIX/SDK/Document/kendryte_freertos_programming_guide_en.pdf`
`https://github.com/kendryte/kendryte-freertos-sdk`

<b>K210 Standalone SDK プログラミングガイド</b>
`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）
1. 最新版のツールチェインをインストール（Download kendryte-toolchain-win-i386-8.2.0-20190409.tar.xz）
1. 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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369631/ae0d57ca-e02c-3f03-93f7-edd9e3c4c0f8.png)
<small>※MaixAmigo Boardは筆者が独自に登録したものだった気がする．．．</small>

<b>ライブラリのリポジトリ</b>
`https://github.com/sipeed/Maixduino/tree/master/libraries`
<b>ピン配置</b>
`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`
を追加する．

<b>・ターゲットボード用の設定（MaxiAmigoの場合）</b>
　現状ボードとして選べるものに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は無い）
1. 書込装置：k-flash


#### サンプル・スケッチ
##### サンプル1：Blinker
スケッチの抜粋を次に示す．LEDのGPIO番号を編集する．

```C++
#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のピンを正しく設定しておく）

```c++
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）
1. Kendryte Standalone SDK
1. Kendryte FreeRTOS SDK

<b>platformIO Kendryte FreeRTOS SDK</b>
`https://docs.platformio.org/en/latest/frameworks/kendryte-freertos-sdk.html#framework-kendryte-freertos-sdk`

<b>PlatformIOのK210のページ</b>
`https://docs.platformio.org/en/latest/platforms/kendryte210.html`

`https://maixduino.sipeed.com/en/`

# 実機での開発例
## MaixAmigo + VS Code + PlatformIO + Kendryte Standard SDK
<b>参考サイト</b>
`https://robopara.co.jp/setting_up_maixduino_on_platformio/`

### 環境構築
#### その1：Kendryte-standalone-sdk_hello

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

#### その2：Kendryte-standalone-sdk-demo

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

### サンプルプログラム
　kendryte-standalone-sdkを使ったサンプルプログラムを幾つか示します．

####サンプル：Lチカ

```c
#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チカ②

```c
#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）があります．どう使い分けるんだろう？

```c
#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

```c
#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入力

```c
#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. 割り込みの有効化/無効化
1. 割り込みハンドラの設定
1. 割り込みプライオリティの調整

##### 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より高位の関数があります．割り込みハンドラへ引数を渡したい場合などに便利です．

```c
#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デバイス＆チャネルの対応は下表の通り．<i>TOGGLE1</i>が<i>CHANNEL0</i>に対応するところに<b>注意</b>．

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：<i>pwm_set_frequency()</i>のシグネチャ

`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`を変更しています．

###### プログラム

```c
#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. 現在のデータと時間の取得
1. 現在のデータと時間を設定
1. 時間間隔の設定
1. アラーム間隔の設定

#### 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つあります．

#### 機能

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

　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

```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で実行できます．
　以下に変更部を示します．

#### プログラム

```c
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なのでありがたいですね．

#### プログラム

```c

```

### 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