[メモ] mynewt (IoT向けのRTOS環境):BLENanoでLチカ

## 概要
- [Apache Mynewt](https://mynewt.apache.org/) というIoTのためのRTOSをためしてみようかと。。
- が、<del>まだ動作してない</del> ... 低速でうごいてたっぽい。Clock周りの修正が必要??<br>とりあえず、アプリ側のウェイトを短くする.
- <del>(UbuntuでJlinkの環境をうごかすのが面倒...フラッシュに焼いて、デバッグ以降..は、そのうち。。)</del>

## 環境
- Ubuntu 16.04 64bit
- [BLENano](http://redbearlab.com/blenano/) nRF51822ベース

## 手順～ツール類の準備

### Linuxのツール [Set up toolchain for Linux](https://mynewt.apache.org/develop/os/get_started/native_tools/)

```bash
#1. Install gcc/libc that will produce 32-bit executables:
sudo apt-get install gcc-multilib libc6-i386
#2. Install gdb
sudo apt-get install gdb
```

### `newt`のインストール [Install newt tool on Linux](https://mynewt.apache.org/develop/newt/install/newt_linux/)

```bash
#1.  Install git, libcurl
sudo apt-get install git 
sudo apt-get install libcurl4-gnutls-dev 
#2. Install Go, the programming language
## ワーク
cd $HOME
mkdir -p dev/go 
cd dev/go
export GOPATH=`pwd`
## golangインストール.
sudo apt-get install golang 
#3. Create local repository
go get mynewt.apache.org/newt/...
#4. Build the Newt tool
cd $GOPATH/src/mynewt.apache.org/newt/newt
go install
ls "$GOPATH"/bin/
# PATHをはる
export PATH=$GOPATH/bin:$PATH
```

### ARMのクロスコンパイラのインストール [Install ARM cross arm tools for Linux](https://mynewt.apache.org/latest/os/get_started/cross_tools/)

```bash
# 16.04だといらない？？.
#sudo apt-get remove binutils-arm-none-eabi gcc-arm-none-eabi 
#sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded 
#
sudo apt-get update 
sudo apt-get install gcc-arm-none-eabi
sudo apt-get install gdb-arm-none-eabi
#
# Install OpenOCD
# sudo apt-get install openocd 
# 0.8.0を入れろと書いてあるが、ubuntu16.04だと、0.9.0がインストールされるので、あとで検討...
```

## 手順～最初のプロジェクト
[Create Your First Mynewt Project](https://mynewt.apache.org/latest/os/get_started/project_create/)

 ... そのままやればよい...Linux上で0 1 0 1とprintfされる。

## 手順～BLENanoで、プロジェクト作成・ビルド

- `sudo apt-get install srecord`<br>srecのツールをインストール. intel hexファイル作成に使用.


```bash
cd $HOME/dev
rm -rfv myproj
#
newt new myproj
cd myproj
#
#vi project.yml
# `project.yml`の`0-latest` => `0.0.0`に変更することで、developブランチから持ってくる.
sed -i 's/0-latest/0.0.0/' project.yml
#
newt install -v
# ファイルは、nrf51dkから持ってくる..そうしないとリンクエラーになる..
cd repos/apache-mynewt-core/hw/bsp/nrf51-blenano/
cp -v ../nrf51dk/*.ld ./.
cp -v ../nrf51dk/src/*.c ./src
cp -v ../nrf51dk/include/bsp/*.h ./include/bsp/
#
# vi include/bsp/bsp.h
## - include/bsp/bsp.h___21から19に変更。
## //#define LED_BLINK_PIN   (21)
## #define LED_BLINK_PIN   (19)
sed -i 's/(21)/(19)/' include/bsp/bsp.h
#
#
cd $HOME/dev/myproj
#
# ターゲット作成.
#Lチカ アプリ.
newt target create blink_blenano
newt target set blink_blenano app=apps/blinky
newt target set blink_blenano bsp=@apache-mynewt-core/hw/bsp/nrf51-blenano
newt target set blink_blenano build_profile=debug
# ブート.
newt target create blenano_boot
newt target set  blenano_boot app=@apache-mynewt-core/apps/boot
newt target set  blenano_boot bsp=@apache-mynewt-core/hw/bsp/nrf51-blenano
newt target set  blenano_boot build_profile=optimized
# 確認.
newt target show
# ビルド
newt build blenano_boot
newt build blink_blenano
# 署名?して、イメージ作成
newt create-image blink_blenano 1.0.0

#
# HEX イメージ作成.
srec_cat bin/blenano_boot/apps/boot/boot.elf.bin -binary  -offset=0x0 -o boot.hex -intel
srec_cat bin/blink_blenano/apps/blinky/blinky.img -binary  -offset=0x8000 -o img.hex -intel
srec_cat boot.hex -intel img.hex -intel -o img_OUT.HEX -intel --line-length=44
```

- 生成物
    - `bin/blenano_boot/apps/boot/boot.elf`  (?? 0x0000から配置 ??)
    - `bin/blink_blenano/apps/blinky/blinky.img` (?? 0x8000から配置 ??)
    - img_OUT.hex => mbedのドライブに放り込んで焼く。


- 5秒くらいごとにLチカする。

- アプリ側のウエイトをかえる...

    ```c:myproj/apps/blinky/src/main.cのblinky_task_handler()
...
        /* Wait one second */
        os_time_delay(200); //<<<=== 1000から 200くらいに。

        /* Toggle the LED */
        hal_gpio_toggle(g_led_pin);
...
```

```bash:再ビルドする
# ビルド
newt build blenano_boot
newt build blink_blenano
# 署名?して、イメージ作成
newt create-image blink_blenano 1.0.0
#
# HEX イメージ作成.
srec_cat bin/blenano_boot/apps/boot/boot.elf.bin -binary  -offset=0x0 -o boot.hex -intel
srec_cat bin/blink_blenano/apps/blinky/blinky.img -binary  -offset=0x8000 -o img.hex -intel
srec_cat boot.hex -intel img.hex -intel -o img_OUT.HEX -intel --line-length=44
```

=> ちょっとはやくなった。


## その他
1. BLE動かすのは、まだ先だな... (だれか...

1. <del>HEXを作って、mbedみたいにやいてうごかないか、、と試したが、できなかった。</del> <br>=> 5倍くらい遅いスピードでLチカしてたっぽい


2. `newt`のloglevel

    ```go:src/mynewt.apache.org/newt/newtmgr/cli/logs.go
...
    const (
            DEBUG    uint64 = 1
            INFO     uint64 = 2
            WARN     uint64 = 4
            ERROR    uint64 = 8
            CRITICAL uint64 = 10
            /* Upto 7 custom loglevels */
            PERUSER uint64 = 12
    )
    
    const (
            STREAM_LOG  uint64 = 0
            MEMORY_LOG  uint64 = 1
            STORAGE_LOG uint64 = 2
    )
    
    func LoglevelToString(ll uint64) string {
            s := ""
            switch ll {
            case DEBUG:
                    s = "DEBUG"
            case INFO:
                    s = "INFO"
            case WARN:
                    s = "WARN"
            case ERROR:
                    s = "ERROR"
            case CRITICAL:
                    s = "CRITICAL"
            case PERUSER:
                    s = "PERUSER"
            default:
                    s = "CUSTOM"
            }
            return s
    }
...
```


3. メモ

```c:myproj/repos/apache-mynewt-core/libs/os/src/os_task.cに実体
int 
os_task_init(struct os_task *t, char *name, os_task_func_t func, void *arg, 
        uint8_t prio, os_time_t sanity_itvl, os_stack_t *stack_bottom, 
        uint16_t stack_size)
```

```c:myproj/apps/blinky/src/main.c
...
/* Init all tasks */
volatile int tasks_initialized;
int init_tasks(void);

/* Task 1 */
#define BLINKY_TASK_PRIO (1)
#define BLINKY_STACK_SIZE    OS_STACK_ALIGN(256)

struct os_task blinky_task;
os_stack_t blinky_stack[BLINKY_STACK_SIZE];
static volatile int g_task1_loops;

/* For LED toggling */
int g_led_pin;

void
blinky_task_handler(void *arg)
{   
    struct os_task *t;
    
    g_led_pin = LED_BLINK_PIN;
    hal_gpio_init_out(g_led_pin, 1);
    
    while (1) {
        t = os_sched_get_current_task();
        assert(t->t_func == blinky_task_handler);

        ++g_task1_loops;

        /* Wait one second */
        os_time_delay(1000);

        /* Toggle the LED */
        hal_gpio_toggle(g_led_pin);
    }
}

/**
 * init_tasks
 *
 * Called by main.c after os_init(). This function performs initializations
 * that are required before tasks are running.
 *
 * @return int 0 success; error otherwise.
 */
int
init_tasks(void)
{
    os_task_init(&blinky_task, "blinky", blinky_task_handler, NULL,
            BLINKY_TASK_PRIO, OS_WAIT_FOREVER, blinky_stack, BLINKY_STACK_SIZE);

    tasks_initialized = 1;

    return 0;
}

/**
 * main
 *
 * The main function for the project. This function initializes the os, calls
 * init_tasks to initialize tasks (and possibly other objects), then starts the
 * OS. We should not return from os start.
 *
 * @return int NOTE: this function should never return!
 */
int
main(int argc, char **argv)
{
    int rc;

#ifdef ARCH_sim
    mcu_sim_parse_args(argc, argv);
#endif

    os_init();

    rc = init_tasks();
    os_start();

    /* os start should never return. If it does, this should be an error */
    assert(0);

    return rc;
}
```

PC上での`hal_gpio_toggle`のしくみ ... `printf`してる

```c:myproj/repos/apache-mynewt-core/hw/mcu/native/src/hal_gpio.c
...
void hal_gpio_write(int pin, int val)
{
    if (pin >= HAL_GPIO_NUM_PINS) {
        return;
    }
    if (hal_gpio[pin].dir != OUTPUT) {
        return;
    }
    hal_gpio[pin].val = (val != 0);
    printf("hal_gpio set pin %2d to %1d\r", pin, hal_gpio[pin].val);
    fflush(stdout);
}

int
hal_gpio_read(int pin)
{
    if (pin >= HAL_GPIO_NUM_PINS) {
        return -1;
    }
    return hal_gpio[pin].val;
}

int
hal_gpio_toggle(int pin)
{
    int pin_state = (hal_gpio_read(pin) != 1);
    hal_gpio_write(pin, pin_state);
    return pin_state;
}
```