0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FreeRTOSを動かしてみる(12)

Last updated at Posted at 2023-12-25

前回の続き

ということで普通にクラサバアプリが作れるか試してみる。

パラメータとか

images

アプリケーション側ではTCPを使うのでダミーで使用したポートとかぶっても良いのだが
わかりやすいように別にしておく。

サンプルアプリケーションの流れ

標準入力から文字列を受け取ってFreeRTOS側でprefixをつけるだけの単純なecho backです。

Linux側

これは特に目新しいことも無いので普通に作る

こんなかんじ

sample_app.c

#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>

/* definitions */
#define NEVENTS 2
#define TARGET_SERVER_IP "192.168.100.2"
#define TARGET_SERVER_PORT 7151
#define SERVER_IP INADDR_ANY
#define SERVER_PORT 7150
#define STDIN_BUF_SIZE 256
#define BUF_SIZE 0x10000

#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)

#define d(s, ...)                                                                 \
    do                                                                            \
    {                                                                             \
        pthread_mutex_lock(&mutex);                                               \
        printf("%s(%d) %s " s "\n", __FILENAME__, __LINE__, __func__, ##__VA_ARGS__); \
        pthread_mutex_unlock(&mutex);                                             \
    } while (0)

#define ERRRET(c, s, ...)                                                                      \
    do                                                                                         \
    {                                                                                          \
        if (c)                                                                                 \
        {                                                                                      \
            fprintf(stderr, "%s(%d) %s " s "\n", __FILENAME__, __LINE__, __func__, ##__VA_ARGS__); \
            goto error_return;                                                                 \
        }                                                                                      \
    } while (0)

#ifndef min
#define min(a, b) (a) > (b) ? (b) : (a)
#endif

enum SERVER_STATUS
{
    ST_SRV_NONE,
    ST_SRV_RUNNING,
    ST_SRV_FAILED,
};

static void *server_thread(void *param);
static void init_sock_addr(int *sock, struct sockaddr_in *addr, uint32_t ip, uint16_t port);
static int set_epoll_event(int epfd, int sock, struct epoll_event *ev);
static char *b2s(uint8_t *data, size_t len);
static void send_tcp_to_freertos(uint8_t *data, size_t len);

/* variables */
pthread_t th;
enum SERVER_STATUS server_status = ST_SRV_NONE;
static char stdin_buf[STDIN_BUF_SIZE];
static __thread char rx_buf[BUF_SIZE];
static char print_buf[BUF_SIZE];
static pthread_mutex_t mutex;

int main(void)
{
    int ret;
    char *p;

    pthread_mutex_init(&mutex, NULL);
    ret = pthread_create(&th, NULL, server_thread, NULL);
    if (ret)
    {
        d("pthread_create failed.");
        return 0;
    }

    while (server_status != ST_SRV_FAILED)
    {
        if (fgets(stdin_buf, STDIN_BUF_SIZE, stdin))
        {
            p = strchr(stdin_buf, '\n');
            if (!p)
                continue;

            *p = '\0';
            send_tcp_to_freertos(p, strlen(p));
        }
    }
    return 0;
}

static void init_sock_addr(int *sock, struct sockaddr_in *addr, uint32_t ip, uint16_t port)
{
    *sock = socket(AF_INET, SOCK_STREAM, 0);
    memset(addr, 0, sizeof(struct sockaddr_in));
    addr->sin_family = AF_INET;
    addr->sin_addr.s_addr = ip;
    addr->sin_port = htons(port);
}

static int set_epoll_event(int epfd, int sock, struct epoll_event *ev)
{

    memset(ev, 0, sizeof(struct epoll_event));
    ev->events = EPOLLIN;
    ev->data.fd = sock;
    return epoll_ctl(epfd, EPOLL_CTL_ADD, sock, ev);
}

static inline char b2c(uint8_t b)
{
    return (0x20 <= b && b <= 0x7e) ? b : '.';
}

static char *b2s(uint8_t *data, size_t org_len)
{
    int i;
    char *p;
    char str[0x11] = {0};
    size_t len = min(sizeof(print_buf) / 5, org_len);

    p = (char *)print_buf;
    for (i = 0; i < len; i++)
    {
        p += sprintf(p, "%02x ", data[i]);
        str[i % 16] = b2c(data[i]);

        if ((i % 16) == 15)
        {
            p += sprintf(p, "%s\n", str);
        }
    }

    if (i % 16)
    {
        str[i] = '\0';
        memset(p, ' ', (16 - (i % 16)) * 3);
        p += (16 - (i % 16)) * 3;
        p += sprintf(p, "%s\n", str);
    }
    return print_buf;
}

static void *server_thread(void *param)
{
    int sock, csock = -1;
    struct sockaddr_in addr, caddr;
    socklen_t csize;
    int epfd;
    struct epoll_event ev[NEVENTS], ev_ret[NEVENTS];
    int i, n, nfds;
    (void)param;

    init_sock_addr(&sock, &addr, SERVER_IP, SERVER_PORT);

    n = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
    ERRRET(n != 0, "bind failed.%d", n);

    n = listen(sock, NEVENTS);
    ERRRET(n != 0, "listen failed.");

    epfd = epoll_create(NEVENTS);
    ERRRET(epfd < 0, "epoll_create failed.");

    n = set_epoll_event(epfd, sock, &ev[0]);
    ERRRET(n != 0, "epoll_ctl failed.");

    server_status = ST_SRV_RUNNING;
    while (1)
    {
        nfds = epoll_wait(epfd, ev_ret, NEVENTS, -1);
        ERRRET(nfds <= 0, "epoll_wait");

        for (i = 0; i < nfds; i++)
        {
            if (ev_ret[i].data.fd == sock)
            {
                csize = sizeof(caddr);
                csock = accept(sock, (struct sockaddr *)&caddr, &csize);
                ev[i].events = EPOLLIN;
                ev[i].data.fd = csock;
                epoll_ctl(epfd, EPOLL_CTL_ADD, csock, &ev[i]);
                d("accept from %x", caddr.sin_addr.s_addr);
            }
            else
            {
                n = read(ev_ret[i].data.fd, rx_buf, BUF_SIZE);
                if (n == 0)
                {
                    epoll_ctl(epfd, EPOLL_CTL_DEL, ev_ret[i].data.fd, NULL);
                    close(ev_ret[i].data.fd);
                    d("close");
                }
                else
                {
                    d("received from FreeRTOS: %s", b2s(rx_buf, n));
                    send(ev_ret[i].data.fd, rx_buf, n, 0);
                }
            }
        }
    }

error_return:
    server_status = ST_SRV_FAILED;
    if (sock >= 0)
        close(sock);
    if (csock >= 0)
        close(csock);
    return NULL;
}

static void send_tcp_to_freertos(uint8_t *data, size_t len)
{
    int sock, ret;
    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    ERRRET(sock < 0, "socket create failed.%d", sock);

    addr.sin_addr.s_addr = inet_addr(TARGET_SERVER_IP);
    addr.sin_family = PF_INET;
    addr.sin_port = htons(TARGET_SERVER_PORT);

    ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    ERRRET(ret, "connect failed.%d", ret);

    ret = send(sock, data, len, 0);
    ERRRET(ret < 0, "send failed.%d", ret);

    ret = recv(sock, rx_buf, BUF_SIZE, 0);
    ERRRET(ret < 0, "recv failed.%d", ret);

    d("send to freertos");

error_return:
    if (sock >= 0)
        close(sock);
    return;
}

FreeRTOS側

マニュアルを見ながら書いてみる
多分意図的だろうと思うけどAPIがLinuxに寄せている気がしてわかりやすい。

なんか送ってみる

$ ./sample_app 
aiueo

FreeRTOSのドライバまでは行ってるが、サーバタスクが受信出来ていないっぽい。

mps2.c(846) send_to_freertos irq fire cpu:0x5635e3d76c80 n:74
[01a4] NetworkInterface.c(272) ether_rx_handler waken sz:74 fr:0xfffffffd 
[23e8] NetworkInterface.c(220) ether_task be waken sz:74 fr:0x291 
[23e8] NetworkInterface.c(233) ether_task xSendEventStructToIPTask:1 sz:74 fr:0x291 

ためしにFreeRTOS側から送信してみる。

[3458] app_client.c(67) vTCPSend socket fr:0xd825 
[3458] FreeRTOS_Sockets.c(3783) FreeRTOS_connect  fr:0xd741 
[6748] NetworkInterface.c(112) xApplicationGetRandomNumber  fr:0x8879 
[3458] FreeRTOS_Sockets.c(3694) prvTCPConnectStart  fr:0x9bf5 
[3458] FreeRTOS_Sockets.c(3701) prvTCPConnectStart fam:2 fr:0x9bf5 
[3458] FreeRTOS_Sockets.c(3717) prvTCPConnectStart FreeRTOS_connect: lp:1024 -> c0a86401:7150 fr:0x9bf5 
mps2.c(751) udp_send2dummy sz:42
mps2.c(846) send_to_freertos irq fire cpu:0x558105197c80 n:42
[6748] NetworkInterface.c(272) ether_rx_handler waken sz:42 fr:0xfffffffd 
[6748] NetworkInterface.c(180) pfOutput ip:164a8c0 po:0 bp:0 len:42 r:1 data:
ff ff ff ff ff ff aa 00 02 aa bb cc 08 06 00 01
08 00 06 04 00 01 aa 00 02 aa bb cc c0 a8 64 02
00 00 00 00 00 00 c0 a8 64 01 
 fr:0x3d3d 
[23e8] NetworkInterface.c(220) ether_task be waken sz:42 fr:0x291 
[3458] FreeRTOS_Sockets.c(3797) FreeRTOS_connect prvTCPConnectStart:0 fr:0xd741 
[3458] FreeRTOS_Sockets.c(3826) FreeRTOS_connect xResult:0 fr:0xd741 
[23e8] NetworkInterface.c(233) ether_task xSendEventStructToIPTask:1 sz:42 fr:0x291 
mps2.c(751) udp_send2dummy sz:42
mps2.c(846) send_to_freertos irq fire cpu:0x558105197c80 n:42
[6748] NetworkInterface.c(180) pfOutput ip:164a8c0 po:[6748] NetworkInterface.c(272) ether_rx_handler waken sz:42 fr:0xfffffff1 
0 bp:0 len:42 r:1 data:
ff ff ff ff ff ff aa 00 02 aa bb cc 08 06 00 01
08 00 06 04 00 01 aa 00 02 aa bb cc c0 a8 64 02
00 00 00 00 00 00 c0 a8 64 01 
 fr:0x3d3d 
[23e8] NetworkInterface.c(220) ether_task be waken sz:42 fr:0x291 
[23e8] NetworkInterface.c(233) ether_task xSendEventStructToIPTask:1 sz:42 fr:0x291 
mps2.c(751) udp_send2dummy sz:42
[67mps2.c(846) send_to_freertos irq fire cpu:0x558105197c80 n:42
][6748] NetworkInterface.c(272) ether_rx_handler waken sz:42 fr:0xfffffffd 
 NetworkInterface.c(272) ether_rx_handler waken sz:42 fr:0xfffffffd 
a:
ff ff ff ff ff ff aa 00 02 aa bb cc 08 06 00 01
08 00 06 04 00 01 aa 00 02 aa bb cc c0 a8 64 02
00 00 00 00 00 00 c0 a8 64 01 
 fr:0x3d3d 
[23e8] NetworkInterface.c(220) ether_task be waken sz:42 fr:0x291 
[23e8] NetworkInterface.c(233) ether_task xSendEventStructToIPTask:1 sz:42 fr:0x291 
[3458] FreeRTOS_Sockets.c(3854) FreeRTOS_connect uxEvents:20 xResut:0 fr:0xd741 
[3458] app_client.c(97) vTCPSend not connected fr:0xd825 

つながらない。なんでだろう。
pingはとぶのになぁ

$ ping -w1 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_seq=1 ttl=64 time=10.7 ms

--- 192.168.100.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.690/10.690/10.690/0.000 ms

戻り値を見てみると特別なエラーとかではなくpdFREERTOS_ERRNO_ENOTCONN(128)が返っている

[3458] app_client.c(98) vTCPSend not connected. -128 fr:0xd825

以下の5パターンのどこかと思われるのでログを埋めてみる

FreeRTOS-Plus-TCP$ grep pdFREERTOS_ERRNO_ENOTCONN . -wnrI
./source/FreeRTOS_IP_Utils.c:1515:        case pdFREERTOS_ERRNO_ENOTCONN:
./source/include/FreeRTOS_Sockets.h:85:    #define FREERTOS_ECLOSED                 ( -pdFREERTOS_ERRNO_ENOTCONN )
./source/include/FreeRTOS_errno_TCP.h:78:    #define pdFREERTOS_ERRNO_ENOTCONN            128 /* Socket is not connected */
./source/FreeRTOS_Sockets.c:3857:                    xResult = -pdFREERTOS_ERRNO_ENOTCONN;
./source/FreeRTOS_Sockets.c:4159:                xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
./source/FreeRTOS_Sockets.c:4337:            xResult = -pdFREERTOS_ERRNO_ENOTCONN;
./source/FreeRTOS_Sockets.c:4619:                    xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
./source/FreeRTOS_Sockets.c:4744:            xResult = -pdFREERTOS_ERRNO_ENOTCONN;

uxEventsがeSOCKET_CLOSED(0x20)になっている

3848                 /* Go sleeping until we get any down-stream event */
3849                 uxEvents = xEventGroupWaitBits( pxSocket->xEventGroup,
3850                                                 ( EventBits_t ) eSOCKET_CONNECT | ( EventBits_t ) eSOCKET_CLOSED,
3851                                                 pdTRUE /*xClearOnExit*/,
3852                                                 pdFALSE /*xWaitAllBits*/,
3853                                                 xRemainingTime );

どうもエラールートっぽい

3857                     xResult = -pdFREERTOS_ERRNO_ENOTCONN;
3858                     FreeRTOS_debug_printf( ( "FreeRTOS_connect() stopped due to an error\n" ) );

Linux上でサーバに送信すると普通につながるので
サーバ側のプログラムは問題ない。

sample_app.c(185) server_thread accept from 100007f
sample_app.c(198) server_thread received from FreeRTOS: 61 69 75 65 6f                                  aiueo

sample_app.c(194) server_thread close

というかそもそもSYN(IPv4)パケットがpfOutputに来ていない。

途中で捨てていないのに0806(ARPパケット)しか来ていない

なんかこんな記事もあったけど
これが本当なら大分使い勝手悪そう、、、

FreeRTOSをサーバにしてLinuxから送ると当然だがSYNパケットが送られている。
(13バイトめの08 00がIv4パケット、48バイトめ(3行目末尾)のa0 02の 002の部分がSYN)

[24b8] NetworkInterface.c(237) ether_task xSendEventStructToIPTask:1 sz:74 data:
aa 00 02 aa bb cc aa 00 02 11 22 33 08 00 45 00
00 3c 84 a0 40 00 40 06 6c c7 c0 a8 64 01 c0 a8
64 02 85 fe 1b ef 32 8b df 50 00 00 00 00 a0 02
fe 2e 72 1f 00 00 02 04 05 a6 04 02 08 0a ec 8b
ee 15 00 00 00 00 01 03 03 07 
 fr:0x291 

で、FreeRTOSが受け取ったこのパケットはどこかに消えていき、その後はひたすらARPを打ち続ける。

完全にFreeRTOSだけの問題なので設定とかドライバの書き方に問題があるかなにかと思われるが、、、

xSendEventStructToIPTaskの先を見てみる
FreeRTOS-Plus-TCP/source/FreeRTOS_IP.c

1379 BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent,
1380                                      TickType_t uxTimeout )
...
1425             xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout );

