Zephyr + STM32F769 Discovery Kit + 4D Systems TouchLCD > UART > タッチディスプレイに文字を書いてACKを受信するまで

```txt:動作環境
ホストOS: Ubuntu 18.04 LTS
ボード: STM32F769 Discovery Kit (以下、STM32F769)
RTOS: Zephyr 2.1.0-rc1
touchLCD: gen4-uLCD-35DT 
  Workshop 4 IDE v4.5.0.17 (on Windows 10 Pro)
```

## 概要

- Zephyr + STM32F769でのUART送受信の練習
    - tty_init()
    - tty_write()
    - tty_read()
- gen4-uLCD-35DT（シリアルスレーブモード)
    - UART送信して文字を描く ('9')
    - UART受信する (ACK[0x06])

## 準備

### gen4-uLCD-35DTの準備

- gen4-uLCD-35DTはWorkshop 4 IDEにてシリアルスレーブモードにしておく
    - baud rate: 115200 bpsで設定
        - ZephyrではSTM32F769のUART_6は115200bpsがデフォルト設定
        
### Zephyrの準備

- UART_6
    - default: 115200 bps
- プロジェクトのprj.conf
    - 下記のようにしておく

```prj.conf
CONFIG_GPIO=y
CONFIG_SERIAL=y
# for tty_init()
CONFIG_CONSOLE_SUBSYS=y
CONFIG_CONSOLE_GETCHAR=y
```


### 配線

gen4-uLCD-35DTはFFCケーブルを介してgen4-IBに接続する。
そして、以下のように配線をする。

- STM32F769 D0(RX) <-> gen4-IB RX
- STM32F769 D1(TX) <-> gen4-IB TX
- STM32F769 GND <-> gen4-IB GND
- 5V電源(*1) PWR <-> gen4-IB +5V
- 5V電源(*1) GND <-> gen4-IB GND

*1) 5V出力(1A)のスイッチングACアダプタ

![IMG_1367.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/f3ed4f90-6b5e-1ab4-1883-aa1eb5b5474a.jpeg)


## 実装


```src/main.c
/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <sys/printk.h>
#include <tty.h>

#include <device.h>
#include <drivers/gpio.h>
// added 2019-11-23
#include <uart.h>
#include <console.h>
//#include <tty.h>
#include <string.h>

#define LED_PORT	DT_ALIAS_LED0_GPIOS_CONTROLLER
#define LED		DT_ALIAS_LED0_GPIOS_PIN

#define SLEEP_TIME_MSEC	1000

#define BARCODE_UART_PORT	"UART_6"
static struct device *uart_dev;
static struct tty_serial ard_serial; // Arduino connector (UART_6) = D0, D1 of CN13 on STM32F769I Discovery

int uart_init()
{
	struct uart_config uart_cfg;
	int ret;

	uart_dev = device_get_binding(BARCODE_UART_PORT);
	if (uart_dev == NULL) {
		printk("Failed to get %s\n", BARCODE_UART_PORT);
		return -1;
	}

	ret = uart_config_get(uart_dev, &uart_cfg);
	if (!ret) {
		printk("\n======== [%s] ========\n", BARCODE_UART_PORT);
		printk("[%s] uart_config.baudrate=%d\n", BARCODE_UART_PORT, uart_cfg.baudrate);
		printk("[%s] uart_config.parity=%d\n", BARCODE_UART_PORT, uart_cfg.parity);
		printk("[%s] uart_config.stop_bits=%d\n", BARCODE_UART_PORT, uart_cfg.stop_bits);
		printk("[%s] uart_config.data_bits=%d\n", BARCODE_UART_PORT, uart_cfg.data_bits);
		printk("[%s] uart_config.flow_ctrl=%d\n", BARCODE_UART_PORT, uart_cfg.flow_ctrl);
	} else {
		printk("uart_config_get() error\n");
		return -1;
	}

	tty_init(&ard_serial, uart_dev);

	return 0;
}

static unsigned char calc_checksum(unsigned char *ptr, int size)
{
    if (ptr == NULL) {
        return 0x00;
    }
    unsigned char code = 0;
    for(int idx=0; idx < size; idx++) {
        code ^= ptr[idx];
    }
    return code;
}

static void touchLCD_dispChar()
{
	// Target: 4D systesms (Serial slave mode) gen4-uLCD-35DT
	// Reference: DIABLO16 SERIAL COMMANDS (Rev. 2.1) 
	//   page 16 > 5.1.2. Put Character
	//
	unsigned char txbuf[20] = { 0 };
	unsigned char rxbuf[20] = { 0 };
	int pos = 0;
	int ret;

	txbuf[pos++] = 0xFF;
	txbuf[pos++] = 0xFE;
	txbuf[pos++] = 0x00;
	txbuf[pos++] = 0x39;
	ret = tty_write(&ard_serial, txbuf, pos);
	ret = tty_read(&ard_serial, rxbuf, 1);
	printk("rx:%02X\n", rxbuf[0]);
}

void main(void)
{
	u32_t cnt = 0;
	struct device *dev;

	printk("Hello World! %s\n", CONFIG_BOARD);

	dev = device_get_binding(LED_PORT);
	gpio_pin_configure(dev, LED, GPIO_DIR_OUT);

	uart_init();

	while (1) {
		// 1. display on touchLCD
		touchLCD_dispChar();
		// 2. LED Blink
		gpio_pin_write(dev, LED, cnt % 2);
		cnt++;
		// 3. wait
		k_sleep(SLEEP_TIME_MSEC);
	}
}
```

