【番外編】ポートFを使えるようにする【SPIKE-RTでロボコンに出よう!!】

# 目次

https://qiita.com/koushiro/items/482162807339f4d18516

| 章 | タイトル | 内容 |
| :-: | :-: | :-: |
| 1 | [はじめに](#1-はじめに) | 本記事について説明 |
| 2 | [ファイルの編集](#2-ファイルの編集) | ポートF解放のためのファイル編集 |
| 3 | [デバッグ](#3-デバッグ) | ポートFが使えるか確認 |
| 4 | [おわりに](#4-おわりに) | 今回のまとめと謝辞 |

# 1. はじめに

この記事は、2023年12月より執筆中のシリーズ【SPIKE-RTでロボコンに出よう!!】の番外編記事です。

本シリーズの[#4 モータの使い方](https://qiita.com/koushiro/items/0471376a9feb9b53b178)にて、以下のような注意書きを記しました。

:::note alert
2023年12月5日現在、ポートFはデバッグ用に使用されているため、モータやセンサ用には使えません。
よって、`pup_motor_get_device`でポートFは指定しないでください。
:::

この通り、SPIKE-RTはデフォルトでは、ハブブロックのFポートが「デバッグメッセージ出力用ポート」に設定されており、通常のモータやセンサを動かす用のポートとして使うことが出来ません。

この制限を解除する方法が判明しましたので、本稿に記したいと思います。

## ⚠ 注意点

本稿で紹介する方法は、公式によるものではありません。
紹介にあたり、ある程度デバッグは行っていますが、本来の動作に影響を及ぼす可能性があることをご承知おき下さい。
又、本稿に紹介する作業を行ったことにより、何らかの不具合が発生したとしても、当方は責任を負いかねますのでご了承ください。

# 2. ファイルの編集

ポートFを使えるようにするためには、以下の5ファイルを編集します。

- `/spike-rt/external/libpybricks/lib/pbio/include/pbdrv/config.h`
- `/spike-rt/external/libpybricks/lib/pbio/platform/prime_hub_spike-rt/pbdrvconfig.h`
- `/spike-rt/external/libpybricks/lib/pbio/platform/prime_hub_spike-rt/pbioconfig.h`
- `/spike-rt/asp3/target/primehub_gcc/primehub.h`
- `/spike-rt/drivers/pybricks.cfg`

以下に編集前、編集後のコードを比較表示します。

```diff_c
- (行番号) 編集前
+ (行番号) 編集後
```
上記のように、赤のマーキング部分を、緑のマーキング部分のように変更して下さい。

## /spike-rt/external/libpybricks/lib/pbio/include/pbdrv/config.h

```diff_c:config.h
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors

#ifndef _PBDRV_CONFIG_H_
#define _PBDRV_CONFIG_H_

// This file is defined per-platform. It should override the config values below as needed.
#include "pbdrvconfig.h"

// set to (1) if there is a port labeled "A" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_A
- 12 #define PBDRV_CONFIG_HAS_PORT_A (0)
+ 12 #define PBDRV_CONFIG_HAS_PORT_A (1)
#endif

// set to (1) if there is a port labeled "B" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_B
- 17 #define PBDRV_CONFIG_HAS_PORT_B (0)
+ 17 #define PBDRV_CONFIG_HAS_PORT_B (1)
#endif

// set to (1) if there is a port labeled "C" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_C
- 22 #define PBDRV_CONFIG_HAS_PORT_C (0)
+ 22 #define PBDRV_CONFIG_HAS_PORT_C (1)
#endif

// set to (1) if there is a port labeled "D" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_D
- 27 #define PBDRV_CONFIG_HAS_PORT_D (0)
+ 27 #define PBDRV_CONFIG_HAS_PORT_D (1)
#endif

// set to (1) if there is a port labeled "E" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_E
- 32 #define PBDRV_CONFIG_HAS_PORT_E (0)
+ 32 #define PBDRV_CONFIG_HAS_PORT_E (1)
#endif

// set to (1) if there is a port labeled "F" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_F
- 37 #define PBDRV_CONFIG_HAS_PORT_F (0)
+ 37 #define PBDRV_CONFIG_HAS_PORT_F (1)
#endif

// set to (1) if there is a port labeled "1" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_1
#define PBDRV_CONFIG_HAS_PORT_1 (0)
#endif

// set to (1) if there is a port labeled "2" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_2
#define PBDRV_CONFIG_HAS_PORT_2 (0)
#endif

// set to (1) if there is a port labeled "3" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_3
#define PBDRV_CONFIG_HAS_PORT_3 (0)
#endif

// set to (1) if there is a port labeled "4" on the programmable brick
#ifndef PBDRV_CONFIG_HAS_PORT_4
#define PBDRV_CONFIG_HAS_PORT_4 (0)
#endif

// the number of built-in motor controllers in the programmable brick
#ifndef PBDRV_CONFIG_NUM_MOTOR_CONTROLLER
#define PBDRV_CONFIG_NUM_MOTOR_CONTROLLER (0)
#elif PBDRV_CONFIG_NUM_MOTOR_CONTROLLER != 0

// the pbio_port_id_t enum value of the first motor port
#ifndef PBDRV_CONFIG_FIRST_MOTOR_PORT
#error PBDRV_CONFIG_NUM_MOTOR_CONTROLLER requires that PBDRV_CONFIG_FIRST_MOTOR_PORT is defined
#endif

// the pbio_port_id_t enum value of the last motor port
#ifndef PBDRV_CONFIG_LAST_MOTOR_PORT
#error PBDRV_CONFIG_NUM_MOTOR_CONTROLLER requires that PBDRV_CONFIG_LAST_MOTOR_PORT is defined
#endif
#endif

#endif // _PBDRV_CONFIG_H_
```

## /spike-rt/external/libpybricks/lib/pbio/platform/prime_hub_spike-rt/pbdrvconfig.h

```diff_c:pbdrvconfig.h

// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2020 The Pybricks Authors
// Copyright (c) 2022 Embedded and Real-Time Systems Laboratory,
//            Graduate School of Information Science, Nagoya Univ., JAPAN

// TODO:
//#include <pbio/config.h>

#define PBDRV_ON_ASP3                               (1)

#define PBDRV_CONFIG_ADC                            (1)
#define PBDRV_CONFIG_ADC_STM32_HAL                  (1)
#define PBDRV_CONFIG_ADC_STM32_HAL_ADC_INSTANCE     ADC1
#define PBDRV_CONFIG_ADC_STM32_HAL_ADC_NUM_CHANNELS 6
#define PBDRV_CONFIG_ADC_STM32_HAL_DMA_INSTANCE     DMA2_Stream0
#define PBDRV_CONFIG_ADC_STM32_HAL_DMA_CHANNEL      DMA_CHANNEL_0
#define PBDRV_CONFIG_ADC_STM32_HAL_DMA_IRQ          DMA2_Stream0_IRQn
#define PBDRV_CONFIG_ADC_STM32_HAL_TIMER_INSTANCE   TIM2
#define PBDRV_CONFIG_ADC_STM32_HAL_TIMER_TRIGGER    ADC_EXTERNALTRIGCONV_T2_TRGO

#define PBDRV_CONFIG_BATTERY                        (1)
#define PBDRV_CONFIG_BATTERY_ADC                    (1)
#define PBDRV_CONFIG_BATTERY_ADC_VOLTAGE_CH         1
#define PBDRV_CONFIG_BATTERY_ADC_VOLTAGE_RAW_MAX    4096
#define PBDRV_CONFIG_BATTERY_ADC_VOLTAGE_SCALED_MAX 9900
#define PBDRV_CONFIG_BATTERY_ADC_CURRENT_CORRECTION 3
#define PBDRV_CONFIG_BATTERY_ADC_CURRENT_CH         0
#define PBDRV_CONFIG_BATTERY_ADC_CURRENT_RAW_OFFSET 0
#define PBDRV_CONFIG_BATTERY_ADC_CURRENT_RAW_MAX    4096
#define PBDRV_CONFIG_BATTERY_ADC_CURRENT_SCALED_MAX 7300
#define PBDRV_CONFIG_BATTERY_ADC_TYPE               (2)
#define PBDRV_CONFIG_BATTERY_ADC_TEMPERATURE        (1)
#define PBDRV_CONFIG_BATTERY_ADC_TEMPERATURE_CH     2

#define PBDRV_CONFIG_BLUETOOTH                      (1)
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK              (1)
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_CONTROL_GPIO (1)
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_STM32_UART   (1)
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND     LWP3_HUB_KIND_TECHNIC_LARGE
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR 0x08007d80

#define PBDRV_CONFIG_BLOCK_DEVICE                   (1)
#define PBDRV_CONFIG_BLOCK_DEVICE_W25QXX_STM32      (1)
#define PBDRV_CONFIG_BLOCK_DEVICE_W25QXX_STM32_W25Q256 (1)
// Carve out 256K from the reserved 1M area at the start of the flash.
// This avoids touching the file system, the area read by the LEGO
// bootloader and the area used by upstream MicroPython. Currently, this
// just needs to be big enough to back up the user program on shutdown.
#define PBDRV_CONFIG_BLOCK_DEVICE_W25QXX_STM32_START_ADDRESS (512 * 1024)
#define PBDRV_CONFIG_BLOCK_DEVICE_W25QXX_STM32_SIZE (256 * 1024)

#define PBDRV_CONFIG_BUTTON                         (1)
#define PBDRV_CONFIG_BUTTON_RESISTOR_LADDER         (1)

#define PBDRV_CONFIG_CHARGER                        (1)
#define PBDRV_CONFIG_CHARGER_MP2639A                (1)
#define PBDRV_CONFIG_CHARGER_MP2639A_MODE_PWM       (1)
#define PBDRV_CONFIG_CHARGER_MP2639A_CHG_RESISTOR_LADDER (1)
#define PBDRV_CONFIG_CHARGER_MP2639A_ISET_PWM       (1)

#define PBDRV_CONFIG_CLOCK                          (1)
#define PBDRV_CONFIG_CLOCK_ASP3                    (1)
// #define PBDRV_CONFIG_CLOCK_STM32                    (1)

#define PBDRV_CONFIG_COUNTER                        (1)
#define PBDRV_CONFIG_COUNTER_NUM_DEV                (6)
#define PBDRV_CONFIG_COUNTER_LPF2                   (1)
- 68 #define PBDRV_CONFIG_COUNTER_LPF2_NUM_DEV           (5) // TODO
+ 68 #define PBDRV_CONFIG_COUNTER_LPF2_NUM_DEV           (6) // TODO

#define PBDRV_CONFIG_GPIO                           (1)
#define PBDRV_CONFIG_GPIO_STM32F4                   (1)

#define PBDRV_CONFIG_IMU                            (1)
#define PBDRV_CONFIG_IMU_LSM6S3TR_C_STM32           (1)
#define PBDRV_CONFIG_IMU_LSM6S3TR_C_STM32_SIGN_X    (-1)
#define PBDRV_CONFIG_IMU_LSM6S3TR_C_STM32_SIGN_Y    (1)
#define PBDRV_CONFIG_IMU_LSM6S3TR_C_STM32_SIGN_Z    (-1)

#define PBDRV_CONFIG_IOPORT                         (1)
#define PBDRV_CONFIG_IOPORT_LPF2                    (1)
- 81 #define PBDRV_CONFIG_IOPORT_LPF2_NUM_PORTS          (5) //TODO
+ 81 #define PBDRV_CONFIG_IOPORT_LPF2_NUM_PORTS          (6) //TODO
#define PBDRV_CONFIG_IOPORT_LPF2_FIRST_PORT         PBIO_PORT_ID_A
- 83 #define PBDRV_CONFIG_IOPORT_LPF2_LAST_PORT          PBIO_PORT_ID_E
+ 83 #define PBDRV_CONFIG_IOPORT_LPF2_LAST_PORT          PBIO_PORT_ID_F

#define PBDRV_CONFIG_LED                            (1)
#define PBDRV_CONFIG_LED_NUM_DEV                    (5)
#define PBDRV_CONFIG_LED_DUAL                       (1)
#define PBDRV_CONFIG_LED_DUAL_NUM_DEV               (1)
#define PBDRV_CONFIG_LED_PWM                        (1)
#define PBDRV_CONFIG_LED_PWM_NUM_DEV                (4)

#define PBDRV_CONFIG_LED_ARRAY                      (1)
#define PBDRV_CONFIG_LED_ARRAY_NUM_DEV              (1)
#define PBDRV_CONFIG_LED_ARRAY_PWM                  (1)
#define PBDRV_CONFIG_LED_ARRAY_PWM_NUM_DEV          (1)

#define PBDRV_CONFIG_MOTOR_DRIVER                   (1)
#define PBDRV_CONFIG_MOTOR_DRIVER_NUM_DEV           (6)
#define PBDRV_CONFIG_MOTOR_DRIVER_HBRIDGE_PWM       (1)

#define PBDRV_CONFIG_PWM                            (1)
#define PBDRV_CONFIG_PWM_NUM_DEV                    (7)
#define PBDRV_CONFIG_PWM_STM32_TIM                  (1)
#define PBDRV_CONFIG_PWM_STM32_TIM_NUM_DEV          (6)
#define PBDRV_CONFIG_PWM_STM32_TIM_EXTRA_FLAGS      (1)
#define PBDRV_CONFIG_PWM_TLC5955_STM32              (1)
#define PBDRV_CONFIG_PWM_TLC5955_STM32_NUM_DEV      (1)

#define PBDRV_CONFIG_RESET                          (1)
#define PBDRV_CONFIG_RESET_STM32                    (1)
#define PBDRV_CONFIG_RESET_STM32_HAS_BLE_BOOTLOADER (0)

#define PBDRV_CONFIG_RESISTOR_LADDER                (1)
#define PBDRV_CONFIG_RESISTOR_LADDER_NUM_DEV        (2)

#define PBDRV_CONFIG_SOUND                          (1)
#define PBDRV_CONFIG_SOUND_STM32_HAL_DAC            (1)

#define PBDRV_CONFIG_UART                           (1)
#define PBDRV_CONFIG_UART_STM32F4_LL_IRQ            (1)
- 121 #define PBDRV_CONFIG_UART_STM32F4_LL_IRQ_NUM_UART   (5)
+ 121 #define PBDRV_CONFIG_UART_STM32F4_LL_IRQ_NUM_UART   (6)

#define PBDRV_CONFIG_USB                            (1)
#define PBDRV_CONFIG_USB_STM32F4                    (1)
#define PBDRV_CONFIG_USB_STM32F4_CDC                (1) // TODO

#define PBDRV_CONFIG_WATCHDOG                       (1)
#define PBDRV_CONFIG_WATCHDOG_STM32                 (1)

#define PBDRV_CONFIG_HAS_PORT_A (1)
#define PBDRV_CONFIG_HAS_PORT_B (1)
#define PBDRV_CONFIG_HAS_PORT_C (1)
#define PBDRV_CONFIG_HAS_PORT_D (1)
#define PBDRV_CONFIG_HAS_PORT_E (1)
//#define PBDRV_CONFIG_HAS_PORT_F (!PBIO_CONFIG_USE_PORT_F_AS_ASP3_DEBUG_UART)
- 136 #define PBDRV_CONFIG_HAS_PORT_F (0) // TODO:
+ 136 #define PBDRV_CONFIG_HAS_PORT_F (1) // TODO:

#define PBDRV_CONFIG_FIRST_MOTOR_PORT       PBIO_PORT_ID_A
#if !PBDRV_CONFIG_HAS_PORT_F
#define PBDRV_CONFIG_LAST_MOTOR_PORT        PBIO_PORT_ID_E
#else
#define PBDRV_CONFIG_LAST_MOTOR_PORT        PBIO_PORT_ID_F
#endif
- 144 #define PBDRV_CONFIG_NUM_MOTOR_CONTROLLER   (5)
+ 144 #define PBDRV_CONFIG_NUM_MOTOR_CONTROLLER   (6)

#define PBDRV_CONFIG_SYS_CLOCK_RATE 96000000

```

## /spike-rt/external/libpybricks/lib/pbio/platform/prime_hub_spike-rt/pbioconfig.h

```diff_c:pbioconfig.h

// SPDX-License-Identifier: MIT
// Copyright (c) 2019-2022 The Pybricks Authors
// Copyright (c) 2022 Embedded and Real-Time Systems Laboratory,
//            Graduate School of Information Science, Nagoya Univ., JAPAN

#define PBIO_CONFIG_BATTERY                 (1)
#define PBIO_CONFIG_DCMOTOR                 (1)
#define PBIO_CONFIG_DRIVEBASE_SPIKE         (1)
#define PBIO_CONFIG_LIGHT                   (1)
#define PBIO_CONFIG_LOGGER                  (1)
#define PBIO_CONFIG_LIGHT_MATRIX            (1)
#define PBIO_CONFIG_SERVO                   (1)
#define PBIO_CONFIG_SERVO_EV3_NXT           (0)
#define PBIO_CONFIG_SERVO_PUP               (1)
#define PBIO_CONFIG_SERVO_PUP_MOVE_HUB      (0)
#define PBIO_CONFIG_TACHO                   (1)

//#define SPIKE_RT_CONFIG_USE_PORT_F_AS_USER_UART   (1)
//#define SPIKE_RT_CONFIG_USE_PORT_E_AS_USER_UART   (0)

- 21 #define PBIO_CONFIG_USE_PORT_F_AS_ASP3_DEBUG_UART  (1)
+ 21 #define PBIO_CONFIG_USE_PORT_F_AS_ASP3_DEBUG_UART  (0)

#define PBIO_CONFIG_UARTDEV                 (1)
#if PBIO_CONFIG_USE_PORT_F_AS_ASP3_DEBUG_UART
#define PBIO_CONFIG_UARTDEV_NUM_DEV         (5)
#else
#define PBIO_CONFIG_UARTDEV_NUM_DEV         (6)
#endif
#define PBIO_CONFIG_UARTDEV_FIRST_PORT      PBIO_PORT_ID_A

#define PBIO_CONFIG_ENABLE_SYS              (1)

```

## /spike-rt/asp3/target/primehub_gcc/primehub.h

```diff_c:primehub.h
/*
 *  TOPPERS Software
 *      Toyohashi Open Platform for Embedded Real-Time Systems
 * 
 *  Copyright (C) 2006-2016 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN
 * 
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 * 
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 * 
 *  $Id: nucleo_f401re.h 648 2016-02-20 00:50:56Z ertl-honda $
 */

/*
 *		NUCLEO F401RE サポートモジュール
 */

#ifndef TOPPERS_PRIMEHUB_H
#define TOPPERS_PRIMEHUB_H

/*
 *  コアのクロック周波数（96MHz）
 */
#define CPU_CLOCK_HZ	96000000

/*
 *  割込み数
 */
#define TMAX_INTNO (101 + 16)

/*
 *  微少時間待ちのための定義（本来はSILのターゲット依存部）
 */
#define SIL_DLY_TIM1    162
#define SIL_DLY_TIM2    100

#ifndef TOPPERS_MACRO_ONLY
/*
 *  tecsgen実行時にstm32f4xx_nucleo.hを読み込むとtecsgenがエラーとなるため
 *  tecsgen実行時に必要な定義はこのファイルで行う
 */
#ifndef TECSGEN
#include "stm32f4xx_nucleo.h"
#else /* !TECSGEN */
- 71 #define UART9_BASE  0x40011800U
+ 71 #define USART6_BASE  0x40011400U
- 72 #define UART9_IRQn  88
+ 72 #define USART6_IRQn  71
#endif /* TECSGEN */
#endif /* TOPPERS_MACRO_ONLY */

/*
 *  USART関連の定義
 */
- 79 #define USART_INTNO (UART9_IRQn + 16)
+ 79 #define USART_INTNO (USART6_IRQn + 16)
- 80 #define USART_NAME  UART9
+ 80 #define USART_NAME  USART6
- 81 #define USART_BASE  UART9_BASE 
+ 81 #define USART_BASE  USART6_BASE

/*
 *  ボーレート
 */
#define BPS_SETTING  (115200)

#ifndef TOPPERS_MACRO_ONLY
#ifndef TECSGEN
/*
 *  UsartのクロックとIOの初期化
 */
Inline void
usart_low_init(void) {
	GPIO_InitTypeDef  GPIO_InitStruct;

	/* Enable Clock */
	__HAL_RCC_GPIOD_CLK_ENABLE();
- 99 	 __HAL_RCC_UART9_CLK_ENABLE();
+ 99 	 __HAL_RCC_USART6_CLK_ENABLE();
  
	/* UART TX GPIO pin configuration  */
- 102 	 GPIO_InitStruct.Pin       = GPIO_PIN_15;    
+ 102	 GPIO_InitStruct.Pin       = GPIO_PIN_14;
	GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull      = GPIO_PULLUP;
	GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
- 106    GPIO_InitStruct.Alternate = GPIO_AF11_UART9;
+ 106 	 GPIO_InitStruct.Alternate = GPIO_AF8_USART6;

	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
	/* UART RX GPIO pin configuration  */
- 111    GPIO_InitStruct.Pin = GPIO_PIN_14;
+ 111	 GPIO_InitStruct.Pin = GPIO_PIN_9;
- 112    GPIO_InitStruct.Alternate = GPIO_AF11_UART9;
+ 112	 GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
    
	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
#endif /* TECSGEN */
#endif /* TOPPERS_MACRO_ONLY */

#endif /* TOPPERS_PRIMEHUB_H */

```

## /spike-rt-f/drivers/pybricks.cfg

```diff_c:primehub.h
/*
 * SPDX-License-Identifier: MIT
 *
 * TOPPERS System Configurations for Pybricks Task.
 *
 * Copyright (c) 2022 Embedded and Real-Time Systems Laboratory,
 *            Graduate School of Information Science, Nagoya Univ., JAPAN
 */

#include "pybricks.h"

#ifndef TOPPERS_USE_QEMU
CRE_TSK(PYBRICKS_TASK, { TA_ACT, 0, pb_main_task, PYBRICKS_PRIORITY, PYBRICKS_STACK_SIZE, NULL });
#else
CRE_TSK(PYBRICKS_TASK, { 0, 0, pb_main_task, PYBRICKS_PRIORITY, PYBRICKS_STACK_SIZE, NULL });
#endif
CRE_CYC(PB_CYCHDR, { TA_STA, { TNFY_HANDLER, 0, pbdrv_timer_handler }, 1000, 0 });

CFG_INT(INTNO_DMA1_STREAM3, { INTATR_DMA1_STREAM3, INTPRI_DMA1_STREAM3 });
DEF_INH(INHNO_DMA1_STREAM3, { TA_NULL, DMA1_Stream3_IRQHandler });

CFG_INT(INTNO_DMA1_STREAM4, { INTATR_DMA1_STREAM4, INTPRI_DMA1_STREAM4 });
DEF_INH(INHNO_DMA1_STREAM4, { TA_NULL, DMA1_Stream4_IRQHandler });

CFG_INT(INTNO_DMA1_STREAM5, { INTATR_DMA1_STREAM5, INTPRI_DMA1_STREAM5 });
DEF_INH(INHNO_DMA1_STREAM5, { TA_NULL, DMA1_Stream5_IRQHandler });

CFG_INT(INTNO_DMA1_STREAM6, { INTATR_DMA1_STREAM6, INTPRI_DMA1_STREAM6 });
DEF_INH(INHNO_DMA1_STREAM6, { TA_NULL, DMA1_Stream6_IRQHandler });

CFG_INT(INTNO_DMA1_STREAM7, { INTATR_DMA1_STREAM7, INTPRI_DMA1_STREAM7 });
DEF_INH(INHNO_DMA1_STREAM7, { TA_NULL, DMA1_Stream7_IRQHandler });

CFG_INT(INTNO_DMA2_STREAM0, { INTATR_DMA2_STREAM0, INTPRI_DMA2_STREAM0 });
DEF_INH(INHNO_DMA2_STREAM0, { TA_NULL, DMA2_Stream0_IRQHandler });

CFG_INT(INTNO_DMA2_STREAM2, { INTATR_DMA2_STREAM2, INTPRI_DMA2_STREAM2 });
DEF_INH(INHNO_DMA2_STREAM2, { TA_NULL, DMA2_Stream2_IRQHandler });

CFG_INT(INTNO_DMA2_STREAM3, { INTATR_DMA2_STREAM3, INTPRI_DMA2_STREAM3 });
DEF_INH(INHNO_DMA2_STREAM3, { TA_NULL, DMA2_Stream3_IRQHandler });

CFG_INT(INTNO_USART2, { INTATR_USART2, INTPRI_USART2 });
DEF_INH(INHNO_USART2, { TA_NULL, USART2_IRQHandler });

CFG_INT(INTNO_UART4, { INTATR_UART4, INTPRI_UART4 });
DEF_INH(INHNO_UART4, { TA_NULL, UART4_IRQHandler });

CFG_INT(INTNO_UART5, { INTATR_UART5, INTPRI_UART5 });
DEF_INH(INHNO_UART5, { TA_NULL, UART5_IRQHandler });

CFG_INT(INTNO_UART7, { INTATR_UART7, INTPRI_UART7 });
DEF_INH(INHNO_UART7, { TA_NULL, UART7_IRQHandler });

CFG_INT(INTNO_UART8, { INTATR_UART8, INTPRI_UART8 });
DEF_INH(INHNO_UART8, { TA_NULL, UART8_IRQHandler });

// TODO: 
//#if !(SPIKE_RT_CONFIG_USE_PORT_F_AS_USER_UART)
- 60 //CFG_INT(INTNO_UART9, { TA_NULL|INTATR_UART9, INTPRI_UART9 });
+ 60 CFG_INT(INTNO_UART9, { INTATR_UART9, INTPRI_UART9 });
- 61 //DEF_INH(INHNO_UART9, { TA_NULL, UART9_IRQHandler });
+ 61 DEF_INH(INHNO_UART9, { TA_NULL, UART9_IRQHandler });
//#endif

// TODO: 
//#if !(SPIKE_RT_CONFIG_USE_PORT_E_AS_USER_UART)
CFG_INT(INTNO_UART10, { INTATR_UART10, INTPRI_UART10 });
DEF_INH(INHNO_UART10, { TA_NULL, UART10_IRQHandler });
//#endif

CFG_INT(INTNO_SPI1, { INTATR_SPI1, INTPRI_SPI1 });
DEF_INH(INHNO_SPI1, { TA_NULL, SPI1_IRQHandler });

CFG_INT(INTNO_SPI2, { INTATR_SPI2, INTPRI_SPI2 });
DEF_INH(INHNO_SPI2, { TA_NULL, SPI2_IRQHandler });

CFG_INT(INTNO_OTG_FS, { INTATR_OTG_FS, INTPRI_OTG_FS });
DEF_INH(INHNO_OTG_FS, { TA_NULL, OTG_FS_IRQHandler });

CFG_INT(INTNO_I2C2_ER, { INTATR_I2C2_ER, INTPRI_I2C2_ER });
DEF_INH(INHNO_I2C2_ER, { TA_NULL, I2C2_ER_IRQHandler });

CFG_INT(INTNO_I2C2_EV, { INTATR_I2C2_EV, INTPRI_I2C2_EV });
DEF_INH(INHNO_I2C2_EV, { TA_NULL, I2C2_EV_IRQHandler });

CFG_INT(INTNO_EXTI9_5, { INTATR_EXTI9_5, INTPRI_EXTI9_5 });
DEF_INH(INHNO_EXTI9_5, { TA_NULL, EXTI9_5_IRQHandler });

```

以上でファイルの編集は完了です。

# 3. デバッグ

実際にFポートが使用可能になったか、試してみたいと思います。
以下に、デバッグ用のコードを用意しました。
基本的には、[#4 モータの使い方](https://qiita.com/koushiro/items/0471376a9feb9b53b178)の2章~7章で紹介したコードをつなぎ合わせたものになっています。

```c:portF_test.c
#include <stdlib.h>
#include <stdio.h>
#include <kernel.h>

#include <spike/hub/system.h>

#include <portF_test.h>

#include "spike/pup/motor.h"
#include "spike/pup/colorsensor.h"
#include "spike/pup/forcesensor.h"
#include "spike/pup/ultrasonicsensor.h"

#include "spike/hub/battery.h"
#include "spike/hub/button.h"
#include "spike/hub/display.h"
#include "spike/hub/imu.h"
#include "spike/hub/light.h"
#include "spike/hub/speaker.h"

#include <pbio/color.h>

#include "kernel_cfg.h"
#include "syssvc/serial.h"

pup_motor_t *motorF;

void Main(intptr_t exinf)
{
  // ここからプログラムを書く
  int i;

  // モータのセットアップ
  motorF = pup_motor_get_device(PBIO_PORT_ID_F);
  pup_motor_setup(motorF, PUP_DIRECTION_CLOCKWISE, true);

  // パワーの設定 (正回転)
  pup_motor_set_power(motorF, 100);
  dly_tsk(3*1000*1000);
  pup_motor_stop(motorF);

  dly_tsk(500*1000);

  // パワーの設定 (逆回転)
  pup_motor_set_power(motorF, -100);
  dly_tsk(3*1000*1000);
  pup_motor_stop(motorF);

  dly_tsk(500*1000);

  // ブレーキ関数のテスト
  pup_motor_set_power(motorF, 100);
  dly_tsk(3*1000*1000);
  pup_motor_brake(motorF);

  dly_tsk(500*1000);

  // 角度維持関数のテスト
  pup_motor_hold(motorF);
  dly_tsk(5*1000*1000);

  // スピードの設定 (正回転)
  pup_motor_set_speed(motorF, 360);
  dly_tsk(1*1000*1000);
  pup_motor_stop(motorF);

  dly_tsk(500*1000);

  // スピードの設定 (逆回転)
  pup_motor_set_speed(motorF, -360);
  dly_tsk(1*1000*1000);
  pup_motor_stop(motorF);

  dly_tsk(500*1000);

  // パワー値の取得
  pup_motor_set_power(motorF, 50);

  for(i=0;i<1000;i++){
    int now_power_F = pup_motor_get_power(motorF); // 今のパワーを得る
    hub_display_number(now_power_F); // ディスプレイに表示する
    dly_tsk(5*1000);
  }

  pup_motor_stop(motorF);
  dly_tsk(500*1000);

  // スピード値の取得
  pup_motor_set_speed(motorF, 360); // 「1秒あたり360度」の回転率で回す

  for(i=0;i<1000;i++){
    int now_speed_F = pup_motor_get_speed(motorF); // 今のパワーを得る
    hub_display_number(now_speed_F/10); // ディスプレイに表示する
    dly_tsk(5*1000);
  }

  pup_motor_stop(motorF);
  dly_tsk(500*1000);

  // 角度の取得
  pup_motor_reset_count(motorF); // モータA の角度をリセット

  while(abs(pup_motor_get_count(motorF)) < 500){
    // パワーの設定
    pup_motor_set_power(motorF, 50);
    hub_display_number(abs(pup_motor_get_count(motorF))/10); // ディスプレイに表示する
  }

  pup_motor_stop(motorF);
  dly_tsk(2*1000*1000);

  exit(0);
}
```

こちらで実行したところ、すべての関数が正しく動作していることが確認出来ました。
モータだけでなく、カラーセンサについても使用可能であることを確認しております。

# 4. おわりに

これまでSPIKE-RTではポートが5つしか使えず、少し不自由に感じる面もありました。
ただ、今回のポートF開放により、ようやく完全体になったと感じております。
皆さんも是非SPIKE Prime & SPIKE-RT でロボット作り、ロボットコンテスト出場にトライしてみてください。

## 謝辞

今回のポートF解放にあたり、私が勤務しているロボットスクールの生徒が、一生懸命調べてくれました。
私自身も調べきれないところまで調べて、沢山デバッグを重ねて、ヒントが少ない中ついにポートF解放までたどり着いてくれました。
この場を借りて感謝申し上げたいと思います。ありがとうございました。

## 関連記事

https://qiita.com/koushiro/items/482162807339f4d18516

https://qiita.com/koushiro/items/0471376a9feb9b53b178