Queueに積んでるだけ

使ってる人

FreeRTOS-Plus-TCP$ grep xNetworkEventQueue . -wnrI | fgrep -v "/test/"
./source/FreeRTOS_IP_Timers.c:279:            if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0U )
./source/FreeRTOS_IP_Utils.c:953:    configASSERT( xNetworkEventQueue == NULL );
./source/include/FreeRTOS_IP_Private.h:104:extern QueueHandle_t xNetworkEventQueue;
./source/portable/BufferManagement/BufferAllocation_2.c:138:                    extern QueueHandle_t xNetworkEventQueue;
./source/portable/BufferManagement/BufferAllocation_2.c:139:                    vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
./source/portable/NetworkInterface/LPC17xx/NetworkInterface.c:79:extern QueueHandle_t xNetworkEventQueue;
./source/portable/NetworkInterface/SH2A/NetworkInterface.c:75:extern QueueHandle_t xNetworkEventQueue;
./source/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c:281:                    extern QueueHandle_t xNetworkEventQueue;
./source/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c:282:                    vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
./source/FreeRTOS_Sockets.c:6188:        xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
./source/FreeRTOS_IP.c:181:QueueHandle_t xNetworkEventQueue = NULL;
./source/FreeRTOS_IP.c:214:    /** @brief Keep track of the lowest amount of space in 'xNetworkEventQueue'. */
./source/FreeRTOS_IP.c:226: *        'xNetworkEventQueue'. prvIPTask() is the only task which has access to
./source/FreeRTOS_IP.c:276:    if( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE )
./source/FreeRTOS_IP.c:287:                uxCount = uxQueueSpacesAvailable( xNetworkEventQueue );
./source/FreeRTOS_IP.c:785:    if( xQueueSendToBackFromISR( xNetworkEventQueue, &xNetworkDownEvent, &xHigherPriorityTaskWoken ) != pdPASS )
./source/FreeRTOS_IP.c:967:            xNetworkEventQueue = xQueueCreateStatic( ipconfigEVENT_QUEUE_LENGTH,
./source/FreeRTOS_IP.c:974:            xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) );
./source/FreeRTOS_IP.c:975:            configASSERT( xNetworkEventQueue != NULL );
./source/FreeRTOS_IP.c:979:    if( xNetworkEventQueue != NULL )
./source/FreeRTOS_IP.c:986:                vQueueAddToRegistry( xNetworkEventQueue, "NetEvnt" );
./source/FreeRTOS_IP.c:1029:            vQueueDelete( xNetworkEventQueue );
./source/FreeRTOS_IP.c:1030:            xNetworkEventQueue = NULL;
./source/FreeRTOS_IP.c:1405:                    if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0U )
./source/FreeRTOS_IP.c:1425:            xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout );

