FreeRTOSを動かしてみる

<details>
<summary>試行錯誤の履歴</summary>

思ったより長くなっているので目次的なもの
- [FreeRTOSを動かしてみる](https://qiita.com/t-yano-tryhard/items/f17f73041e293b6d0052)
- [FreeRTOSを動かしてみる(2)](https://qiita.com/t-yano-tryhard/items/f17f73041e293b6d0052)
- [FreeRTOSを動かしてみる(3)](https://qiita.com/t-yano-tryhard/items/ea3fb589ce85621ef947)
- FreeRTOSを動かしてみる(4) 作成中
- [FreeRTOSを動かしてみる(5)](https://qiita.com/t-yano-tryhard/items/8c1faccada30715c6d01)
- [FreeRTOSを動かしてみる(6)](https://qiita.com/t-yano-tryhard/items/e5541f1fc7490c17d77c)
- [FreeRTOSを動かしてみる(7)](https://qiita.com/t-yano-tryhard/items/f6992531359a914c13d9)
- FreeRTOSを動かしてみる(8)
- [FreeRTOSを動かしてみる(9)](https://qiita.com/t-yano-tryhard/items/fe3840011f5b45faa5dc)
- [FreeRTOSを動かしてみる(10)](https://qiita.com/t-yano-tryhard/items/fd31955287b81d97dc0c)
- [FreeRTOSを動かしてみる(11)](https://qiita.com/t-yano-tryhard/items/b0146c6bee658c7b1bd3)
- [FreeRTOSを動かしてみる(12)](https://qiita.com/t-yano-tryhard/items/f01ba4d701ade89297ec)
- [FreeRTOSを動かしてみる(13)](https://qiita.com/t-yano-tryhard/items/36130ed771d42f63991a)
- [FreeRTOSを動かしてみる(14)](https://qiita.com/t-yano-tryhard/items/105b6badc6ed57c5bb2f)
- [FreeRTOSを動かしてみる(15)](https://qiita.com/t-yano-tryhard/items/9f46d70489067c113c9f)
</details>

# 最新状況
Linuxからpingを打って応答が返ってきたサンプル
- [FreeRTOSを動かしてみる(11)](https://qiita.com/t-yano-tryhard/items/b0146c6bee658c7b1bd3)

# 前提条件
1. Windows PCが無い
2. 実機は無い
3. ネットワーク接続を行う


# FreeRTOSのダウンロード
[公式](https://www.freertos.org/a00104.html)から落としてくる
使用したのは[FreeRTOS 202212.01](https://github.com/FreeRTOS/FreeRTOS/releases/download/202212.01/FreeRTOSv202212.01.zip)

適当なディレクトリに解凍する。
```shell
mv ~/Downloads/FreeRTOSv202212.01.zip ./
unzip FreeRTOSv202212.01.zip
```

ついでにバージョン管理もやっておく
```
cd FreeRTOSv202212.01
git init
git add .
git commit -m "init"
```

# やることを決める
条件2より、必然的に[qemu](https://www.qemu.org/)を使用する他ない。
条件3は単体で動かしても用途が限られると思われるため。

一般的なTCP/IPを利用してLinuxとqemuのFreeRTOS間で通信出来ないか検討する。
マシンはとりあえずarmで良いかな、、、

# qemuのインストール
```
sudo apt install qemu-system-arm
```
# クロスコンパイラのインストール
環境が豊富そうな32bitで進める
```
sudo apt install gcc-arm-none-eabi
```

# マシンの選定
FreeRTOSの動作検証用デモが予め用意されている。
余計なのも含んでいるがおよそ200パターンくらいあるっぽい。
```
ls  FreeRTOS/Demo/ | wc
    211     211    5480
```

gccを使用するのでMakefile形式が扱いやすい。
のでそれを探す。
```
for a in `ls -F  FreeRTOS/Demo | grep "/" `; do cd FreeRTOS/Demo/$a; if [[ "" != ""`ls Makefile 2>/dev/null` ]] ; then echo $a; fi; cd ../../../; done
ARM7_AT91FR40008_GCC/
ARM7_LPC2106_GCC/
AVR_ATMega4809_MPLAB.X/
AVR_Dx_MPLAB.X/
CORTEX_LM3S102_GCC/
CORTEX_LM3S811_GCC/
CORTEX_M3_MPS2_QEMU_GCC/
CORTEX_MPU_M3_MPS2_QEMU_GCC/
Cygnal/
HCS12_GCC_banked/
PIC24_MPLAB/
Posix_GCC/
RISC-V-Qemu-virt_GCC/
RISC-V-spike-htif_GCC/
WIN32-MingW/
WizNET_DEMO_GCC_ARM7/
```
意外と少ない
```
for a in `ls -F  FreeRTOS/Demo | grep "/" `; do cd FreeRTOS/Demo/$a; if [[ "" != ""`ls Makefile 2>/dev/null` ]] ; then echo $a; fi; cd ../../../; done | wc
     16      16     304
```
## 動作確認
[この辺](https://qiita.com/imagou/items/cfbae702849602b80c3d)を試してみる

```
cd FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC
make
```
動いた
```
$ sudo qemu-system-arm -machine mps2-an385 -monitor null -semihosting --semihosting-config enable=on,target=native -kernel ./build/RTOSDemo.axf -serial stdio -nographic
blinking
blinking
```

# TCPを組み込んで見る

<details>
<summary>こんな感じ</summary>

```diff
git diff
diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
index bc7b74c4..a4bc7e67 100644
--- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
+++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
@@ -80,6 +80,12 @@ else
 endif
     CFLAGS += -fstrict-aliasing -Wstrict-aliasing -Wno-error=address-of-packed-member
 
+# TCP
+TCP_DIR := $(abspath ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/)
+INCLUDE_DIRS += -I$(TCP_DIR)/source/include
+INCLUDE_DIRS += -I$(TCP_DIR)/source/portable/Compiler/GCC
+SOURCE_FILES += $(wildcard $(TCP_DIR)/source/*.c)
+
 OBJ_FILES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o)
 
 CPPFLAGS += $(DEFINES)
```
</details>

なんか関数がないとか言って怒られる
```
FreeRTOS_ARP.c:(.text+0x654): undefined reference to `vReleaseNetworkBufferAndDescriptor'
/usr/lib/gcc/arm-none-eabi/9.2.1/../../../arm-none-eabi/bin/ld: build//home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/FreeRTOS_ARP.o: in function `xCheckLoopback':
FreeRTOS_ARP.c:(.text+0x9e0): undefined reference to `vReleaseNetworkBufferAndDescriptor'
collect2: error: ld returned 1 exit status
make: *** [Makefile:97: build/RTOSDemo.axf] Error 1
```

見づらいので整形

```
make clean
make 2>&1 | grep "undefined reference to"  | sed -e "s/^.*undefined reference to//g" | sort | uniq -c
      9  `pxGetNetworkBufferWithDescriptor'
      2  `ulApplicationGetNextSequenceNumber'
     19  `vReleaseNetworkBufferAndDescriptor'
      5  `xApplicationGetRandomNumber'
      1  `xBufferAllocFixedSize'
      1  `xNetworkBuffersInitialise'
      1  `xNetworkInterfaceInitialise'
      8  `xNetworkInterfaceOutput'
```


なんだろう
```
grep vReleaseNetworkBufferAndDescriptor ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ -nwrI --include="*.c" | grep void
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/test/cbmc/stubs/freertos_api.c:320:void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c:497:void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_2.c:339:void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/BufferManagement/BufferAllocation_1.c:378:void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
```

BufferAllocationとかいうのが要るらしい
よくわからんけど2にしてみた

```diff
git diff
diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
index bc7b74c4..dfb1f5f1 100644
--- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
+++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
@@ -80,6 +80,13 @@ else
 endif
     CFLAGS += -fstrict-aliasing -Wstrict-aliasing -Wno-error=address-of-packed-member
 
+# TCP
+TCP_DIR := $(abspath ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/)
+INCLUDE_DIRS += -I$(TCP_DIR)/source/include
+INCLUDE_DIRS += -I$(TCP_DIR)/source/portable/Compiler/GCC
+SOURCE_FILES += $(wildcard $(TCP_DIR)/source/*.c)
+SOURCE_FILES += $(TCP_DIR)/source/portable/BufferManagement/BufferAllocation_2.c
+
 OBJ_FILES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o)
 
 CPPFLAGS += $(DEFINES)

```

まだ残ってる
```
/source/FreeRTOS_UDP_IP.o: in function `vProcessGeneratedUDPPacket':
FreeRTOS_UDP_IP.c:(.text+0x44): undefined reference to `xNetworkInterfaceOutput'
/usr/lib/gcc/arm-none-eabi/9.2.1/../../../arm-none-eabi/bin/ld: build//home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/FreeRTOS_ARP.o: in function `FreeRTOS_OutputARPRequest':
FreeRTOS_ARP.c:(.text+0x52e): undefined reference to `xNetworkInterfaceOutput'
collect2: error: ld returned 1 exit status
make: *** [Makefile:98: build/RTOSDemo.axf] Error 1
```

```
grep "undefined reference to" build.log  | sed -e "s/^.*undefined reference to//g" | sort | uniq -c
      2  `ulApplicationGetNextSequenceNumber'
      5  `xApplicationGetRandomNumber'
      1  `xNetworkInterfaceInitialise'
      8  `xNetworkInterfaceOutput'
```

```
grep xNetworkInterfaceOutput ../../../FreeRTOS-Plus/ -wnrI --include="*.c" | grep BaseType_t
...
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/pic32mzef/NetworkInterface_wifi.c:105:BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c:60:BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/M487/NetworkInterface.c:141:BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/ksz8851snl/NetworkInterface.c:387:BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/mw300_rd/NetworkInterface.c:217:BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
...
```

NICドライバが必要らしい

サイズ的にboard_familyがテンプレっぽい
```bash
for a in `find ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/ -name NetworkInterface.c`; do ls $a; done | xargs ls -S
...
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/SH2A/NetworkInterface.c
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
```
ので入れてみる

```
/home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c: In function 'xNetworkInterfaceOutput':
/home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c:60:71: error: unused parameter 'pxNetworkBuffer' [-Werror=unused-parameter]
   60 | BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
/home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c:61:48: error: unused parameter 'xReleaseAfterSend' [-Werror=unused-parameter]
   61 |                                     BaseType_t xReleaseAfterSend )
      |                                     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c: In function 'vNetworkInterfaceAllocateRAMToBuffers':
/home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c:67:71: error: unused parameter 'pxNetworkBuffers' [-Werror=unused-parameter]
   67 | void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
      |                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make: *** [Makefile:113: build//home/voyager/workspace/freertos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.o] Error 1
```

めんどくさ

```diff
git diff ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
index fe44dccc..66f0e177 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
@@ -60,12 +60,15 @@ BaseType_t xNetworkInterfaceInitialise( void )
 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
                                     BaseType_t xReleaseAfterSend )
 {
+    (void)pxNetworkBuffer;
+    (void)xReleaseAfterSend;
     /* FIX ME. */
     return pdFALSE;
 }
 
 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
 {
+    (void)pxNetworkBuffers;
     /* FIX ME. */
 }
```

あとちょっと
```
grep "undefined reference to" build.log  | sed -e "s/^.*undefined reference to//g" | sort | uniq -c
      2  `ulApplicationGetNextSequenceNumber'
      5  `xApplicationGetRandomNumber'
```
NICドライバに実装するでよさそう



```diff
grep ulApplicationGetNextSequenceNumber ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ -nwrI
...
../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/ThirdParty/MSP432/NetworkMiddleware.c:178:uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
...
```

<details>
<summary>ここまでの差分</summary>

```diff
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
index fe44dccc..38608777 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/board_family/NetworkInterface.c
@@ -60,12 +60,15 @@ BaseType_t xNetworkInterfaceInitialise( void )
 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
                                     BaseType_t xReleaseAfterSend )
 {
+    (void)pxNetworkBuffer;
+    (void)xReleaseAfterSend;
     /* FIX ME. */
     return pdFALSE;
 }
 
 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
 {
+    (void)pxNetworkBuffers;
     /* FIX ME. */
 }
 
@@ -74,3 +77,21 @@ BaseType_t xGetPhyLinkStatus( void )
     /* FIX ME. */
     return pdFALSE;
 }
+
+BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber ) {
+    return *pulNumber + 1;
+}
+uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
+                                             uint16_t usSourcePort,
+                                             uint32_t ulDestinationAddress,
+                                             uint16_t usDestinationPort )
+{
+    (void)ulSourceAddress;
+    (void)usSourcePort;
+    (void)ulDestinationAddress;
+    (void)usDestinationPort;
+    uint32_t pulNumber = 0;
+
+    xApplicationGetRandomNumber( &pulNumber );
+    return pulNumber;
+}
diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/FreeRTOSIPConfig.h b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/FreeRTOSIPConfig.h
new file mode 100644
index 00000000..54c715f5
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/FreeRTOSIPConfig.h
@@ -0,0 +1,4 @@
+#ifndef FREERTOS_IP_CONFIG_H
+#define FREERTOS_IP_CONFIG_H
+#define ipconfigBYTE_ORDER  pdFREERTOS_LITTLE_ENDIAN
+#endif
diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
index bc7b74c4..b2bc2eef 100644
--- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
+++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile
@@ -64,6 +64,7 @@ else
     CFLAGS := -DmainCREATE_SIMPLE_BLINKY_DEMO_ONLY=1
 endif
 
+
 DEFINES :=  -DQEMU_SOC_MPS2 -DHEAP3
 
 LDFLAGS = -T ./scripts/mps2_m3.ld -specs=nano.specs --specs=rdimon.specs -lc -lrdimon
@@ -80,6 +81,17 @@ else
 endif
     CFLAGS += -fstrict-aliasing -Wstrict-aliasing -Wno-error=address-of-packed-member
 
+### TCP/IP
+TCP_DIR := $(abspath ../../../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/)
+INCLUDE_DIRS += -I$(TCP_DIR)/source/include
+INCLUDE_DIRS += -I$(TCP_DIR)/source/portable/Compiler/GCC
+SOURCE_FILES += $(wildcard $(TCP_DIR)/source/*.c)
+SOURCE_FILES += $(TCP_DIR)/source/portable/BufferManagement/BufferAllocation_2.c
+SOURCE_FILES += $(TCP_DIR)/source/portable/NetworkInterface/board_family/NetworkInterface.c
+
+### TCP/IP APP
+#SOURCE_FILES += app_tcp.c
+
 OBJ_FILES := $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o)
 
 CPPFLAGS += $(DEFINES)

 ```
 
</details>

動作確認
```
sudo qemu-system-arm -machine mps2-an385 -monitor null -semihosting --semihosting-config enable=on,target=native -kernel ./build/RTOSDemo.axf -serial stdio -nographic
blinking
blinking
```

一旦ここでcommit

```
git checkout -b work
git add FreeRTOSIPConfig.h
git add -u
git commit -m "add plus-tcp"
```

----
# 参考
https://qiita.com/imagou/items/cfbae702849602b80c3d