setup stack pointer move initial data from ROM to RAM clear non-initial RAM area call main routine
set config (bus width etc.) init_device(); if MODE != 5 then user1_start else user2_start (MES/main.c)
init(); device open, set_handle(task_sw) ip_init(); arp_init(); udp_init(); tcp_init(); task_init(); task_attach(initial());
.h8300h .section .text .align 1 .global _int_wovi .global _int_trap0 .global _int_trap1 .global _int_trap2 _int_wovi: _int_trap0: push.l er0 いろいろPUSH push.l er1 push.l er2 push.l er3 push.l er4 push.l er5 push.l er6 mov.l @_stackpp,er0 SPをstackppに設定 mov.l sp,@er0 mov.l @_handlefunc,er0 handlefuncをcall jsr @er0 _int_trap2: mov.l @_stackpp,er0 SPをstackppに設定 mov.l @er0,sp pop.l er6 いろいろPOP pop.l er5 pop.l er4 pop.l er3 pop.l er2 pop.l er1 pop.l er0 rte リターン _int_trap1: mov.l @_curtaskp,er0 curtaskpをer0に入れて mov.l @er0,er0 rte リターン .end
int (*handlefunc)(); void *stackpp, *curtaskp; void set_handle(int (*func)(), void *spp, void *ctp) { handlefunc = func; stackpp = spp; curtaskp = ctp; }
set_handle(task_sw, &stackptr, &curtask);
つまり、curtaskにtask_sw()を登録してから、 task_init()を呼ぶ(initial()が呼ばれる)
単純に自分のIP, MASK, MACを返すだけ
typedef struct { uint32_t rem_ip; // Remote IP address uint32_t send_unacked; uint32_t send_next; uint32_t receive_next; uint32_t packet_size; uint32_t next_packet_size; uint32_t recv_packet_size; STRING packet; STRING next_packet; STRING recv_packet; int32_t (*event_listener)(uint32_t, Byte, uint32_t, uint16_t); uint16_t remport; // Remote TCP port uint16_t locport; // Local TCP port uint16_t id; // task id uint16_t send_mtu; Byte state; Byte type; Byte flags; // State machine flags Byte myflags; // My flags to be Txed Byte close_count; Byte resend_timer; Byte ack_timer; Byte fin_timer; } tcp_info;
#define TCP_STATE_FREE 1 #define TCP_STATE_RESERVED 2 #define TCP_STATE_CLOSED 3 #define TCP_STATE_LISTENING 4 #define TCP_STATE_SYN_RECEIVED 5 #define TCP_STATE_SYN_SENT 6 #define TCP_STATE_FINW1 7 #define TCP_STATE_FINW2 8 #define TCP_STATE_CLOSING 9 #define TCP_STATE_LAST_ACK 10 #define TCP_STATE_TIMED_WAIT 11 #define TCP_STATE_CONNECTED 12
void tcp_init() { int32_t i; for(i = 0;i <= TCP_NUM;i++) { tcp_socket[i].state = TCP_STATE_FREE; tcp_socket[i].type = TCP_TYPE_NONE; tcp_socket[i].flags = 0; tcp_socket[i].rem_ip = 0; tcp_socket[i].remport = 0; tcp_socket[i].locport = 0; tcp_socket[i].myflags = 0; tcp_socket[i].send_mtu = TCP_DEF_MTU; tcp_socket[i].event_listener = 0; } }
case TCP_STATE_SYN_SENT: if(tcphdr->hlen_flags & TCP_FLAG_RESET) { soc->event_listener(sock, TCP_EVENT_ABORT, soc->rem_ip, soc->remport); if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return -1; } /* Is it SYN+ACK? */ if((tcphdr->hlen_flags & TCP_FLAG_SYN) && (tcphdr->hlen_flags & TCP_FLAG_ACK)) { /* Right ACK? */ if( tcphdr->ackno != soc->send_next ) return -1; soc->receive_next = tcphdr->seqno; soc->receive_next++; /* ACK SYN */ soc->send_unacked = soc->send_next; tcp_newstate(sock, TCP_STATE_CONNECTED); soc->myflags = TCP_FLAG_ACK; tcp_sendcontrol(sock); プライベート内では通るけど、ルータ越しでは通らない soc->event_listener(sock, TCP_EVENT_CONNECTED, soc->rem_ip, soc->remport); return 0;
int32_t tcpip(uint32_t fd, IP_HDR *iphdr, Byte *destmac) { int32_t index, ret; uint32_t ip, mask; Byte mac[6]; if(iphdr->version != 4) return -1; index = fd2index(fd); if(index == -1) return -1; ret = set_ip_addr(index, iphdr->destip, destmac); if(ret == -1) return -1; ret = get_ipinfo(index, &ip, &mask, mac); if(ret == -1) return -1; if((ip & mask) != (iphdr->srcip & mask)) return -1; ここで同一ネットワーク内でないとreturnしている? if(ip != iphdr->destip && (iphdr->destip | mask) != 0xffffffff) return -1; switch(iphdr->proto) { case ICMP: icmp(fd, iphdr); break; case UDP: udp(fd, iphdr); break; case TCP: tcp(fd, iphdr); break; } return 0;
if((soc->id != id) && (soc->state != TCP_STATE_FREE) && (soc->state != TCP_STATE_RESERVED) && (soc->state != TCP_STATE_CLOSED)) { return -1; }
ret = tcp_releasesocket(id, sock); if(ret == -1) { task = get_taskptr(id); task->state |= NET_STATE; soc->fin_timer = 2; } return ret;
if(sys_count != sys_count_ms / 1000) { check_flagroot_index(); tcp_interval(); }
if((soc->fin_timer) > 0) { if(--(soc->fin_timer) == 0) { task->state &= ~NET_STATE; task->retval = -1; tcp_abort(i); tcp_releasesocket(soc->id, i); } }
case TCP_STATE_SYN_SENT: case TCP_STATE_SYN_RECEIVED: case TCP_STATE_CONNECTED: case TCP_STATE_FINW1: case TCP_STATE_FINW2: case TCP_STATE_CLOSING: case TCP_STATE_LAST_ACK: soc->myflags = TCP_FLAG_RESET; tcp_sendcontrol(sock); tcp_newstate(sock, TCP_STATE_CLOSED); return sock;
case TCP_STATE_FINW1: //sockの状態変数はTCP_STATE_FINW1になっている if(tcphdr->hlen_flags & TCP_FLAG_RESET) { //結局、ここを通っていない。ただし、tcpip()からtcp()は呼ばれている soc->event_listener(sock, TCP_EVENT_ABORT, soc->rem_ip, soc->remport); if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return -1; } /* Is it FIN+ACK? */ if((tcphdr->hlen_flags & TCP_FLAG_FIN) && (tcphdr->hlen_flags & TCP_FLAG_ACK)) { if(tcphdr->ackno != soc->send_next) return -1; soc->receive_next = tcphdr->seqno; soc->receive_next++; soc->receive_next += dlen; soc->send_unacked = soc->send_next; tcp_newstate(sock, TCP_STATE_TIMED_WAIT); soc->myflags = TCP_FLAG_ACK; tcp_sendcontrol(sock); return 0; } /* Is it just FIN */ if(tcphdr->hlen_flags & TCP_FLAG_FIN) { soc->receive_next = tcphdr->seqno; soc->receive_next++; soc->receive_next += dlen; tcp_newstate(sock, TCP_STATE_CLOSING); soc->myflags = TCP_FLAG_ACK; tcp_sendcontrol(sock); return 0; } /* Is it just ACK? */ //tcpdumpの結果では、ここを通るはず if(tcphdr->hlen_flags & TCP_FLAG_ACK) { /* Right ACK? */ //このif文の中は通っていない。このcase文を通るか? if( tcphdr->ackno != soc->send_next ) return -1; soc->send_unacked = soc->send_next; tcp_newstate(sock, TCP_STATE_FINW2); //TCP_STATE_FINW2に状態遷移 return 0; } break; case TCP_STATE_FINW2: //で、TCP_STATE_FINW2の処理を見ると if(tcphdr->hlen_flags & TCP_FLAG_RESET) { soc->event_listener(sock, TCP_EVENT_ABORT, soc->rem_ip, soc->remport); if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return -1; } if(tcphdr->hlen_flags & TCP_FLAG_FIN) { //tcpdumpの結果では、ここを通るはず soc->receive_next = tcphdr->seqno; soc->receive_next++; soc->receive_next += dlen; tcp_newstate(sock, TCP_STATE_TIMED_WAIT); //TCP_STATE_TIMED_WAITに状態遷移 soc->myflags = TCP_FLAG_ACK; //ここでACK処理している? tcp_sendcontrol(sock); return 0; } break; case TCP_STATE_CLOSING: if(tcphdr->hlen_flags & TCP_FLAG_RESET) { soc->event_listener(sock, TCP_EVENT_ABORT, soc->rem_ip, soc->remport); if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return -1; } /* Is it ACK? */ if( tcphdr->hlen_flags & TCP_FLAG_ACK ) { /* Right ACK? */ if( tcphdr->ackno != soc->send_next ) return -1; soc->send_unacked = soc->send_next; tcp_newstate(sock, TCP_STATE_TIMED_WAIT); return 0; } if(tcphdr->hlen_flags & TCP_FLAG_FIN) { soc->receive_next = tcphdr->seqno; soc->receive_next++; soc->receive_next += dlen; soc->myflags = TCP_FLAG_ACK; tcp_sendcontrol(sock); return 0; } break; case TCP_STATE_LAST_ACK: if(tcphdr->hlen_flags & TCP_FLAG_RESET) { soc->event_listener(sock, TCP_EVENT_ABORT, soc->rem_ip, soc->remport); if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return -1; } /* Is it ACK? */ if( tcphdr->hlen_flags & TCP_FLAG_ACK ) { /* Right ACK? */ if(tcphdr->ackno != soc->send_next) return -1; soc->send_unacked = soc->send_next; if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return 0; } /* Is it repeated FIN? */ if(tcphdr->hlen_flags & TCP_FLAG_FIN) { /* ACK FIN and all data */ soc->receive_next = tcphdr->seqno; soc->receive_next++; soc->receive_next += dlen; soc->myflags = TCP_FLAG_FIN | TCP_FLAG_ACK; tcp_sendcontrol(sock); return 0; } break; case TCP_STATE_TIMED_WAIT: if(tcphdr->hlen_flags & TCP_FLAG_RESET) { soc->event_listener(sock, TCP_EVENT_ABORT, soc->rem_ip, soc->remport); if(soc->type & TCP_TYPE_SERVER) tcp_newstate(sock, TCP_STATE_LISTENING); else tcp_newstate(sock, TCP_STATE_CLOSED); return -1; } /* Is it repeated FIN? */ if(tcphdr->hlen_flags & TCP_FLAG_FIN) { soc->receive_next = tcphdr->seqno; soc->receive_next++; soc->receive_next += dlen; soc->myflags = TCP_FLAG_ACK; tcp_sendcontrol(sock); return 0; } break;
ptr = (STRING)iphdr; ptr = &(ptr[iphdr->header_len * 4]); tcphdr = (TCP_HDR*)ptr; len = iphdr->datasize; len -= (int32_t)iphdr->header_len * 4; hlen = tcphdr->hlen_flags & 0xF000; hlen >>= 10; if(hlen < MIN_TCP_HLEN) return -1; olen = hlen - MIN_TCP_HLEN; if(olen > MAX_TCP_OPTLEN) return -1; if(hlen > len) return -1; dlen = len - hlen; tcpdata = &ptr[hlen]; sock = tcp_mapsocket(iphdr); //ここで-1が返される if(sock == -1) return 0; //TCP_STATE_FINW1が処理されない soc = &tcp_socket[sock];
static int32_t tcp_mapsocket(IP_HDR *iphdr) { TCP_HDR *tcphdr; STRING ptr; int32_t i;
ptr = (STRING)iphdr; ptr = &(ptr[iphdr->header_len * 4]); tcphdr = (TCP_HDR*)ptr; for(i = 0;i < TCP_NUM;i++) { //既存ソケットの検索 if(tcp_socket[i].state == TCP_STATE_LISTENING) continue; if(tcp_socket[i].remport != tcphdr->sport) continue; //このif文がFALSEにならない=remportとsportとが違う if(tcp_socket[i].locport != tcphdr->dport) continue; if(tcp_socket[i].rem_ip != iphdr->srcip) continue; return i; } if((tcphdr->hlen_flags & TCP_FLAG_SYN) == 0) return -1; //SYN受信〜新規ソケットの作成 if(tcphdr->hlen_flags & TCP_FLAG_ACK) return -1; if(tcphdr->hlen_flags & TCP_FLAG_RESET) return -1; if(tcphdr->hlen_flags & TCP_FLAG_FIN) return -1; for(i = 0;i < TCP_NUM;i++){ if(tcp_socket[i].state != TCP_STATE_LISTENING) continue; if(tcp_socket[i].locport != tcphdr->dport) continue; tcp_socket[i].rem_ip = iphdr->srcip; tcp_socket[i].remport = tcphdr->sport; return i; } return -1; }
void initial() { static STRING ptrs[2]; static Byte name[16]; static int64_t sys_count_ms; volatile char w; Task *taskptr; int32_t c, *sp_ptr; strcpy(name, "/rom0/shell"); ptrs[0] = name; ptrs[1] = 0; curtask->req = EXEC_REQ; curtask->arg[0] = 1; curtask->arg[1] = (int32_t)ptrs; request(curtask); if(curtask->retval == -1) { strcpy(name, "/rom0/netsh"); ptrs[0] = name; ptrs[1] = 0; curtask->req = EXEC_REQ; curtask->arg[0] = 1; curtask->arg[1] = (int32_t)ptrs; request(curtask); if(curtask->retval == -1) { write_device(stdio, "Shell not found, system halt.\n", 31); while(1); } } sys_count_ms = 0; while(1) { //無限ループ int_disable(); for(taskptr = curtask->next;taskptr != curtask;taskptr = taskptr->next) { //タスクのスキャン if(taskptr->state & EXIT_STATE) { //タスクの終了処理 dettach_task(taskptr); taskptr = curtask->next; continue; } if(taskptr->state & REQ_STATE) request(taskptr); //要求待ちタスクの実行 if(taskptr->net_count > 0) { (taskptr->net_count)--; net_request(taskptr); //SEND_ARP_REQのみを処理してる } if(taskptr->count > 0) { taskptr->count -= time_count / counter; if(taskptr->count <= 0) taskptr->count = 0; } if(taskptr->interval > 0) { taskptr->interval -= time_count / counter; if(taskptr->interval <= 0) { #ifdef H8_300H sp_ptr = taskptr->sp; sp_ptr = &(sp_ptr[-1]); taskptr->sp = sp_ptr; for(c = 0;c < PC_REG;c++) sp_ptr[c] = sp_ptr[c + 1]; #endif #ifdef SH sp_ptr[PR_REG] = sp_ptr[PC_REG]; #endif sp_ptr[PC_REG] = (int32_t)(taskptr->sigfunc); taskptr->interval = 0; } } sys_count_ms += time_count / counter; } ip_request(); //rcv_fifoからパケットを取出して time_count -= (time_count / counter) * counter; //case ARP_TYPE, case IP_TYPEする if(sys_count != sys_count_ms / 1000) { check_flagroot_index(); tcp_interval(); //相手のFINに対するACK不送出に関連がある? } sys_count = sys_count_ms / 1000; int_enable(); TRAP0; } }
FDAUのクロックは20MHzなので、task.cの以下を変更する。 でも、ちょっと変なソースなので再考したい。
static void init_timer() { time_count = 0; counter = ((25 * 1000) >> 8) & 0xff; ここの25を20に変更 counter = (256 - counter) & 0xff; WDTはアップカウンタなので256から引算 start_timer(); }