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 リターン
.endint (*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();
}