source: EcnlProtoTool/trunk/ntshell/src/main.c@ 442

Last change on this file since 442 was 442, checked in by coas-nagasima, 4 years ago

ntshellアプリはnewlibを使うよう変更し、syscallの実装部分と区別がつくよう更新。

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 14.7 KB
RevLine 
[279]1/*
[433]2 * TOPPERS PROJECT Home Network Working Group Software
[279]3 *
[433]4 * Copyright (C) 2014-2019 Cores Co., Ltd. Japan
[279]5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37
38/*
39 * サンプルプログラム(1)の本体
40 */
41
42#include <kernel.h>
43#include <t_stdlib.h>
44#include <sil.h>
[331]45#include <setjmp.h>
[433]46#include <string.h>
[279]47#include "syssvc/serial.h"
48#include "syssvc/syslog.h"
[441]49#include "target_syssvc.h"
[279]50#include "kernel_cfg.h"
51#include "main.h"
[442]52#include "mbed_retarget.h"
[441]53#include "fdtable.h"
54#ifndef NTSHELL_NO_SOCKET
[279]55#include <tinet_config.h>
56#include <netinet/in.h>
57#include <netinet/in_itron.h>
58#include <tinet_nic_defs.h>
59#include <tinet_cfg.h>
60#include <netinet/in_var.h>
61#include <net/ethernet.h>
62#include <net/if6_var.h>
63#include <net/net.h>
64#include <net/if_var.h>
65#include <netinet/udp_var.h>
66#include "ffarch.h"
67#include "ff.h"
68#include "websocket_fbs.h"
[331]69#include "core/ntshell.h"
70#include "core/ntlibc.h"
[279]71#include "usrcmd.h"
[331]72#include "util/ntopt.h"
[441]73#include "netapp/dhcp4_cli.h"
74#include "ntp_cli.h"
75#include "netcmd.h"
76#endif
[279]77
78ID ws_api_mailboxid = MAIN_DATAQUEUE;
79ID ws_mempoolid = MPF_NET_BUF_256;
80
81char command[NTOPT_TEXT_MAXLEN];
82
[331]83const uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
[279]84
85enum main_state_t {
86 main_state_start,
87 main_state_idle,
[441]88#ifndef NTSHELL_NO_SOCKET
89 main_state_start_dhcp,
90#endif
91 main_state_servey_cmd,
[279]92};
93
[431]94struct main_obj_t {
[432]95 ntshell_t ntshell;
[441]96 int timer;
[279]97 enum main_state_t state;
98 SYSTIM prev, now;
[441]99 task_base_t **tasks;
100 int task_count;
101#ifndef NTSHELL_NO_SOCKET
102 uint8_t link;
103 uint8_t link_up;
104 uint8_t up;
105 uint8_t dhcp;
106 uint8_t ntp;
107 ntp_cli_state_t ntp_state;
108#endif
109 bool_t exec;
110 int event_req, event_res;
[279]111};
[431]112struct main_obj_t main_obj;
[279]113
[441]114#ifndef NTSHELL_NO_SOCKET
115static void netif_link_callback(T_IFNET *ether);
116static void main_change_netif_link(uint8_t link_up, uint8_t up);
117#endif
[432]118static void main_initialize(struct main_obj_t *obj);
[441]119static void main_finalize(struct main_obj_t *obj);
120static int main_get_timer(struct main_obj_t *obj);
121static void main_progress(struct main_obj_t *obj, int elapse);
122static void main_timeout(struct main_obj_t *obj, bool_t wakeup);
123static int execute_command(struct main_obj_t *obj, int wait);
[431]124static int usrcmd_ntopt_callback(long *args, void *extobj);
[441]125#ifndef NTSHELL_NO_SOCKET
126static void ntp_cli_state_changed(ntp_cli_state_t state);
127#endif
[279]128
[441]129void stdio_open(ID portid);
130void stdio_input(unsigned char c);
131
132bool_t dhcp_enable;
133int ntshell_exit;
[431]134int shellcmd_exit_code;
135volatile int shellcmd_state;
136typedef void (*PowerOn_Reset_t)(long *args);
137jmp_buf shellcmd_exit;
138
[441]139void main_task_init(task_base_t **tasks, int task_count)
140{
141 main_obj.tasks = tasks;
142 main_obj.task_count = task_count;
143}
144
[279]145int uart_read(char *buf, int cnt, void *extobj)
146{
[441]147 struct main_obj_t *obj = (struct main_obj_t *)extobj;
148 int result;
149 ER ret;
150 int timer;
151 bool_t wakeup = false;
152
153 obj->prev = obj->now;
154
155 if (obj->event_req != obj->event_res) {
156 obj->event_res = obj->event_req;
157 wakeup = true;
158#ifndef NTSHELL_NO_SOCKET
159 if (obj->dhcp) {
160 obj->dhcp = 0;
161 obj->state = main_state_start_dhcp;
162 }
163#endif
164 obj->timer = 0;
165 }
166
167 /* タイマー取得 */
168 timer = main_get_timer(obj);
169
170 /* 待ち */
171 ret = serial_trea_dat(SIO_PORTID, buf, cnt, timer);
172 if ((ret < 0) && (ret != E_OK) && (ret != E_TMOUT) && (ret != E_RLWAI)) {
173 syslog(LOG_NOTICE, "tslp_tsk ret: %s %d", itron_strerror(ret), timer);
174 ntshell_exit = 1;
175 return -1;
176 }
177 if (ret != E_TMOUT)
178 wakeup = true;
179 result = (int)ret;
180
181 ret = get_tim(&obj->now);
182 if (ret != E_OK) {
183 syslog(LOG_NOTICE, "get_tim ret: %s", itron_strerror(ret));
184 ntshell_exit = 1;
185 return -1;
186 }
187
188 /* 時間経過 */
189 int elapse = obj->now - obj->prev;
190 main_progress(obj, elapse);
191
192 /* タイムアウト処理 */
193 main_timeout(obj, wakeup);
194
195 return result;
[279]196}
197
198int uart_write(const char *buf, int cnt, void *extobj)
199{
200 return serial_wri_dat(SIO_PORTID, buf, cnt);
201}
202
[432]203int cmd_execute(const char *text, void *extobj)
[279]204{
[431]205 if (text != NULL) {
[442]206 strlcpy(command, text, sizeof(command));
[431]207 }
208 ER ret;
209 ID tskid = 0;
[279]210
[431]211 ret = get_tid(&tskid);
212 if (ret != E_OK) {
213 syslog(LOG_ERROR, "get_tid %d", ret);
214 }
215
[441]216 return execute_command(&main_obj, tskid == MAIN_TASK);
[279]217}
218
[441]219gpio_t led_blue, led_green, led_red, sw;
220
[279]221/*
[441]222 * メインタスク
[279]223 */
224void main_task(intptr_t exinf)
225{
[432]226 struct main_obj_t *obj = (struct main_obj_t *)&main_obj;
[279]227
[441]228 gpio_init_out(&led_blue, LED_BLUE);
229 gpio_init_out(&led_green, LED_GREEN);
230 gpio_init_out(&led_red, LED_RED);
231 gpio_init_in(&sw, USER_BUTTON0);
232
233 obj->exec = gpio_read(&sw) == 1;
234
235 gpio_write(&led_blue, 1);
236 gpio_write(&led_green, obj->exec ? 1 : 0);
237 gpio_write(&led_red, 0);
238
239 ether_set_link_callback(main_change_netif_link);
240
241 /* 初期化 */
242 ffarch_init();
243
244 stdio_open(SIO_PORTID);
245
246#ifndef NTSHELL_NO_SOCKET
247 ntp_cli_set_state_changed_cb(ntp_cli_state_changed);
248#endif
249
[432]250 main_initialize(obj);
251
252 ntshell_init(&obj->ntshell, uart_read, uart_write, cmd_execute, obj);
253 ntshell_set_prompt(&obj->ntshell, "NTShell>");
254 ntshell_execute(&obj->ntshell);
[441]255
256 main_finalize(obj);
[279]257}
258
259/*
260 * 初期化
261 */
[432]262static void main_initialize(struct main_obj_t *obj)
[279]263{
[432]264 ER ret;
[441]265 ID tskid = 0;
[279]266
[441]267 ret = get_tid(&tskid);
268 if (ret != E_OK) {
269 syslog(LOG_ERROR, "get_tid %d", ret);
270 return;
271 }
[279]272
[441]273 obj->timer = 100000;
[432]274 obj->state = main_state_start;
[279]275
[441]276 for (int i = 0; i < obj->task_count; i++) {
277 task_base_t *task = obj->tasks[i];
278 task->on_start(task, tskid);
[279]279 }
280
[441]281 gpio_write(&led_blue, 0);
[279]282 gpio_write(&led_green, 0);
283
284 act_tsk(HTTPD1_TASK);
285 act_tsk(HTTPD2_TASK);
286
[432]287 ret = get_tim(&obj->now);
288 if (ret != E_OK) {
[279]289 syslog(LOG_ERROR, "get_tim");
290 ext_tsk();
291 return;
292 }
293}
294
[441]295static void main_finalize(struct main_obj_t *obj)
296{
297 for (int i = 0; i < obj->task_count; i++) {
298 task_base_t *task = obj->tasks[i];
299 task->on_end(task);
300 }
301}
302
[279]303/*
304 * タイマー取得
305 */
[441]306static int main_get_timer(struct main_obj_t *obj)
[279]307{
[441]308 int timer = obj->timer;
[279]309
[441]310 for (int i = 0; i < obj->task_count; i++) {
311 task_base_t *task = obj->tasks[i];
312 int timer2 = task->get_timer(task);
313 if ((timer == -1) || ((timer2 != -1) && (timer > timer2)))
314 timer = timer2;
315 }
316
[279]317 return timer;
318}
319
320/*
321 * 時間経過
322 */
[441]323static void main_progress(struct main_obj_t *obj, int elapse)
[279]324{
[432]325 if (obj->timer != TMO_FEVR) {
326 obj->timer -= elapse;
327 if (obj->timer < 0) {
328 obj->timer = 0;
[279]329 }
330 }
[441]331
332 for (int i = 0; i < obj->task_count; i++) {
333 task_base_t *task = obj->tasks[i];
334 task->progress(task, elapse);
335 }
[279]336}
337
338/*
339 * タイムアウト処理
340 */
[441]341static void main_timeout(struct main_obj_t *obj, bool_t wakeup)
[279]342{
[441]343 ER ret;
344 uint32_t event = wakeup ? MAIN_EVENT_WAKEUP : 0;
345
346 if (!wakeup && (obj->timer != 0))
347 return;
348
349 switch (obj->state) {
350 case main_state_start:
351#ifndef NTSHELL_NO_SOCKET
352 ether_set_link_callback(netif_link_callback);
353#endif
354 {
355 FILINFO fno;
356#if FF_USE_LFN
357 char lfn[FF_MAX_LFN + 1];
358 fno.lfname = lfn;
359 fno.lfsize = FF_MAX_LFN + 1;
360#endif
361 if (f_stat("1:/upload/main.mrb", &fno) != FR_OK) {
362 obj->exec = false;
363 }
364
365 if (obj->exec) {
366 cmd_execute("mruby -b 1:/upload/main.mrb", obj);
367 }
368 }
369 obj->state = main_state_idle;
370 obj->timer = TMO_FEVR;
371 break;
372#ifndef NTSHELL_NO_SOCKET
373 case main_state_start_dhcp:
374 ret = dhcp4c_renew_info();
375 if (ret == E_OK) {
376 obj->state = main_state_idle;
377 obj->timer = TMO_FEVR;
378 }
379 else {
380 obj->state = main_state_start_dhcp;
381 obj->timer = 1000000;
382 }
383 break;
384#endif
385 default:
386 obj->state = main_state_idle;
387 obj->timer = TMO_FEVR;
388 break;
389 }
390#ifndef NTSHELL_NO_SOCKET
391 if (obj->link) {
392 obj->link = 0;
393 event |= MAIN_EVENT_NETIF_CHANGED;
394 if (obj->link_up)
395 event |= MAIN_EVENT_LINK_UP;
396 if (obj->up)
397 event |= MAIN_EVENT_UP;
398
399 if (obj->link_up && obj->up)
400 ntp_cli_execute();
401
402 main_change_netif_link(obj->link_up, obj->up);
403 }
404 if (obj->ntp) {
405 obj->ntp = 0;
406 if (obj->ntp_state != NTP_CLI_STATE_SYNC)
407 event |= MAIN_EVENT_NTP_ASYNC;
408 else
409 event |= MAIN_EVENT_NTP_SYNC;
410 }
411#endif
412 for (int i = 0; i < obj->task_count; i++) {
413 task_base_t *task = obj->tasks[i];
414 task->process(task, event);
415 }
[279]416}
417
[441]418#ifndef NTSHELL_NO_SOCKET
[279]419/* MACアドレスの設定時に呼ばれる */
420void mbed_mac_address(char *mac)
421{
422 memcpy(mac, mac_addr, 6);
423}
424
[441]425void main_change_netif_link(uint8_t link_up, uint8_t up)
[279]426{
427 FLGPTN flgptn;
428 T_RTSK rtsk;
429 ER ret;
430
[431]431 ret = ref_tsk(SHELLCMD_TASK, &rtsk);
[279]432 if ((ret != E_OK) || (rtsk.tskstat == TTS_DMT))
433 return;
434
435 FD_SET(0, (fd_set *)&flgptn);
436
437 set_flg(FLG_SELECT_WAIT, flgptn);
438}
439
[441]440void netif_link_callback(T_IFNET *ether)
441{
442 struct main_obj_t *obj = (struct main_obj_t *)&main_obj;
443 uint8_t link_up = (ether->flags & IF_FLAG_LINK_UP) != 0;
444 uint8_t up = (ether->flags & IF_FLAG_UP) != 0;
445 bool_t wake = false;
446
447 if (dhcp_enable) {
448 if (!link_up)
449 dhcp4c_rel_info();
450 else if (!up) {
451 wake = dhcp4c_renew_info() != E_OK;
452 if (wake) {
453 obj->dhcp = 1;
454 }
455 }
456 }
457 else {
458 up = link_up;
459 }
460
461 if ((obj->link_up != link_up) || (obj->up != up)) {
462 obj->link = 1;
463 wake = true;
464 }
465
466 obj->link_up = link_up;
467 obj->up = up;
468
469 if (wake && (obj->event_req == obj->event_res)) {
470 obj->event_req++;
471 rel_wai(MAIN_TASK);
472 }
473}
474
475void ntp_cli_state_changed(ntp_cli_state_t state)
476{
477 struct main_obj_t *obj = (struct main_obj_t *)&main_obj;
478 bool_t wake = obj->ntp_state != state;
479
480 if (wake) {
481 obj->ntp_state = state;
482 obj->ntp = 1;
483
484 if (obj->event_req == obj->event_res) {
485 obj->event_req++;
486 rel_wai(MAIN_TASK);
487 }
488 }
489}
490#endif
491
[279]492/*
[431]493 * shellcmdタスク
[279]494 */
[431]495void shellcmd_task(intptr_t exinf)
[279]496{
[431]497 shellcmd_state = 1;
[441]498
499 if (setjmp(shellcmd_exit) == 0) {
500 shellcmd_exit_code = ntopt_parse(command, usrcmd_ntopt_callback, NULL);
501 }
502
503 //fflush(stdout);
504 clean_fd();
505
[431]506 shellcmd_state = 2;
[279]507}
508
[331]509static const cmd_table_t cmdlist[] = {
510 {"cd", "change directory", usrcmd_cd },
511 {"ls", "list files", usrcmd_ls },
512 {"cp", "copy file", usrcmd_cp },
513 {"rm", "remove file", usrcmd_rm },
514 {"mv", "move file", usrcmd_mv },
515 {"mkdir", "Make directory", usrcmd_mkdir},
516 {"hexdump", "Hex dump", usrcmd_hexdump},
[433]517 {"date", "print date and time", usrcmd_date},
[441]518#ifndef NTSHELL_NO_SOCKET
519 {"ping", "ping", usrcmd_ping},
520 {"dhcpc", "DHCP Client rel/renew/info", usrcmd_dhcp4c},
521 {"dnsc", "DNS client", usrcmd_dnsc },
522 {"ntpc", "NTP client", usrcmd_ntpc },
523#endif
[331]524 {"info", "This is a description text string for info command.", usrcmd_info},
[332]525 {"exit", "Exit Natural Tiny Shell", usrcmd_exit},
[331]526};
527cmd_table_info_t cmd_table_info = { cmdlist, sizeof(cmdlist) / sizeof(cmdlist[0]) };
528
529static int usrcmd_ntopt_callback(long *args, void *extobj)
530{
531 const cmd_table_t *p = cmd_table_info.table;
[432]532 int result = 0;
533 int found = 0;
534
535 if (*args == 0)
536 return result;
537
[442]538 if (strcmp((const char *)args[1], "help") == 0) {
[441]539 result = usrcmd_help(args[0], (char **)&args[1]);
[331]540 }
541 else for (int i = 0; i < cmd_table_info.count; i++) {
[442]542 if (strcmp((const char *)args[1], p->cmd) == 0) {
[441]543 found = 1;
544 result = p->func(args[0], (char **)&args[1]);
545 break;
[331]546 }
547 p++;
548 }
[441]549
550 if ((found == 0) && setjmp(shellcmd_exit) == 0) {
551 found = 1;
552 (*((PowerOn_Reset_t *)0x18200000))(args);
[279]553 }
[441]554
555 if ((found == 0) && (((const char *)args[1])[0] != '\0'))
[442]556 printf("Unknown command found. %s \n", (const char *)args[1]);
[441]557
558 return result;
[279]559}
560
[331]561int usrcmd_help(int argc, char **argv)
562{
563 const cmd_table_t *p = cmd_table_info.table;
564 for (int i = 0; i < cmd_table_info.count; i++) {
[442]565 printf(p->cmd);
566 printf("\t:");
567 puts(p->desc);
[331]568 p++;
569 }
570 return 0;
571}
572
[279]573void shellif_into()
574{
575 /* メインタスクの優先度より高くする */
[431]576 chg_pri(SHELLCMD_PRIORITY, MAIN_PRIORITY + 1);
[279]577}
578
579void shellif_outof()
580{
[431]581 /* shellcmdタスクの優先度に戻す */
582 chg_pri(SHELLCMD_PRIORITY, SHELLCMD_PRIORITY);
[279]583}
584
[441]585int execute_command(struct main_obj_t *obj, int wait)
[279]586{
[441]587 T_RTSK rtsk;
[279]588 ER ret;
589
[431]590 ret = ter_tsk(SHELLCMD_TASK);
[279]591 if ((ret != E_OK) && (ret != E_OBJ)) {
592 syslog(LOG_ERROR, "ter_tsk => %d", ret);
593 }
594
[441]595 if (ret == E_OK)
596 tslp_tsk(100000);
[279]597
598 clean_fd();
599
[431]600 shellcmd_state = 0;
601 ret = act_tsk(SHELLCMD_TASK);
[279]602 if (ret != E_OK) {
603 syslog(LOG_ERROR, "act_tsk => %d", ret);
604 }
605
606 if (wait == 0)
607 return 0;
608
609 do {
[441]610 obj->state = main_state_servey_cmd;
611 obj->timer = 100000;
612
613 char c;
614 if (obj->ntshell.func_read(&c, sizeof(c), obj->ntshell.extobj) == 1) {
615 // Ctrl+Cが押された場合
616 if (c == 0x03) {
617 // コマンドタスクを終了
618 ret = ter_tsk(SHELLCMD_TASK);
619 if (ret != E_OK) {
620 syslog(LOG_ERROR, "ter_tsk => %d", ret);
621 }
622 shellcmd_exit_code = -1;
623 shellcmd_state = 4;
624 if (ret == E_OK)
625 tslp_tsk(100000);
626 break;
627 }
628
629 stdio_input(c);
630 }
631
632 ret = ref_tsk(SHELLCMD_TASK, &rtsk);
633 if ((ret != E_OK) || (rtsk.tskstat == TTS_DMT))
634 shellcmd_state = 3;
[431]635 } while(shellcmd_state == 1);
[279]636
[441]637 obj->state = main_state_idle;
638 obj->timer = TMO_FEVR;
639
640 clean_fd();
641
[431]642 return shellcmd_exit_code;
[279]643}
644
Note: See TracBrowser for help on using the repository browser.