• R/O
  • HTTP
  • SSH
  • HTTPS

kz_h8write: Commit

H8/3069F writer for KOZOS - kz_h8write


Commit MetaInfo

Revisiondcdd5f05ce6e0f46fa292d6ca4e437e1745994d5 (tree)
Time2012-04-30 09:01:08
AuthorShinichiro Nakamura <shinta.main.jp@gmai...>
CommiterShinichiro Nakamura

Log Message

The argument specification changed.

Change Summary

Incremental Difference

--- a/src/Makefile
+++ b/src/Makefile
@@ -1,5 +1,5 @@
11 TARGET1=kz_h8write
2-SRCS1=kz_h8write.c serial_linux.c mot.c
2+SRCS1=kz_h8write.c serial_linux.c mot.c optparse.c
33
44 TARGET2=motdump
55 SRCS2=motdump.c mot.c
--- a/src/kz_h8write.c
+++ b/src/kz_h8write.c
@@ -39,14 +39,16 @@
3939 #include <stdlib.h>
4040 #include <stdint.h>
4141 #include "serial.h"
42-#include "kz_h8write.h"
4342 #include "mot.h"
43+#include "optparse.h"
44+#include "kz_h8write.h"
4445
4546 /**
46- * @brief デバッグモードフラグ。
47- * @details 0:デバッグモードオフ、1:デバッグモードオン。
47+ * @brief プログラム終了用マクロ。
48+ * @details このマクロはシリアルポートのオープン成功後の処理に用いる。
49+ * @param CODE シェルに返すコード番号。
4850 */
49-#define DEBUG 0
51+#define PROGEXIT(CODE) serial_close(serial); exit(CODE)
5052
5153 /**
5254 * @brief シリアルタイムアウト時間。
@@ -54,9 +56,44 @@
5456 */
5557 #define SERIAL_TIMEOUT_MS 500
5658
57-SERIAL *serial;
58-unsigned char memory_image[0x100000 + 0x100];
59-unsigned int memory_lastaddr = 0;
59+/**
60+ * @brief ユーザオプション構造体。
61+ */
62+typedef struct {
63+ char cpu_name[BUFSIZ]; /**< CPU名。 */
64+ int cpu_freq; /**< CPU周波数。 */
65+ char mot_file[BUFSIZ]; /**< MOTファイル名。NULLなら標準入力。 */
66+ char serial_port[BUFSIZ]; /**< シリアルポート名。 */
67+ int version; /**< バージョンフラグ。 */
68+ int help; /**< ヘルプフラグ。 */
69+ int debug; /**< デバッグフラグ。 */
70+ int error; /**< オプション指定エラー検出フラグ。 */
71+} user_option_t;
72+
73+#define USER_OPTION_INITIALIZER \
74+{ \
75+ .cpu_name = "\0", \
76+ .cpu_freq = 20, \
77+ .mot_file = "\0", \
78+ .serial_port = "\0", \
79+ .version = 0, \
80+ .help = 0, \
81+ .debug = 0, \
82+ .error = 0, \
83+}
84+
85+#define USER_OPTION_CPU_NAME(P) ((P)->cpu_name)
86+#define USER_OPTION_CPU_FREQ(P) ((P)->cpu_freq)
87+#define USER_OPTION_MOT_FILE(P) ((P)->mot_file)
88+#define USER_OPTION_SERIAL_PORT(P) ((P)->serial_port)
89+#define USER_OPTION_VERSION(P) ((P)->version)
90+#define USER_OPTION_HELP(P) ((P)->help)
91+#define USER_OPTION_DEBUG(P) ((P)->debug)
92+#define USER_OPTION_ERROR(P) ((P)->error)
93+
94+static SERIAL *serial;
95+static unsigned char memory_image[0x100000 + 0x100];
96+static unsigned int memory_lastaddr = 0;
6097
6198 int com_getc(void);
6299 int com_putc(unsigned char c);
@@ -553,12 +590,41 @@ enum ErrorCode program(void)
553590 return NoError;
554591 }
555592
556-/**
557- * @brief プログラム終了用マクロ。
558- * @details このマクロはシリアルポートのオープン成功後の処理に用いる。
559- * @param CODE シェルに返すコード番号。
560- */
561-#define PROGEXIT(CODE) serial_close(serial); exit(CODE)
593+int optparse_callback(const char option, const char *argument, void *extobj)
594+{
595+ user_option_t *user_option = (user_option_t *)extobj;
596+
597+ printf("option=%c, argument=%s\n", option, argument);
598+
599+ /*
600+ * USER_OPTION_MOT_FILE()とUSER_OPTION_SERIAL_PORT()は別に取得する。
601+ */
602+ switch (option) {
603+ case '3':
604+ strcpy(USER_OPTION_CPU_NAME(user_option), "3");
605+ strcat(USER_OPTION_CPU_NAME(user_option), argument);
606+ break;
607+ case 'F':
608+ case 'f':
609+ if (sscanf(argument, "%i", &USER_OPTION_CPU_FREQ(user_option)) != 1) {
610+ USER_OPTION_ERROR(user_option) = 1;
611+ }
612+ break;
613+ case 'V':
614+ case 'v':
615+ USER_OPTION_VERSION(user_option) = 1;
616+ break;
617+ case 'H':
618+ case 'h':
619+ USER_OPTION_HELP(user_option) = 1;
620+ break;
621+ case 'D':
622+ case 'd':
623+ USER_OPTION_DEBUG(user_option) = 1;
624+ break;
625+ }
626+ return 0;
627+}
562628
563629 /**
564630 * @brief エントリーポイント。
@@ -570,60 +636,101 @@ int main(int argc, char **argv)
570636 {
571637 enum ErrorCode ec;
572638 uint32_t devcode;
573- char *motfile;
574- int clock;
575- char *interface;
639+ user_option_t user_option = USER_OPTION_INITIALIZER;
576640
641+ /*
642+ * バナーを表示する。
643+ */
577644 fprintf(stderr, "=================================================\n");
578645 fprintf(stderr, " H8/3069F Flash Writer for KOZOS (Version %d.%d.%d)\n",
579646 VERSION_MAJOR,
580647 VERSION_MINOR,
581648 VERSION_RELEASE);
582- fprintf(stderr, " Copyright(C) 2011 Shinichiro Nakamura \n");
649+ fprintf(stderr, " Copyright(C) 2011-2012 Shinichiro Nakamura\n");
583650 fprintf(stderr, "=================================================\n");
584651
585- if (argc != 4) {
586- fprintf(stderr, "%s [mot file] [clock] [interface]\n", argv[0]);
652+ /*
653+ * オプションのデフォルト値を設定する。
654+ */
655+ strcpy(USER_OPTION_CPU_NAME(&user_option), "3069");
656+ USER_OPTION_CPU_FREQ(&user_option) = 20;
657+ strcpy(USER_OPTION_MOT_FILE(&user_option), "");
658+ strcpy(USER_OPTION_SERIAL_PORT(&user_option), "");
659+ USER_OPTION_VERSION(&user_option) = 0;
660+ USER_OPTION_HELP(&user_option) = 0;
661+ USER_OPTION_DEBUG(&user_option) = 0;
662+ USER_OPTION_ERROR(&user_option) = 0;
663+
664+ /*
665+ * 文字ベースでオプションを解析する。
666+ */
667+ optparse_char(argc, argv, &user_option, optparse_callback);
668+
669+ /*
670+ * オプションの指定に誤りがある場合には、使い方を表示して終了する。
671+ */
672+ if ((argc < 3) || USER_OPTION_ERROR(&user_option)
673+ || USER_OPTION_VERSION(&user_option) || USER_OPTION_HELP(&user_option)) {
674+ fprintf(stderr, "%s [options...] [mot file] [interface]\n", argv[0]);
675+ fprintf(stderr, "\n");
676+ fprintf(stderr, " Target CPU : -3069 (Default:3069)\n");
677+ fprintf(stderr, " Target Frequency : -f[20 | 25] (Default:20)\n");
678+ fprintf(stderr, " Version : -v\n");
679+ fprintf(stderr, " Help : -h\n");
680+ fprintf(stderr, " Debug : -d\n");
587681 exit(1);
588682 }
589683
590684 /*
591- * パラメータを受け取る。
685+ * 与えられた引数の最後の二つは、それぞれMOTファイルとシリアルポート名であるという仮定。
686+ */
687+ strcpy(USER_OPTION_MOT_FILE(&user_option), argv[argc - 2]);
688+ strcpy(USER_OPTION_SERIAL_PORT(&user_option), argv[argc - 1]);
689+
690+ /*
691+ * デバッグ用の出力。
692+ */
693+ if (USER_OPTION_DEBUG(&user_option)) {
694+ fprintf(stderr, "Target CPU : %s\n", USER_OPTION_CPU_NAME(&user_option));
695+ fprintf(stderr, "Target Frequency : %d\n", USER_OPTION_CPU_FREQ(&user_option));
696+ fprintf(stderr, "MOT File : %s\n", USER_OPTION_MOT_FILE(&user_option));
697+ fprintf(stderr, "Seiral Port : %s\n", USER_OPTION_SERIAL_PORT(&user_option));
698+ }
699+
700+ /*
701+ * 与えられたオプションを検証する。
592702 */
593- motfile = argv[1];
594- if (sscanf(argv[2], "%d", &clock) != 1) {
595- fprintf(stderr, "Invalid clock number found.\n");
703+ if (strcmp(USER_OPTION_CPU_NAME(&user_option), "3069") != 0) {
704+ /*
705+ * 3069F以外はエラーとする。
706+ * 3069F以外で検証するつもりは今のところないから対象外とする。
707+ * プロトコルが同じなら書き込めるだろう。
708+ */
709+ fprintf(stderr, "Unsupported CPU name found.\n");
710+ exit(1);
711+ }
712+ if ((USER_OPTION_CPU_FREQ(&user_option) != 20) && (USER_OPTION_CPU_FREQ(&user_option) != 25)) {
713+ /*
714+ * 20MHzでもなく、25MHzでもなければエラー。
715+ */
716+ fprintf(stderr, "Unsupported CPU frequency value found.\n");
596717 exit(1);
597718 }
598- interface = argv[3];
599719
600720 /*
601721 * motファイルを読み込む。
602722 */
603723 mot_t mot;
604724 mot.cb_data = mot_callback;
605- if (mot_read(motfile, &mot) != 0) {
725+ if (mot_read(USER_OPTION_MOT_FILE(&user_option), &mot) != 0) {
606726 fprintf(stderr, "file read error\n");
607727 exit(1);
608728 }
609729
610-#if (DEBUG==1)
611- /*
612- * ダンプしてチェック。
613- */
614- for (unsigned int i = 0; i < memory_lastaddr; i++) {
615- if ((i % 16) == 0) {
616- fprintf(stderr, "\n0x%04X :", i);
617- }
618- fprintf(stderr, " %02X", memory_image[i]);
619- }
620- fprintf(stderr, "\n");
621-#endif
622-
623730 /*
624731 * シリアルポートをオープンする。
625732 */
626- serial = serial_open(interface, SerialBaud19200);
733+ serial = serial_open(USER_OPTION_SERIAL_PORT(&user_option), SerialBaud19200);
627734 if (serial == NULL) {
628735 fprintf(stderr, "com port open error\n");
629736 exit(1);
@@ -653,9 +760,9 @@ int main(int argc, char **argv)
653760 * リトライした結果として成功した事を知りたい時にのみ
654761 * 表示を有効にすると良い。
655762 */
656-#if (DEBUG==1)
657- fprintf(stderr, "Bitrate sequence failed.\n");
658-#endif
763+ if (USER_OPTION_DEBUG(&user_option)) {
764+ fprintf(stderr, "Bitrate sequence failed.\n");
765+ }
659766 }
660767 }
661768 if (ec != NoError) {
@@ -707,7 +814,7 @@ int main(int argc, char **argv)
707814 /*
708815 * 新ビットレート選択を実行する。
709816 */
710- ec = select_bitrate(19200, clock);
817+ ec = select_bitrate(19200, USER_OPTION_CPU_FREQ(&user_option));
711818 if (ec != NoError) {
712819 fprintf(stderr, "Select bitrate failed. (code=0x%02x)\n", (int)ec);
713820 PROGEXIT(1);
--- a/src/mot.c
+++ b/src/mot.c
@@ -235,21 +235,34 @@ static int parse_record(mot_t *p, const char *txt)
235235
236236 /**
237237 * @brief motファイルを読み込む。
238- * @param filename ファイル名。
238+ *
239+ * @param filename ファイル名。(NULLを与えると標準入力を入力とする。)
239240 * @param p mot構造体。(コールバック関数などの情報を参照する。)
241+ *
240242 * @retval 0 成功
241243 * @retval 0以外 エラー番号。
242244 */
243245 int mot_read(const char *filename, mot_t *p)
244246 {
245247 char buf[BUFSIZ];
248+ FILE *fp = NULL;
246249
247- /*
248- * ファイルをオープンする。
249- */
250- FILE *fp = fopen(filename, "r");
251- if (fp == NULL) {
252- return -1;
250+ if (filename == NULL) {
251+ /*
252+ * 標準入力を入力用ファイルとして用いる。
253+ */
254+ fp = stdin;
255+ if (fp == NULL) {
256+ return -1;
257+ }
258+ } else {
259+ /*
260+ * ファイルをオープンする。
261+ */
262+ fp = fopen(filename, "r");
263+ if (fp == NULL) {
264+ return -1;
265+ }
253266 }
254267
255268 /*
--- a/src/mot.h
+++ b/src/mot.h
@@ -46,6 +46,15 @@ typedef struct {
4646 extern "C" {
4747 #endif
4848
49+/**
50+ * @brief motファイルを読み込む。
51+ *
52+ * @param filename ファイル名。(NULLを与えると標準入力を入力とする。)
53+ * @param p mot構造体。(コールバック関数などの情報を参照する。)
54+ *
55+ * @retval 0 成功
56+ * @retval 0以外 エラー番号。
57+ */
4958 int mot_read(const char *filename, mot_t *p);
5059
5160 #ifdef __cplusplus
--- /dev/null
+++ b/src/optparse.c
@@ -0,0 +1,159 @@
1+/**
2+ * @file optparse.c
3+ * @author Shinichiro Nakamura
4+ * @brief オプション解析モジュールの実装。
5+ */
6+
7+/*
8+ * ===============================================================
9+ * Option parse library
10+ * Version 0.0.1
11+ * ===============================================================
12+ * Copyright (c) 2012 Shinichiro Nakamura
13+ *
14+ * Permission is hereby granted, free of charge, to any person
15+ * obtaining a copy of this software and associated documentation
16+ * files (the "Software"), to deal in the Software without
17+ * restriction, including without limitation the rights to use,
18+ * copy, modify, merge, publish, distribute, sublicense, and/or
19+ * sell copies of the Software, and to permit persons to whom the
20+ * Software is furnished to do so, subject to the following
21+ * conditions:
22+ *
23+ * The above copyright notice and this permission notice shall be
24+ * included in all copies or substantial portions of the Software.
25+ *
26+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33+ * OTHER DEALINGS IN THE SOFTWARE.
34+ * ===============================================================
35+ */
36+
37+#include <string.h>
38+#include "optparse.h"
39+
40+int optparse_char(
41+ int argc,
42+ char **argv,
43+ void *extobj,
44+ int (*callback)(
45+ const char option, const char *argument, void *extobj))
46+{
47+ for (int i = 1; i < argc;) {
48+ int r = 0;
49+ int c = 0;
50+ if (argv[i][0] == '-') {
51+ /*
52+ * 与えられた文字列は引数である。
53+ */
54+ if (strlen(argv[i]) > 2) {
55+ /*
56+ * 同じ箇所にアーギュメントが指定されている。
57+ */
58+ r = callback(argv[i][1], &argv[i][2], extobj);
59+ c = 1;
60+ } else {
61+ if ((i + 1) < argc) {
62+ /*
63+ * まだ続きがありそうだ。
64+ * 先を見ておこう。
65+ */
66+ if (argv[i + 1][0] == '-') {
67+ /*
68+ * その引数にアーギュメントはない。
69+ */
70+ r = callback(argv[i][1], "", extobj);
71+ c = 1;
72+ } else {
73+ /*
74+ * その引数にアーギュメントがある。
75+ */
76+ r = callback(argv[i][1], argv[i + 1], extobj);
77+ c = 2;
78+ }
79+ } else {
80+ /*
81+ * もう先がない。
82+ * ということはアーギュメントはない。
83+ */
84+ r = callback(argv[i][1], "", extobj);
85+ c = 1;
86+ }
87+ }
88+ } else {
89+ /*
90+ * 与えられた文字列はオプションでない
91+ * 単独アーギュメントである。
92+ */
93+ r = callback('\x00', &argv[i][0], extobj);
94+ c = 1;
95+ }
96+ i += c;
97+ if (r != 0) {
98+ break;
99+ }
100+ }
101+ return 0;
102+}
103+
104+int optparse_text(
105+ int argc,
106+ char **argv,
107+ void *extobj,
108+ int (*callback)(
109+ const char *option, const char *argument, void *extobj))
110+{
111+ for (int i = 1; i < argc;) {
112+ int r = 0;
113+ int c = 0;
114+ if (argv[i][0] == '-') {
115+ /*
116+ * 与えられた文字列は引数である。
117+ */
118+ if ((i + 1) < argc) {
119+ /*
120+ * まだ続きがありそうだ。
121+ * 先を見ておこう。
122+ */
123+ if (argv[i + 1][0] == '-') {
124+ /*
125+ * その引数にアーギュメントはない。
126+ */
127+ r = callback(&argv[i][1], "", extobj);
128+ c = 1;
129+ } else {
130+ /*
131+ * その引数にアーギュメントがある。
132+ */
133+ r = callback(&argv[i][1], argv[i + 1], extobj);
134+ c = 2;
135+ }
136+ } else {
137+ /*
138+ * もう先がない。
139+ * ということはアーギュメントはない。
140+ */
141+ r = callback(&argv[i][1], "", extobj);
142+ c = 1;
143+ }
144+ } else {
145+ /*
146+ * 与えられた文字列はオプションでない
147+ * 単独アーギュメントである。
148+ */
149+ r = callback("", &argv[i][0], extobj);
150+ c = 1;
151+ }
152+ i += c;
153+ if (r != 0) {
154+ break;
155+ }
156+ }
157+ return 0;
158+}
159+
--- /dev/null
+++ b/src/optparse.h
@@ -0,0 +1,55 @@
1+/**
2+ * @file optparse.h
3+ * @author Shinichiro Nakamura
4+ * @brief オプション解析モジュールの定義。
5+ */
6+
7+/*
8+ * ===============================================================
9+ * Option parse library
10+ * Version 0.0.1
11+ * ===============================================================
12+ * Copyright (c) 2012 Shinichiro Nakamura
13+ *
14+ * Permission is hereby granted, free of charge, to any person
15+ * obtaining a copy of this software and associated documentation
16+ * files (the "Software"), to deal in the Software without
17+ * restriction, including without limitation the rights to use,
18+ * copy, modify, merge, publish, distribute, sublicense, and/or
19+ * sell copies of the Software, and to permit persons to whom the
20+ * Software is furnished to do so, subject to the following
21+ * conditions:
22+ *
23+ * The above copyright notice and this permission notice shall be
24+ * included in all copies or substantial portions of the Software.
25+ *
26+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33+ * OTHER DEALINGS IN THE SOFTWARE.
34+ * ===============================================================
35+ */
36+
37+#ifndef OPTPARSE_H
38+#define OPTPARSE_H
39+
40+int optparse_char(
41+ int argc,
42+ char **argv,
43+ void *extobj,
44+ int (*callback)(
45+ const char option, const char *argument, void *extobj));
46+
47+int optparse_text(
48+ int argc,
49+ char **argv,
50+ void *extobj,
51+ int (*callback)(
52+ const char *option, const char *argument, void *extobj));
53+
54+#endif
55+
Show on old repository browser