令和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が動作しませんでした。
今回は以上です。それでは。
コメント
コメントを投稿