## 実行手順

３つのターミナルで実施した。
最初はgen4-uLCD-35DTの電源を抜いておく(起動直後のスプラッシュスクリーンを表示するため、プログラムが走らないwest debug時に電源を入れるため）。
プロジェクトのルートは`~/Zephyr_191116/zephyrproject/`としてセットアップしている。

- 1. STM32F769をUSB接続しておく
    - ST-LinkのUSB接続
- 2. ターミナル１：デバッグ用のシリアル接続をする
    - `sudo screen /dev/ttyACM0 115200`
- 3. ターミナル２：プログラムをビルド
    - `cd ~/Zephyr_191116/zephyrproject/`
    - `west build -p auto -b stm32f769i_disco zephyr/samples/basic/wrk_uart_191123`
- 4. ターミナル２：プログラム書き込み
    - `west flash`
- 5. ターミナル３：デバッグ実行開始
    - `cd ~/Zephyr_191116/zephyrproject/`
    - `west debug`
- 6. gen4-uLCD-35DTの電源を接続
    - 3秒待って、初期画面を表示 (4D Systems...の文字が表示される)
- 7. ターミナル３：デバッグ継続
    - 停止しながらデバッグ
        - `(gdb) break main.c:main`
        - `(gbd) c`
            - 下記まで実行される
                - `94		printk("Hello World! %s\n", CONFIG_BOARD);
`
        - `(gbd) n`
            - 繰り返してtouchLCD_dispChar()の実行を３回繰り返す

### 終了手順

- 1. ターミナル３：デバッグ接続 (west debug)
    - q[Enter]
    - y
- 2. ターミナル２：デバッグ用シリアル (screen)
    - ctrl-a, k
    - y

## 動作の様子

以下は、printk()デバッグ用のターミナルの出力。

```
***** Booting Zephyr OS build v2.1.0-rc1-141-g3cc5bda2fa10 *****
Hello World! stm32f769i_disco

======== [UART_6] ========
[UART_6] uart_config.baudrate=115200
[UART_6] uart_config.parity=0
[UART_6] uart_config.stop_bits=1
[UART_6] uart_config.data_bits=3
[UART_6] uart_config.flow_ctrl=0
rx:06
rx:06
rx:06
```

touchLCDには以下のように表示される。

![IMG_1369.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/943368d3-da19-068a-bf6c-4a21caad649c.jpeg)

コマンドを送信して、gen4-uLCD-35DTが受信成功したというACK[0x06]をSTM32F769にて受信できている。


### 参考

- [DIABLO16 SERIAL COMMANDS (Rev. 2.1) ](https://4dsystems.com.au/mwdownloads/download/link/id/12/)