令和2年12月現在では、OTGFSの載っているF407VBBではRNDISは動作しますが、NuttxのRNDISはSTM32F103系ではOTGFSがないため、残念ながら動作しません。そこで、他の方法はないかと調べたところ、RNDISではなくCDCECMがあり、こちらの場合は、STM32F103RCを搭載したボードでネットワーク接続できたので、linux/Debian 11に接続して使うまでを、メモ代わりに本稿を上げてみました。なお、一般的なUSB-Ethernetと異なり、コントローラ自体にアクセスするため、Linux側から見たデバイスにアドレスをあたえるのではなく、デバイス上のインターフェースにアドレスを付与する必要があります。このあたりが少しわかりにくいかもしれませんが、早速設定に入っていきたいと思います。
まず初めに、(2023/10追記: mkdir -p nuttx/boards/arm/stm32/f103rcbb/configs/cdcecm でディレクトリを作ってからの) cdcecm/defconfigですが、以下の様にしてみました。なお、IPアドレスはbridge経由でDHCPにて取得するようにしています。(固定IPの場合、bridge非経由・経由のいずれも、telnetdが自動的に起動しませんでした。)
ボードが複数枚ある場合は、上記の
CONFIG_NETINIT_MACADDR_1=0xbabe000a
CONFIG_CDCECM_MACSTRID="0a0ebabe000a"
を変更して、ビルドしています。
追記:2021/03/06: ボードが複数枚ある場合でも、CPUIDの一部をmac addressの一部にマッピングさせたので、同じバイナリーでも個体ごとに異なるmac addressが設定されるようにしました。
参考までに、f103rcbbなるボードは、nucleo-f103rbからフォークさせたものです。
次は、そのほかの変更です。
boards/arm/stm32/f103rcbb/src/Make.defs
make menuconfigで設定できるようにしてみました。追記:2021/03/06: STM32F10XXでCPUID(12byte)の一部を疑似的にmac addressとして自動設定するようにしました。以下、変更および設定です。
なお、usbとして認識される場合(ONFIG_CDCECM_MACSTRID="020000112233"のままの場合、または、固定IPの場合)とethとして認識される場合(CONFIG_CDCECM_MACSTRIDをCONFIG_NETINIT_MACADD_1 CONFIG_NETINIT_MACADD_2に合わせて変更した場合)があります。こちらで調べた範囲ですが、CONFIG_NETINIT_MACADD_1,2 とCONFIG_CDCECM_MACSTRIDが全く同一の場合、ネットワークの動きが怪しくなりますが、上述のように、Vender IDに該当する部分のみ変更し残りを合わせておくと、CONFIG_CDCECM_MACSTRIDを変更してもethXとして認識されます。修正:2020/03/09:udevでmac addressごとにethXとして識別されるようにしました
/etc/udev/rules.d/70-persistent-net.rules
今回は以上です。それでは。
CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="f103rcbb" CONFIG_ARCH_BOARD_F103RCBB=y CONFIG_ARCH_CHIP="stm32" CONFIG_ARCH_CHIP_STM32=y CONFIG_ARCH_CHIP_STM32F103RC=y CONFIG_ARCH_STACKDUMP=y CONFIG_BOARD_LOOPSPERMSEC=5483 CONFIG_BOARDCTL_RESET=y CONFIG_BUILTIN=y CONFIG_DEBUG_FULLOPT=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DEFAULT_SMALL=y CONFIG_DEV_CONSOLE=y # 2023/10/20追記 12.2.1 CONFIG_DISABLE_PTHREAD=n CONFIG_FILE_STREAM=y CONFIG_INTELHEX_BINARY=y CONFIG_LIB_BOARDCTL=y CONFIG_MAX_TASKS=16 CONFIG_MAX_WDOGPARMS=2 CONFIG_NFILE_DESCRIPTORS=8 CONFIG_NFILE_STREAMS=8 CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_FILEIOSIZE=512 CONFIG_FILE_STREAM=y CONFIG_NSH_LINELEN=80 CONFIG_PREALLOC_MQ_MSGS=4 CONFIG_PREALLOC_TIMERS=4 CONFIG_PREALLOC_WDOGS=4 CONFIG_RAM_SIZE=49152 CONFIG_RAM_START=0x20000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_HPWORK=y CONFIG_SCHED_HPWORKPRIORITY=192 CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y CONFIG_SERIAL_TERMIOS=y CONFIG_START_DAY=5 CONFIG_START_MONTH=7 CONFIG_START_YEAR=2011 CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y CONFIG_STM32_JTAG_FULL_ENABLE=y CONFIG_STM32_USART1=y CONFIG_SYMTAB_ORDEREDBYNAME=y CONFIG_SYSTEM_NSH=y CONFIG_TASK_NAME_SIZE=0 CONFIG_USART1_SERIAL_CONSOLE=y # 2023/10/20追記: 0.9.1 CONFIG_USER_ENTRYPOINT="nsh_main" # 2023/10/20追記:12.2.1 CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_WDOG_INTRESERVE=0 CONFIG_FS_PROCFS=y CONFIG_BOARD_LATE_INITIALIZE=y CONFIG_USBDEV=y CONFIG_BOARDCTL_USBDEVCTRL=y CONFIG_STM32_USB=y CONFIG_SYSTEM_PING=y CONFIG_NET=y CONFIG_NET_CDCECM=y CONFIG_NET_BROADCAST=y CONFIG_NET_ICMP=y CONFIG_NET_ICMP_SOCKET=y CONFIG_NET_ROUTE=y CONFIG_NET_ARP_IPIN=y CONFIG_NET_ARP_SEND=y CONFIG_NET_STATISTICS=y CONFIG_NET_TCP=y CONFIG_NET_TCP_NOTIFIER=y CONFIG_NET_TCP_WRITE_BUFFERS=y CONFIG_NET_UDP=y CONFIG_NET_LOOPBACK=y CONFIG_NET_SOCKOPTS=y CONFIG_NETDEV_PHY_IOCTL=y CONFIG_NETDEV_IFINDEX=y CONFIG_NETDEVICES=y CONFIG_NETINIT_NETLOCAL=n CONFIG_NETINIT_NOMAC=y CONFIG_NETUTILS_DHCPC=y CONFIG_NETUTILS_TELNETD=y CONFIG_NETINIT_DHCPC=y CONFIG_NETINIT_SWMAC=y CONFIG_NETINIT_MACADDR_1=0xbabe000a CONFIG_NETINIT_MACADDR_2=0x00e0 CONFIG_NETINIT_THREAD=y # 2023/10/20: 0.9.1 以下 CONFIG_NSH_TELNET=y CONFIG_NSH_DISABLE_TELNETD=n # 0.9.1 以上 # 2023/10/20: 12.2.1 以下 CONFIG_NSH_LIBRARY=y CONFIG_NSH_TELNET=y CONFIG_NSH_DISABLE_TELNETD=n CONFIG_NSH_DISABLE_TELNETSTART=n CONFIG_SYSTEM_TELNETD=y # 12.2.1 以上 CONFIG_NETDB_DNSCLIENT=y CONFIG_NETDB_DNSSERVER_IPv4ADDR=0x0 CONFIG_CDCECM_MACSTRID="a0e0babe000a"
ifeq ($(CONFIG_USBDEV),y) CSRCS += stm32_usbdev.c endif # 2023/10/20追記:追加 ifeq ($(CONFIG_NETDEVICES),y) CSRCS += stm32_netinit.c endif # 2023/10/20追記:変更 ifeq ($(CONFIG_BOARDCTL),y) CSRCS += stm32_appinit.c ifeq ($(CONFIG_BOARDCTL_RESET),y) CSRCS += stm32_reset.c endif endif # stm32_netinit.cのコピー cp boards/arm/stm32/stm32f4discovery/src/stm32_netinit.c boards/arm/stm32/f103rcbb/src/stm32_netinit.c sed -i 's/stm32f4discovery/f103rcbb/g' boards/arm/stm32/f103rcbb/src/stm32_netinit.c # stm32_rest.cのコピー cp boards/arm/stm32/stm32f103-minimum/src/stm32_reset.c boards/arm/stm32/f103rcbb/src/stm32_reset.c sed -i 's/stm32f103-minimum/f103rcbb/g' boards/arm/stm32/f103rcbb/src/stm32_reset.cboards/arm/stm32/f103rcbb/src/stm32_bringup.c
...
#ifdef CONFIG_NET_CDCECM
# include <nuttx/usb/cdcecm.h>
# include <net/if.h>
#endif
...
int stm32_bringup(void)
{
...
## 0.9.1
#ifdef CONFIG_NET_CDCECM
ret = cdcecm_initialize(0, NULL);
if (ret < 0)
{
_err("ERROR: cdcecm_initialize() failed: %d\n", ret);
}
#endif
## 12.2.1
#ifdef CONFIG_NET_CDCECM
ret = cdcecm_initialize(0, NULL);
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: :cdcecm_initialize() failed: %d\n",
ret);
return ret;
}
#endif
#endif
...
2023/10/20追記:
boards/arm/stm32/f103rcbb/include/board.h
...
/* USB divider -- Divide PLL clock by 1.5 */
#define STM32_CFGR_USBPRE 0
...
/* USB Soft Connect Pullup: PC.12 */
#define GPIO_USB_PULLUP (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\
GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN12)
2023/10/20追記:
cp boards/arm/stm32/stm32f103-minimum/src/stm32_usbdev.c boards/arm/stm32/f103rcbb/src/stm32_usbdev.c sed -i 's/stm32f103-minimum/f103rcbb/g' boards/arm/stm32/f103rcbb/src/stm32_usbdev.c sed -i 's/stm32f103_minimum/f103rcbb/g' boards/arm/stm32/f103rcbb/src/stm32_usbdev.c基本的にはUSBをDebianマシンに接続すればネットにつながるようにしてみました。 具体的には、接続されるごとにethX としてudev上で認識させ、さらにそれらをブリッジ br0 に接続されるようにしています。 なお、2020/12現在のNuttxではcdcecmのmac addressはソースコードdrivers/usbdev/cdcecm.cに、linux側から認識されるmacアドレスは020000112233で、さらにnuttx上でinterfaceがupされるときのアドレスは"\x00\xe0\xde\xad\xbe\xef"でハードコーディングされていてますので、
$ diff -urN drivers/usbdev/cdcecm.c.orig drivers/usbdev/cdcecm.c
--- drivers/usbdev/cdcecm.c.orig 2020-09-21 00:09:41.000000000 +0900
+++ drivers/usbdev/cdcecm.c 2021-03-06 13:44:33.544785800 +0900
@@ -123,6 +123,10 @@
#define BUF ((struct eth_hdr_s *)self->dev.d_buf)
+#ifdef CONFIG_STM32_STM32F10XX
+#define ID3 (*(unsigned long *)0x1FFFF7F0)
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -1337,9 +1341,33 @@
self->config = config;
/* Set client's MAC address */
-
+#if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_NETINIT_MACADDR_2)
+ uint8_t mac[6];
+ unsigned long *id3 = (unsigned long *)0x1FFFF7F0;
+ mac[0] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 1)) & 0xff;
+ mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff;
+ mac[2] = (id3[0] >> (8 * 3)) & 0xff;
+ mac[3] = (id3[0] >> (8 * 2)) & 0xff;
+ mac[4] = (id3[0] >> (8 * 1)) & 0xff;
+ mac[5] = (id3[0] >> (8 * 0)) & 0xff;
+ memcpy(self->dev.d_mac.ether.ether_addr_octet,
+ &mac, IFHWADDRLEN);
+#else
+#if defined(CONFIG_NETINIT_MACADDR_1) && defined(CONFIG_NETINIT_MACADDR_2)
+ uint8_t mac[6];
+ mac[0] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 1)) & 0xff;
+ mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff;
+ mac[2] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 3)) & 0xff;
+ mac[3] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 2)) & 0xff;
+ mac[4] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 1)) & 0xff;
+ mac[5] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 0)) & 0xff;
+ memcpy(self->dev.d_mac.ether.ether_addr_octet,
+ &mac, IFHWADDRLEN);
+#else
memcpy(self->dev.d_mac.ether.ether_addr_octet,
"\x00\xe0\xde\xad\xbe\xef", IFHWADDRLEN);
+#endif
+#endif
/* Report link up to networking layer */
@@ -1414,7 +1442,18 @@
#endif
case CDCECM_MACSTRID:
- str = "020000112233";
+#ifdef CONFIG_STM32_STM32F10XX
+ /* Use CPU ID3 as part of pseudo mac address */
+ ;
+ char id3_str[9] ="", mac_str[13]="";
+ sprintf(id3_str, "%08lx", ID3);
+ strcat (mac_str, "0a0e");
+ strcat (mac_str, id3_str);
+ str = mac_str;
+#else
+ str = CONFIG_CDCECM_MACSTRID;
+#endif
+
break;
default:
@@ -2151,8 +2190,33 @@
* Applies only if the Ethernet MAC has its own internal address.
*/
+#if defined(CONFIG_STM32_STM32F10XX) && defined(CONFIG_NETINIT_MACADDR_2)
+ uint8_t mac[6];
+ unsigned long *id3 = (unsigned long *)0x1FFFF7F0;
+ mac[0] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 1)) & 0xff;
+ mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff;
+ mac[2] = (id3[0] >> (8 * 3)) & 0xff;
+ mac[3] = (id3[0] >> (8 * 2)) & 0xff;
+ mac[4] = (id3[0] >> (8 * 1)) & 0xff;
+ mac[5] = (id3[0] >> (8 * 0)) & 0xff;
+ memcpy(self->dev.d_mac.ether.ether_addr_octet,
+ &mac, IFHWADDRLEN);
+#else
+#if defined(CONFIG_NETINIT_MACADDR_1) && defined(CONFIG_NETINIT_MACADDR_2)
+ uint8_t mac[6];
+ mac[0] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 1)) & 0xff;
+ mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff;
+ mac[2] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 3)) & 0xff;
+ mac[3] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 2)) & 0xff;
+ mac[4] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 1)) & 0xff;
+ mac[5] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 0)) & 0xff;
+ memcpy(self->dev.d_mac.ether.ether_addr_octet,
+ &mac, IFHWADDRLEN);
+#else
memcpy(self->dev.d_mac.ether.ether_addr_octet,
"\x00\xe0\xde\xad\xbe\xef", IFHWADDRLEN);
+#endif
+#endif
/* Register the device with the OS so that socket IOCTLs can be performed */
$ diff -urN ../apps/netutils/netinit/netinit.c.orig ../apps/netutils/netinit/netinit.c --- ../apps/netutils/netinit/netinit.c.orig 2020-09-21 00:09:46.000000000 +0900 +++ ../apps/netutils/netinit/netinit.c 2021-03-06 17:50:52.634785800 +0900 @@ -299,11 +299,18 @@ mac[0] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 1)) & 0xff; mac[1] = (CONFIG_NETINIT_MACADDR_2 >> (8 * 0)) & 0xff; - +#ifdef CONFIG_STM32_STM32F10XX + unsigned long *pmac = (unsigned long *)0x1FFFF7F0; + mac[2] = (pmac[0] >> (8 * 3)) & 0xff; + mac[3] = (pmac[0] >> (8 * 2)) & 0xff; + mac[4] = (pmac[0] >> (8 * 1)) & 0xff; + mac[5] = (pmac[0] >> (8 * 0)) & 0xff; +#else mac[2] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 3)) & 0xff; mac[3] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 2)) & 0xff; mac[4] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 1)) & 0xff; mac[5] = (CONFIG_NETINIT_MACADDR_1 >> (8 * 0)) & 0xff; +#endif /* Set the MAC address */
--- drivers/usbdev/Kconfig.orig 2020-09-21 00:09:41.000000000 +0900
+++ drivers/usbdev/Kconfig 2021-01-03 01:38:22.900000000 +0900
@@ -565,6 +565,10 @@
string "Product string"
default "CDC/ACM Serial"
+config CDCACM_SERIALSTR
+ string "CDC ACM SERIALSTR"
+ default "0"
+
endif # !CDCACM_COMPOSITE
endif # CDCACM
@@ -969,6 +973,10 @@
endif # USBDEV_DUALSPEED
+config CDCECM_MACSTRID
+ string "MAC address string"
+ default "020000112233"
+
if !CDCECM_COMPOSITE
# In a composite device the Vendor- and Product-ID is given by the composite
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="0a:0e:51:16:VV:WW", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="0a:0e:51:14:XX:YY", NAME="eth1"
/etc/network/interfaces.d/br0
auto br0 iface br0 inet static pre-up /sbin/brctl addbr br0 address 10.0.0.1 netmask 255.255.255.0/etc/network/interfaces.d/eth0
allow-hotplug eth0 iface eth0 inet manual pre-up brctl addif br0 eth0 pre-down brctl delif br0 eth0/etc/network/interfaces.d/eth1
allow-hotplug eth1 iface eth1 inet manual pre-up brctl addif br0 eth1 pre-down brctl delif br0 eth1訂正2021/03/16: 外にでるパケットのため、外側IF(例えばenp3s0)をマスカレードさせておきます。
iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE続いて、dhcpサーバをbr0上で駆動させます。IPアドレスを付与するだけなので、とりあえず以下の様にしてみました。 /etc/dhcp/dhcpd.conf
subnet 10.0.0.0 netmask 255.255.255.0 {
range 10.0.0.10 10.0.0.20;
option routers 10.0.0.1;
option domain-name-servers 1.1.1.1, 1.0.0.1;
}
2023/10/20追記:
Debianの場合、DHCPDをIPv6で起動させたくない場合(設定をしない場合)/etc/default/isc-dhcp-serverを以下のようにします。
(前略) INTERFACESv4="br0" INTERFACESv6=""最後にLinux再起動時にボードを再認識させるようにしておきます。(残念ながらこれがないとLinux再起動後、ネットに接続できません。) /usr/local/bin/ls-usb-devices.sh (chmod +x)
#!/bin/bash
{
cd /sys/bus/usb/devices
for i in *; do
[ -e $i/idProduct ] && echo $(cat $i/idVendor $i/idProduct) $i
done
}
/etc/rc.local (chmod +x)
# reset nuttx cdcecm devices
for dev in `/usr/local/bin/ls-usb-devices.sh | grep "0525 a4a2" | awk '{print $3}'`; do \
echo -n $dev > /sys/bus/usb/drivers/usb/unbind
sleep 1
echo -n $dev > /sys/bus/usb/drivers/usb/bind
done
設定が済んだらビルドしたnuttx.binをインストールし、端末をリセットした後で、再起動させたlinux機にusbで接続させてみてください。そうすると、ethXとして認識されたうえに、br0へ追加され、ネットにつながるようになります。
$ telnet 10.0.0.10
Trying 10.0.0.10...
Connected to 10.0.0.10.
Escape character is '^]'.
NuttShell (NSH) NuttX-9.1.0
nsh> ifconfig
lo Link encap:Local Loopback at UP
inet addr:127.0.0.1 DRaddr:127.0.0.1 Mask:255.0.0.0
eth0 Link encap:Ethernet HWaddr 00:e0:51:08:57:08 at UP
inet addr:10.0.0.10 DRaddr:10.0.0.1 Mask:255.255.255.0
IPv4 TCP UDP ICMP
Received 0070 005a 0005 0011
Dropped 0000 0000 0000 0000
IPv4 VHL: 0000 Frg: 0000
Checksum 0000 0000 0000 ----
TCP ACK: 0000 SYN: 0000
RST: 0002 0002
Type 0000 ---- ---- 0000
Sent 006f 0057 0007 0011
Rexmit ---- 0000 ---- ----
nsh> ping -c2 www.google.com
PING 216.58.220.100 56 bytes of data
56 bytes from 216.58.220.100: icmp_seq=0 time=10 ms
56 bytes from 216.58.220.100: icmp_seq=1 time=10 ms
2 packets transmitted, 2 received, 0% packet loss, time 2030 ms
#2023/10/20追記:12.2.1でCONFIG_NSH_DISABLE_IFCONFIG=nをコンフィグに含んだのですが、ifconfigが動作しませんでした。今回は以上です。それでは。
コメント
コメントを投稿