待ってる人一人だけっぽい。
ログ仕込んでみると

[24b8] NetworkInterface.c(237) ether_task xSendEventStructToIPTask:1 sz:74 data:
aa 00 02 aa bb cc aa 00 02 11 22 33 08 00 45 00
00 3c 13 0a 40 00 40 06 de 5d c0 a8 64 01 c0 a8
64 02 dd 1e 1b ef 89 27 cb fd 00 00 00 00 a0 02
fe 2e d6 09 00 00 02 04 05 a6 04 02 08 0a ec a1
ef ab 00 00 00 00 01 03 03 07 
 fr:0x291 
[6748] FreeRTOS_IP.c(279) prvProcessIPEventsAndTimers queue no event fr:0x5cff 
[6748] FreeRTOS_IP.c(1419) xSendEventStructToIPTask send fr:0x57a3 

送ってるデータが無いことにされているっぽい

mps2.c(846) send_to_freertos irq fire cpu:0x55c69fb34880 n:74
[01a4] NetworkInterface.c(276) ether_rx_handler waken sz:74 fr:0xfffffffd 
[24b8] NetworkInterface.c(224) ether_task be waken sz:74 fr:0x291 
[24b8] FreeRTOS_IP.c(1419) xSendEventStructToIPTask send ev:1 to:0 fr:0xd49f 
[6748] FreeRTOS_IP.c(276) prvProcessIPEventsAndTimers wait queue wait:1000 fr:0x5d0b 
[24b8] FreeRTOS_IP.c(1429) xSendEventStructToIPTask queue push is 1 fr:0xd49f 
[24b8] NetworkInterface.c(237) ether_task xSendEventStructToIPTask:1 sz:74 data:
aa 00 02 aa bb cc aa 00 02 11 22 33 08 00 45 00
00 3c fa aa 40 00 40 06 f6 bc c0 a8 64 01 c0 a8
64 02 e3 6c 1b ef 7d f5 22 7f 00 00 00 00 a0 02
fe 2e 4e 89 00 00 02 04 05 a6 04 02 08 0a ec b5
25 7b 00 00 00 00 01 03 03 07 
 fr:0x291 
[6748] FreeRTOS_IP.c(279) prvProcessIPEventsAndTimers queue no event fr:0x5d0b 

xSendEventStructToIPTaskのタイムアウトを変えてみたりしたが関係なかった。

FreeRTOSからはarpリクエストがひたすら来てるからこれドライバで応答返さないといけない?
IPスタックにそのまま投げてるが応答返す気配がないのが問題かも???

ドライバからIPを取得する方法がわからなかったので
試しに固定値で返すようにしてみた。

static void arp_reply(uint8_t *data, size_t len)
{
    memcpy(reply_data, data, len);
    struct ethhdr *eth = (struct ethhdr*)data;
    struct arphdr *arp = (struct arphdr *)&eth[1];
    struct arpbdy *bdy = (struct arpbdy *)&arp[1];
    macaddr_t tomac = *(macaddr_t *)eth->h_source;
    ipaddr_t toip = bdy->src_ip;

    eth = (struct ethhdr *)reply_data;
    arp = (struct arphdr *)&eth[1];
    bdy = (struct arpbdy *)&arp[1];

    *(macaddr_t*)eth->h_dest = tomac;
    *(macaddr_t*)eth->h_source = self_mac_addr;
    arp->ar_op = 0x0200;
    *(uint32_t*)&bdy->src_ip = 0x0164a8c0;
    bdy->src_mac = self_mac_addr;
    bdy->tgt_ip = toip;
    bdy->tgt_mac = tomac;

    send_udp(reply_data, len);
}

FreeRTOSも同様にしてみるが、まぁ関係なかった

static void arp_reply(uint8_t *data, size_t len)
{
    EthernetHeader_t *eth = (EthernetHeader_t *)data;
    ARPHeader_t *arp = (ARPHeader_t *)&eth[1];
    MACAddress_t mac;
    IP_Address_t ip;
    MACAddress_t tomac = eth->xSourceAddress;
    IP_Address_t toip = *(IP_Address_t *)arp->ucSenderProtocolAddress;

    NetworkEndPoint_t *ep = FreeRTOS_FirstEndPoint(NULL);
    if (ep)
    {
        ip = *(IP_Address_t *)&ep->ipv4_defaults.ulIPAddress;
        mac = ep->xMACAddress;
        eth = (EthernetHeader_t *)reply_buf;
        arp = (ARPHeader_t *)&eth[1];

        eth->xDestinationAddress = tomac;
        eth->xSourceAddress = mac;
        arp->usOperation = 0x0200;
        arp->xSenderHardwareAddress = mac;
        *(IP_Address_t *)arp->ucSenderProtocolAddress = ip;
        arp->xTargetHardwareAddress = tomac;
        *(IP_Address_t*)&arp->ulTargetProtocolAddress = toip;
        mmio_write_on();
        *TX_SIZE = len;
        mmio_write(0, (uint8_t *)reply_buf, len);
        mmio_write_off();
    }
}

ドライバがarp理解しないとダメとかさすがにないよな。
とするとIPスタックのどこかで詰まっている。

ICMP(24バイトめが01)の場合はQueueに積む関数を抜ける前に即返している
➡受信時の出力をxSendEventStructToIPTaskを抜けたあとにしているので順序逆転している。

[24b8] NetworkInterface.c(228) ether_task be waken sz:98 fr:0x291 
[24b8] FreeRTOS_IP.c(1419) xSendEventStructToIPTask send ev:1 to:0 fr:0xd421 
mps2.c(751) udp_send2dummy sz:98
[674c] NetworkInterface.c(187) pfOutput ip:0 po:0 bp:0 len:98 r:1 data:
aa 00 02 11 22 33 aa 00 02 aa bb cc 08 00 45 00
00 54 5e 40 00 00 40 01 d3 14 c0 a8 64 02 c0 a8
64 01 00 00 06 ec 00 17 00 01 e3 51 89 65 00 00
00 00 c3 71 0a 00 00 00 00 00 10 11 12 13 14 15
16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
 fr:0x5873 
[24b8] FreeRTOS_IP.c(1429) xSendEventStructToIPTask queue push is 1 fr:0xd421 
[24b8] NetworkInterface.c(249) ether_task rx data to stack:1 sz:98 data:
aa 00 02 11 22 33 aa 00 02 aa bb cc 08 00 45 00
00 54 5e 40 00 00 40 01 d3 14 c0 a8 64 02 c0 a8
64 01 00 00 06 ec 00 17 00 01 e3 51 89 65 00 00
00 00 c3 71 0a 00 00 00 00 00 10 11 12 13 14 15
16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
 fr:0x291 

ここまでのコード


参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?