1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
27 #include "configuration.h"
36 #include "telnet_server.h"
37 #include "gdb_server.h"
39 #include <time_support.h>
41 #include <sys/types.h>
49 #include <cyg/io/flash.h>
50 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
55 #include <cyg/fileio/fileio.h>
57 #include <cyg/athttpd/http.h>
58 #include <cyg/athttpd/socket.h>
59 #include <cyg/athttpd/handler.h>
60 #include <cyg/athttpd/cgi.h>
61 #include <cyg/athttpd/forms.h>
62 #include <cyg/hal/hal_diag.h>
63 #include <cyg/kernel/kapi.h>
64 #include <cyg/io/serialio.h>
65 #include <cyg/io/io.h>
66 #include <netinet/tcp.h>
68 #include <sys/ioctl.h>
69 #include <sys/socket.h>
70 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
76 #include <netinet/in.h>
78 #include <arpa/inet.h>
86 #if defined(CYGPKG_NET_FREEBSD_STACK)
87 #include <tftp_support.h>
88 /* posix compatibility broken*/
89 struct tftpd_fileops fileops
=
91 (int (*)(const char *, int))open
,
93 (int (*)(int, const void *, int))write
,
94 ( int (*)(int, void *, int))read
99 #define ZYLIN_VERSION "1.45"
100 #define ZYLIN_DATE __DATE__
101 #define ZYLIN_TIME __TIME__
102 /* hmmm.... we can't pick up the right # during build if we've checked this out
103 * in Eclipse... arrggghh...*/
104 #define ZYLIN_OPENOCD "$Revision$"
105 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
106 #define ZYLIN_CONFIG_DIR "/config/settings"
108 void diag_write(char *buf
, int len
)
111 for (j
= 0; j
< len
; j
++)
113 diag_printf("%c", buf
[j
]);
117 static bool serialLog
= true;
118 static bool writeLog
= true;
129 static int fastload_num
;
130 static struct FastLoad
*fastload
;
132 static void free_fastload()
137 for (i
=0; i
<fastload_num
; i
++)
139 if (fastload
[i
].data
)
140 free(fastload
[i
].data
);
148 int handle_fast_load_image_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
154 u32 max_address
=0xffffffff;
163 if ((argc
< 1)||(argc
> 5))
165 return ERROR_COMMAND_SYNTAX_ERROR
;
168 /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
171 image
.base_address_set
= 1;
172 image
.base_address
= strtoul(args
[1], NULL
, 0);
176 image
.base_address_set
= 0;
180 image
.start_address_set
= 0;
184 min_address
=strtoul(args
[3], NULL
, 0);
188 max_address
=strtoul(args
[4], NULL
, 0)+min_address
;
191 if (min_address
>max_address
)
193 return ERROR_COMMAND_SYNTAX_ERROR
;
196 duration_start_measure(&duration
);
198 if (image_open(&image
, args
[0], (argc
>= 3) ? args
[2] : NULL
) != ERROR_OK
)
205 fastload_num
=image
.num_sections
;
206 fastload
=(struct FastLoad
*)malloc(sizeof(struct FastLoad
)*image
.num_sections
);
212 memset(fastload
, 0, sizeof(struct FastLoad
)*image
.num_sections
);
213 for (i
= 0; i
< image
.num_sections
; i
++)
215 buffer
= malloc(image
.sections
[i
].size
);
218 command_print(cmd_ctx
, "error allocating buffer for section (%d bytes)", image
.sections
[i
].size
);
222 if ((retval
= image_read_section(&image
, i
, 0x0, image
.sections
[i
].size
, buffer
, &buf_cnt
)) != ERROR_OK
)
232 /* DANGER!!! beware of unsigned comparision here!!! */
234 if ((image
.sections
[i
].base_address
+buf_cnt
>=min_address
)&&
235 (image
.sections
[i
].base_address
<max_address
))
237 if (image
.sections
[i
].base_address
<min_address
)
239 /* clip addresses below */
240 offset
+=min_address
-image
.sections
[i
].base_address
;
244 if (image
.sections
[i
].base_address
+buf_cnt
>max_address
)
246 length
-=(image
.sections
[i
].base_address
+buf_cnt
)-max_address
;
249 fastload
[i
].address
=image
.sections
[i
].base_address
+offset
;
250 fastload
[i
].data
=malloc(length
);
251 if (fastload
[i
].data
==NULL
)
256 memcpy(fastload
[i
].data
, buffer
+offset
, length
);
257 fastload
[i
].length
=length
;
259 image_size
+= length
;
260 command_print(cmd_ctx
, "%u byte written at address 0x%8.8x", length
, image
.sections
[i
].base_address
+offset
);
266 duration_stop_measure(&duration
, &duration_text
);
267 if (retval
==ERROR_OK
)
269 command_print(cmd_ctx
, "Loaded %u bytes in %s", image_size
, duration_text
);
270 command_print(cmd_ctx
, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
276 if (retval
!=ERROR_OK
)
284 int handle_fast_load_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
287 return ERROR_COMMAND_SYNTAX_ERROR
;
290 LOG_ERROR("No image in memory");
296 for (i
=0; i
<fastload_num
;i
++)
299 target_t
*target
= get_current_target(cmd_ctx
);
300 if ((retval
= target_write_buffer(target
, fastload
[i
].address
, fastload
[i
].length
, fastload
[i
].data
)) != ERROR_OK
)
304 size
+=fastload
[i
].length
;
306 int after
=timeval_ms();
307 command_print(cmd_ctx
, "Loaded image %f kBytes/s", (float)(size
/1024.0)/((float)(after
-ms
)/1000.0));
312 /* Give TELNET a way to find out what version this is */
313 int handle_zy1000_version_command(struct command_context_s
*cmd_ctx
, char *cmd
,
314 char **args
, int argc
)
318 return ERROR_COMMAND_SYNTAX_ERROR
;
322 command_print(cmd_ctx
, ZYLIN_OPENOCD_VERSION
);
323 } else if (strcmp("openocd", args
[0])==0)
326 revision
=atol(ZYLIN_OPENOCD
+strlen("XRevision: "));
327 command_print(cmd_ctx
, "%d", revision
);
328 } else if (strcmp("zy1000", args
[0])==0)
330 command_print(cmd_ctx
, "%s", ZYLIN_VERSION
);
331 } else if (strcmp("date", args
[0])==0)
333 command_print(cmd_ctx
, "%s", ZYLIN_DATE
);
336 return ERROR_COMMAND_SYNTAX_ERROR
;
342 extern flash_driver_t
*flash_drivers
[];
343 extern target_type_t
*target_types
[];
345 #ifdef CYGPKG_PROFILE_GPROF
346 #include <cyg/profile/profile.h>
348 extern char _stext
, _etext
; // Defined by the linker
350 void start_profile(void)
352 // This starts up the system-wide profiling, gathering
353 // profile information on all of the code, with a 16 byte
354 // "bucket" size, at a rate of 100us/profile hit.
355 // Note: a bucket size of 16 will give pretty good function
356 // resolution. Much smaller and the buffer becomes
357 // much too large for very little gain.
358 // Note: a timer period of 100us is also a reasonable
359 // compromise. Any smaller and the overhead of
360 // handling the timter (profile) interrupt could
361 // swamp the system. A fast processor might get
362 // by with a smaller value, but a slow one could
363 // even be swamped by this value. If the value is
364 // too large, the usefulness of the profile is reduced.
366 // no more interrupts than 1/10ms.
367 // profile_on(&_stext, &_etext, 16, 10000); // DRAM
368 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
369 profile_on(0, &_etext
, 16, 10000); // SRAM & DRAM
373 // launch GDB server if a config file exists
374 bool zylinjtag_parse_config_file(struct command_context_s
*cmd_ctx
, const char *config_file_name
)
376 bool foundFile
= false;
377 FILE *config_file
= NULL
;
378 command_print(cmd_ctx
, "executing config file %s", config_file_name
);
379 config_file
= fopen(config_file_name
, "r");
384 retval
= command_run_linef(cmd_ctx
, "script %s", config_file_name
);
385 if (retval
== ERROR_OK
)
391 command_print(cmd_ctx
, "Failed executing %s %d", config_file_name
, retval
);
396 command_print(cmd_ctx
, "No %s found", config_file_name
);
405 static char reboot_stack
[2048];
409 zylinjtag_reboot(cyg_addrword_t data
)
412 diag_printf("Rebooting in 100 ticks..\n");
413 cyg_thread_delay(100);
414 diag_printf("Unmounting /config..\n");
416 diag_printf("Rebooting..\n");
417 HAL_PLATFORM_RESET();
419 static cyg_thread zylinjtag_thread_object
;
420 static cyg_handle_t zylinjtag_thread_handle
;
428 (void *)reboot_stack
,
429 sizeof(reboot_stack
),
430 &zylinjtag_thread_handle
,
431 &zylinjtag_thread_object
);
432 cyg_thread_resume(zylinjtag_thread_handle
);
435 int configuration_output_handler(struct command_context_s
*context
, const char* line
)
437 diag_printf("%s", line
);
442 int zy1000_configuration_output_handler_log(struct command_context_s
*context
, const char* line
)
444 LOG_USER_N("%s", line
);
449 int handle_rm_command(struct command_context_s
*cmd_ctx
, char *cmd
,
450 char **args
, int argc
)
454 command_print(cmd_ctx
, "rm <filename>");
455 return ERROR_INVALID_ARGUMENTS
;
458 if (unlink(args
[0]) != 0)
460 command_print(cmd_ctx
, "failed: %d", errno
);
466 int loadFile(const char *fileName
, void **data
, int *len
);
468 int handle_cat_command(struct command_context_s
*cmd_ctx
, char *cmd
,
469 char **args
, int argc
)
473 command_print(cmd_ctx
, "cat <filename>");
474 return ERROR_INVALID_ARGUMENTS
;
477 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
481 int retval
= loadFile(args
[0], &data
, &len
);
482 if (retval
== ERROR_OK
)
484 command_print(cmd_ctx
, "%s", data
);
489 command_print(cmd_ctx
, "%s not found %d", args
[0], retval
);
494 int handle_trunc_command(struct command_context_s
*cmd_ctx
, char *cmd
,
495 char **args
, int argc
)
499 command_print(cmd_ctx
, "trunc <filename>");
500 return ERROR_INVALID_ARGUMENTS
;
503 FILE *config_file
= NULL
;
504 config_file
= fopen(args
[0], "w");
505 if (config_file
!= NULL
)
512 int handle_meminfo_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
515 struct mallinfo info
;
519 command_print(cmd_ctx
, "meminfo");
520 return ERROR_INVALID_ARGUMENTS
;
527 command_print(cmd_ctx
, "Diff: %d", prev
- info
.fordblks
);
529 prev
= info
.fordblks
;
531 command_print(cmd_ctx
, "Available ram: %d", info
.fordblks
);
536 static bool savePower
;
538 static void setPower(bool power
)
543 HAL_WRITE_UINT32(0x08000014, 0x8);
546 HAL_WRITE_UINT32(0x08000010, 0x8);
550 int handle_power_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
554 return ERROR_INVALID_ARGUMENTS
;
559 if (strcmp(args
[0], "on") == 0)
563 else if (strcmp(args
[0], "off") == 0)
568 command_print(cmd_ctx
, "arg is \"on\" or \"off\"");
569 return ERROR_INVALID_ARGUMENTS
;
573 command_print(cmd_ctx
, "Target power %s", savePower
? "on" : "off");
578 int handle_append_command(struct command_context_s
*cmd_ctx
, char *cmd
,
579 char **args
, int argc
)
583 command_print(cmd_ctx
,
584 "append <filename> [<string1>, [<string2>, ...]]");
585 return ERROR_INVALID_ARGUMENTS
;
588 FILE *config_file
= NULL
;
589 config_file
= fopen(args
[0], "a");
590 if (config_file
!= NULL
)
593 fseek(config_file
, 0, SEEK_END
);
595 for (i
= 1; i
< argc
; i
++)
597 fwrite(args
[i
], strlen(args
[i
]), 1, config_file
);
600 fwrite(" ", 1, 1, config_file
);
603 fwrite("\n", 1, 1, config_file
);
610 extern int telnet_socket
;
612 int readMore(int fd
, void *data
, int length
)
614 /* used in select() */
617 /* monitor sockets for acitvity */
620 /* listen for new connections */
621 FD_SET(fd
, &read_fds
);
623 // Maximum 5 seconds.
628 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, &tv
);
631 diag_printf("Timed out waiting for binary payload\n");
637 return read_socket(fd
, data
, length
);
640 int readAll(int fd
, void *data
, int length
)
645 int actual
= readMore(fd
, ((char *) data
) + pos
, length
- pos
);
646 // diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
656 int handle_peek_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
661 return ERROR_INVALID_ARGUMENTS
;
663 HAL_READ_UINT32(strtoul(args
[0], NULL
, 0), value
);
664 command_print(cmd_ctx
, "0x%x : 0x%x", strtoul(args
[0], NULL
, 0), value
);
668 int handle_poke_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
672 return ERROR_INVALID_ARGUMENTS
;
674 HAL_WRITE_UINT32(strtoul(args
[0], NULL
, 0), strtoul(args
[1], NULL
, 0));
678 int handle_cp_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
682 return ERROR_INVALID_ARGUMENTS
;
685 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
689 int retval
= loadFile(args
[0], &data
, &len
);
690 if (retval
!= ERROR_OK
)
693 FILE *f
= fopen(args
[1], "wb");
695 retval
= ERROR_INVALID_ARGUMENTS
;
700 int chunk
= len
- pos
;
701 static const int maxChunk
= 512 * 1024; // ~1/sec
702 if (chunk
> maxChunk
)
707 if ((retval
==ERROR_OK
)&&(fwrite(((char *)data
)+pos
, 1, chunk
, f
)!=chunk
))
708 retval
= ERROR_INVALID_ARGUMENTS
;
710 if (retval
!= ERROR_OK
)
715 command_print(cmd_ctx
, "%d", len
- pos
);
723 if (retval
== ERROR_OK
)
725 command_print(cmd_ctx
, "Copied %s to %s", args
[0], args
[1]);
728 command_print(cmd_ctx
, "Failed: %d", retval
);
736 if (retval
!= ERROR_OK
)
742 #ifdef CYGPKG_PROFILE_GPROF
743 extern void start_profile();
745 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
747 command_print(cmd_ctx
, "Profiling started");
754 externC
void phi_init_all_network_interfaces();
756 command_context_t
*cmd_ctx
;
758 static bool webRunning
= false;
760 void keep_webserver()
762 // Target initialisation is only attempted at startup, so we sleep forever and
763 // let the http server bail us out(i.e. get config files set up).
764 diag_printf("OpenOCD has invoked exit().\n"
765 "Use web server to correct any configuration settings and reboot.\n");
769 // exit() will terminate the current thread and we we'll then sleep eternally or
770 // we'll have a reboot scheduled.
773 extern void printDccChar(char c
);
775 static char logBuffer
[128 * 1024];
776 static const int logSize
= sizeof(logBuffer
);
780 void _zylinjtag_diag_write_char(char c
, void **param
)
784 logBuffer
[writePtr
] = c
;
785 writePtr
= (writePtr
+ 1) % logSize
;
792 HAL_DIAG_WRITE_CHAR('\r');
794 HAL_DIAG_WRITE_CHAR(c
);
800 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
803 static void copyfile(char *name2
, char *name1
)
811 fd1
= open(name1
, O_WRONLY
| O_CREAT
);
813 SHOW_RESULT( open
, fd1
);
815 fd2
= open(name2
, O_RDONLY
);
817 SHOW_RESULT( open
, fd2
);
821 done
= read(fd2
, buf
, IOSIZE
);
824 SHOW_RESULT( read
, done
);
828 if( done
== 0 ) break;
830 wrote
= write(fd1
, buf
, done
);
831 if( wrote
!= done
) SHOW_RESULT( write
, wrote
);
833 if( wrote
!= done
) break;
837 if( err
< 0 ) SHOW_RESULT( close
, err
);
840 if( err
< 0 ) SHOW_RESULT( close
, err
);
843 static void copydir(char *name
, char *destdir
)
848 dirp
= opendir(destdir
);
851 mkdir(destdir
, 0777);
854 err
= closedir(dirp
);
857 dirp
= opendir(name
);
858 if( dirp
== NULL
) SHOW_RESULT( opendir
, -1 );
862 struct dirent
*entry
= readdir(dirp
);
867 if (strcmp(entry
->d_name
, ".") == 0)
869 if (strcmp(entry
->d_name
, "..") == 0)
874 char fullPath
[PATH_MAX
];
875 strncpy(fullPath
, name
, PATH_MAX
);
876 strcat(fullPath
, "/");
877 strncat(fullPath
, entry
->d_name
, PATH_MAX
- strlen(fullPath
));
879 if (stat(fullPath
, &buf
) == -1)
881 diag_printf("unable to read status from %s", fullPath
);
884 isDir
= S_ISDIR(buf
.st_mode
) != 0;
889 // diag_printf("<INFO>: entry %14s",entry->d_name);
890 char fullname
[PATH_MAX
];
891 char fullname2
[PATH_MAX
];
893 strcpy(fullname
, name
);
894 strcat(fullname
, "/");
895 strcat(fullname
, entry
->d_name
);
897 strcpy(fullname2
, destdir
);
898 strcat(fullname2
, "/");
899 strcat(fullname2
, entry
->d_name
);
900 // diag_printf("from %s to %s\n", fullname, fullname2);
901 copyfile(fullname
, fullname2
);
903 // diag_printf("\n");
906 err
= closedir(dirp
);
907 if( err
< 0 ) SHOW_RESULT( stat
, err
);
911 MTAB_ENTRY( romfs_mte1
,
915 (CYG_ADDRWORD
) &filedata
[0] );
918 void openocd_sleep_prelude()
920 cyg_mutex_unlock(&httpstate
.jim_lock
);
923 void openocd_sleep_postlude()
925 cyg_mutex_lock(&httpstate
.jim_lock
);
929 zylinjtag_Jim_Command_rm(Jim_Interp
*interp
,
931 Jim_Obj
* const *argv
)
936 Jim_WrongNumArgs(interp
, 1, argv
, "rm ?dirorfile?");
941 if (unlink(Jim_GetString(argv
[1], NULL
)) == 0)
943 if (rmdir(Jim_GetString(argv
[1], NULL
)) == 0)
946 return del
? JIM_OK
: JIM_ERR
;
949 static int zylinjtag_Jim_Command_threads(Jim_Interp
*interp
, int argc
,
950 Jim_Obj
* const *argv
)
952 cyg_handle_t thread
= 0;
954 Jim_Obj
*threads
= Jim_NewListObj(interp
, NULL
, 0);
956 /* Loop over the threads, and generate a table row for
959 while (cyg_thread_get_next(&thread
, &id
))
961 Jim_Obj
*threadObj
= Jim_NewListObj(interp
, NULL
, 0);
963 cyg_thread_info info
;
966 cyg_thread_get_info(thread
, id
, &info
);
968 if (info
.name
== NULL
)
969 info
.name
= "<no name>";
971 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
972 info
.name
, strlen(info
.name
)));
974 /* Translate the state into a string.
977 state_string
= "RUN";
978 else if (info
.state
& 0x04)
979 state_string
= "SUSP";
981 switch (info
.state
& 0x1b)
984 state_string
= "SLEEP";
987 state_string
= "CNTSLEEP";
990 state_string
= "CREATE";
993 state_string
= "EXIT";
996 state_string
= "????";
1000 Jim_ListAppendElement(interp
, threadObj
, Jim_NewStringObj(interp
,
1001 state_string
, strlen(state_string
)));
1003 Jim_ListAppendElement (interp
, threadObj
, Jim_NewIntObj(interp
, id
));
1004 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.set_pri
));
1005 Jim_ListAppendElement(interp
, threadObj
, Jim_NewIntObj(interp
, info
.cur_pri
));
1007 Jim_ListAppendElement(interp
, threads
, threadObj
);
1009 Jim_SetResult( interp
, threads
);
1016 zylinjtag_Jim_Command_ls(Jim_Interp
*interp
,
1018 Jim_Obj
* const *argv
)
1022 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1026 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
1029 dirp
= opendir(name
);
1034 Jim_Obj
*objPtr
= Jim_NewListObj(interp
, NULL
, 0);
1038 struct dirent
*entry
= NULL
;
1039 entry
= readdir(dirp
);
1043 if ((strcmp(".", entry
->d_name
)==0)||(strcmp("..", entry
->d_name
)==0))
1046 Jim_ListAppendElement(interp
, objPtr
, Jim_NewStringObj(interp
, entry
->d_name
, strlen(entry
->d_name
)));
1050 Jim_SetResult(interp
, objPtr
);
1057 zylinjtag_Jim_Command_getmem(Jim_Interp
*interp
,
1059 Jim_Obj
* const *argv
)
1063 Jim_WrongNumArgs(interp
, 1, argv
, "ls ?dir?");
1069 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1071 if (Jim_GetLong(interp
, argv
[2], &length
) != JIM_OK
)
1074 if (length
< 0 && length
> (4096 * 1024))
1076 Jim_WrongNumArgs(interp
, 1, argv
, "getmem ?dir?");
1080 void *mem
= malloc(length
);
1084 target_t
*target
= get_current_target(cmd_ctx
);
1089 if ((address
% 4 == 0) && (count
% 4 == 0))
1095 if ((retval
= target
->type
->read_memory(target
, address
, size
, count
, mem
)) != ERROR_OK
)
1101 Jim_Obj
*objPtr
= Jim_NewStringObj(interp
, mem
, length
);
1102 Jim_SetResult(interp
, objPtr
);
1110 zylinjtag_Jim_Command_peek(Jim_Interp
*interp
,
1112 Jim_Obj
* const *argv
)
1116 Jim_WrongNumArgs(interp
, 1, argv
, "peek ?address?");
1121 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1124 int value
= *((volatile int *) address
);
1126 Jim_SetResult(interp
, Jim_NewIntObj(interp
, value
));
1132 zylinjtag_Jim_Command_poke(Jim_Interp
*interp
,
1134 Jim_Obj
* const *argv
)
1138 Jim_WrongNumArgs(interp
, 1, argv
, "poke ?address? ?value?");
1143 if (Jim_GetLong(interp
, argv
[1], &address
) != JIM_OK
)
1146 if (Jim_GetLong(interp
, argv
[2], &value
) != JIM_OK
)
1149 *((volatile int *) address
) = value
;
1157 zylinjtag_Jim_Command_flash(Jim_Interp
*interp
,
1159 Jim_Obj
* const *argv
)
1163 flash_bank_t
*t
= get_flash_bank_by_num_noprobe(0);
1173 if (retval
== JIM_OK
)
1175 Jim_SetResult(interp
, Jim_NewIntObj(interp
, base
));
1186 zylinjtag_Jim_Command_log(Jim_Interp
*interp
,
1188 Jim_Obj
* const *argv
)
1190 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1192 if (logCount
>= logSize
)
1194 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
1196 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, logBuffer
, writePtr
);
1198 Jim_SetResult(interp
, tclOutput
);
1203 zylinjtag_Jim_Command_reboot(Jim_Interp
*interp
,
1205 Jim_Obj
* const *argv
)
1212 zylinjtag_Jim_Command_mac(Jim_Interp
*interp
,
1214 Jim_Obj
* const *argv
)
1218 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
1221 strcpy(ifr
.ifr_name
, "eth0");
1223 res
= ioctl(s
, SIOCGIFHWADDR
, &ifr
);
1232 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1235 sprintf(hwaddr
, "%02x:%02x:%02x:%02x:%02x:%02x",
1236 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[0],
1237 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[1],
1238 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[2],
1239 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[3],
1240 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[4],
1241 (int) ((unsigned char *) &ifr
.ifr_hwaddr
.sa_data
)[5]);
1243 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, hwaddr
, strlen(hwaddr
));
1245 Jim_SetResult(interp
, tclOutput
);
1251 zylinjtag_Jim_Command_ip(Jim_Interp
*interp
,
1253 Jim_Obj
* const *argv
)
1255 Jim_Obj
*tclOutput
= Jim_NewStringObj(interp
, "", 0);
1257 struct ifaddrs
*ifa
= NULL
, *ifp
= NULL
;
1259 if (getifaddrs(&ifp
) < 0)
1264 for (ifa
= ifp
; ifa
; ifa
= ifa
->ifa_next
)
1269 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
1270 salen
= sizeof(struct sockaddr_in
);
1271 else if (ifa
->ifa_addr
->sa_family
== AF_INET6
)
1272 salen
= sizeof(struct sockaddr_in6
);
1276 if (getnameinfo(ifa
->ifa_addr
, salen
, ip
, sizeof(ip
), NULL
, 0,
1277 NI_NUMERICHOST
) < 0)
1282 Jim_AppendString(httpstate
.jim_interp
, tclOutput
, ip
, strlen(ip
));
1289 Jim_SetResult(interp
, tclOutput
);
1294 extern Jim_Interp
*interp
;
1296 static void zylinjtag_startNetwork()
1298 // Bring TCP/IP up immediately before we're ready to accept commands.
1300 // That is as soon as a PING responds, we're accepting telnet sessions.
1301 #if defined(CYGPKG_NET_FREEBSD_STACK)
1302 phi_init_all_network_interfaces();
1308 diag_printf("Network not up and running\n");
1311 #if defined(CYGPKG_NET_FREEBSD_STACK)
1313 tftpd_start(69, &fileops
);
1316 cyg_httpd_init_tcl_interpreter();
1318 interp
= httpstate
.jim_interp
;
1320 Jim_CreateCommand(httpstate
.jim_interp
, "log", zylinjtag_Jim_Command_log
, NULL
, NULL
);
1321 Jim_CreateCommand(httpstate
.jim_interp
, "reboot", zylinjtag_Jim_Command_reboot
, NULL
, NULL
);
1322 Jim_CreateCommand(httpstate
.jim_interp
, "peek", zylinjtag_Jim_Command_peek
, NULL
, NULL
);
1323 Jim_CreateCommand(httpstate
.jim_interp
, "zy1000_flash", zylinjtag_Jim_Command_flash
, NULL
, NULL
);
1324 Jim_CreateCommand(httpstate
.jim_interp
, "poke", zylinjtag_Jim_Command_poke
, NULL
, NULL
);
1325 Jim_CreateCommand(httpstate
.jim_interp
, "ls", zylinjtag_Jim_Command_ls
, NULL
, NULL
);
1326 Jim_CreateCommand(httpstate
.jim_interp
, "threads", zylinjtag_Jim_Command_threads
, NULL
, NULL
);
1327 Jim_CreateCommand(httpstate
.jim_interp
, "getmem", zylinjtag_Jim_Command_getmem
, NULL
, NULL
);
1328 Jim_CreateCommand(httpstate
.jim_interp
, "mac", zylinjtag_Jim_Command_mac
, NULL
, NULL
);
1329 Jim_CreateCommand(httpstate
.jim_interp
, "ip", zylinjtag_Jim_Command_ip
, NULL
, NULL
);
1330 Jim_CreateCommand(httpstate
.jim_interp
, "rm", zylinjtag_Jim_Command_rm
, NULL
, NULL
);
1336 diag_printf("Web server running\n");
1339 static bool readPowerDropout()
1342 // sample and clear power dropout
1343 HAL_WRITE_UINT32(0x08000010, 0x80);
1344 HAL_READ_UINT32(0x08000010, state
);
1346 powerDropout
= (state
& 0x80) != 0;
1347 return powerDropout
;
1353 // sample and clear SRST sensing
1354 HAL_WRITE_UINT32(0x08000010, 0x00000040);
1355 HAL_READ_UINT32(0x08000010, state
);
1357 srstAsserted
= (state
& 0x40) != 0;
1358 return srstAsserted
;
1361 // every 300ms we check for reset & powerdropout and issue a "reset halt" if
1365 static int sense_handler(void *priv
)
1367 struct command_context_s
*cmd_ctx
;
1368 cmd_ctx
= (struct command_context_s
*) priv
;
1370 static bool prevSrstAsserted
= false;
1371 static bool prevPowerdropout
= false;
1374 powerDropout
= readPowerDropout();
1377 powerRestored
= prevPowerdropout
&& !powerDropout
;
1380 LOG_USER("Sensed power restore.");
1383 cyg_tick_count_t current
= cyg_current_time();
1384 static cyg_tick_count_t lastPower
= 0;
1385 bool waitMore
= lastPower
+ 200 > current
;
1386 if (powerDropout
&& !waitMore
)
1388 LOG_USER("Sensed power dropout.");
1389 lastPower
= current
;
1392 bool srstAsserted
= readSRST();
1394 bool srstDeasserted
;
1395 srstDeasserted
= prevSrstAsserted
&& !srstAsserted
;
1397 static cyg_tick_count_t lastSrst
= 0;
1398 waitMore
= lastSrst
+ 200 > current
;
1399 if (srstDeasserted
&& !waitMore
)
1401 LOG_USER("Sensed nSRST deasserted");
1405 if (!prevSrstAsserted
&& srstAsserted
)
1407 LOG_USER("Sensed nSRST asserted");
1410 prevSrstAsserted
= srstAsserted
;
1411 prevPowerdropout
= powerDropout
;
1413 if (srstDeasserted
|| powerRestored
)
1415 /* Other than logging the event we can't do anything here.
1416 * Issuing a reset is a particularly bad idea as we might
1417 * be inside a reset already.
1427 print_exception_handler(cyg_addrword_t data
, cyg_code_t exception
, cyg_addrword_t info
)
1431 char *infoStr
= "unknown";
1434 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
:
1435 infoStr
= "undefined instruction";
1437 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT
:
1438 infoStr
= "software interrupt";
1440 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH
:
1441 infoStr
= "abort prefetch";
1443 case CYGNUM_HAL_VECTOR_ABORT_DATA
:
1444 infoStr
= "abort data";
1450 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1452 diag_printf("Dumping log\n---\n");
1453 if (logCount
>= logSize
)
1455 diag_write(logBuffer
+ logCount
% logSize
, logSize
- logCount
% logSize
);
1457 diag_write(logBuffer
, writePtr
);
1459 diag_printf("---\nLogdump complete.\n");
1460 diag_printf("Exception: %08x(%s) %08x\n", exception
, infoStr
, info
);
1461 diag_printf("\n---\nRebooting\n");
1462 HAL_PLATFORM_RESET();
1466 static void setHandler(cyg_code_t exception
)
1468 cyg_exception_handler_t
*old_handler
;
1469 cyg_addrword_t old_data
;
1471 cyg_exception_set_handler(exception
,
1472 print_exception_handler
,
1478 static cyg_thread zylinjtag_uart_thread_object
;
1479 static cyg_handle_t zylinjtag_uart_thread_handle
;
1480 static char uart_stack
[4096];
1482 static char forwardBuffer
[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1483 static char backwardBuffer
[1024];
1485 static cyg_io_handle_t serial_handle
;
1487 void setNoDelay(int session
, int flag
)
1490 // This decreases latency dramatically for e.g. GDB load which
1491 // does not have a sliding window protocol
1493 // Can cause *lots* of TCP/IP packets to be sent and it would have
1494 // to be enabled/disabled on the fly to avoid the CPU being
1496 setsockopt(session
, /* socket affected */
1497 IPPROTO_TCP
, /* set option at TCP level */
1498 TCP_NODELAY
, /* name of option */
1499 (char *) &flag
, /* the cast is historical
1501 sizeof(int)); /* length of option value */
1511 } tcpipSent
[512 * 1024];
1515 zylinjtag_uart(cyg_addrword_t data
)
1517 int so_reuseaddr_option
= 1;
1520 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1)
1522 LOG_ERROR("error creating socket: %s", strerror(errno
));
1526 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&so_reuseaddr_option
, sizeof(int));
1528 struct sockaddr_in sin
;
1529 unsigned int address_size
;
1530 address_size
= sizeof(sin
);
1531 memset(&sin
, 0, sizeof(sin
));
1532 sin
.sin_family
= AF_INET
;
1533 sin
.sin_addr
.s_addr
= INADDR_ANY
;
1534 sin
.sin_port
= htons(5555);
1536 if (bind(fd
, (struct sockaddr
*) &sin
, sizeof(sin
)) == -1)
1538 LOG_ERROR("couldn't bind to socket: %s", strerror(errno
));
1542 if (listen(fd
, 1) == -1)
1544 LOG_ERROR("couldn't listen on socket: %s", strerror(errno
));
1547 // socket_nonblock(fd);
1552 int session
= accept(fd
, (struct sockaddr
*) &sin
, &address_size
);
1558 setNoDelay(session
, 1);
1559 int oldopts
= fcntl(session
, F_GETFL
, 0);
1560 fcntl(session
, F_SETFL
, oldopts
| O_NONBLOCK
); //
1562 int serHandle
= open("/dev/ser0", O_RDWR
| O_NONBLOCK
);
1580 FD_ZERO(&write_fds
);
1583 FD_SET(session
, &read_fds
);
1585 FD_SET(serHandle
, &read_fds
);
1586 if (serHandle
> fd_max
)
1592 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1593 if ((actual
== 0) && (actual2
== 0))
1595 int retval
= select(fd_max
+ 1, &read_fds
, NULL
, NULL
, NULL
);
1604 memset(backwardBuffer
, 's', sizeof(backwardBuffer
));
1605 actual2
=read(serHandle
, backwardBuffer
, sizeof(backwardBuffer
));
1608 if (errno
!= EAGAIN
)
1621 int written
= write(session
, backwardBuffer
+ pos2
, actual2
);
1629 if (FD_ISSET(session
, &read_fds
)&&(sizeof(forwardBuffer
)>actual
))
1631 // NB! Here it is important that we empty the TCP/IP read buffer
1632 // to make transmission tick right
1633 memmove(forwardBuffer
, forwardBuffer
+ pos
, actual
);
1636 // this will block if there is no data at all
1637 t
=read_socket(session
, forwardBuffer
+actual
, sizeof(forwardBuffer
)-actual
);
1649 /* Do not put things into the serial buffer if it has something to send
1650 * as that can cause a single byte to be sent at the time.
1654 int written
= write(serHandle
, forwardBuffer
+ pos
, actual
);
1657 if (errno
!= EAGAIN
)
1661 // The serial buffer is full
1672 tcpipSent
[cur
].req
= x
;
1673 tcpipSent
[cur
].actual
= y
;
1674 tcpipSent
[cur
].req2
= x2
;
1675 tcpipSent
[cur
].actual2
= y2
;
1685 for (i
= 0; i
< 1024; i
++)
1687 diag_printf("%d %d %d %d\n", tcpipSent
[i
].req
, tcpipSent
[i
].actual
, tcpipSent
[i
].req2
, tcpipSent
[i
].actual2
);
1695 void startUart(void)
1697 cyg_thread_create(1,
1703 &zylinjtag_uart_thread_handle
,
1704 &zylinjtag_uart_thread_object
);
1705 cyg_thread_set_priority(zylinjtag_uart_thread_handle
, 1); // low priority as it sits in a busy loop
1706 cyg_thread_resume(zylinjtag_uart_thread_handle
);
1711 int handle_uart_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1715 command_print(cmd_ctx
, "usage: uart <baudrate>");
1716 return ERROR_INVALID_ARGUMENTS
;
1719 int baud
= atol(args
[0]);
1724 baud
= CYGNUM_SERIAL_BAUD_9600
;
1727 baud
= CYGNUM_SERIAL_BAUD_19200
;
1730 baud
= CYGNUM_SERIAL_BAUD_38400
;
1733 baud
= CYGNUM_SERIAL_BAUD_57600
;
1736 baud
= CYGNUM_SERIAL_BAUD_115200
;
1739 baud
= CYGNUM_SERIAL_BAUD_230400
;
1742 command_print(cmd_ctx
, "unsupported baudrate");
1743 return ERROR_INVALID_ARGUMENTS
;
1746 cyg_serial_info_t buf
;
1748 //get existing serial configuration
1749 len
= sizeof(cyg_serial_info_t
);
1751 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN
, &buf
, &len
);
1752 err
= cyg_io_get_config(serial_handle
, CYG_IO_GET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1755 command_print(cmd_ctx
, "Failed to get serial port settings %d", err
);
1760 err
= cyg_io_set_config(serial_handle
, CYG_IO_SET_CONFIG_SERIAL_INFO
, &buf
, &len
);
1763 command_print(cmd_ctx
, "Failed to set serial port settings %d", err
);
1770 bool logAllToSerial
= false;
1772 /* boolean parameter stored on config */
1773 bool boolParam(char *var
)
1775 bool result
= false;
1776 char *name
= alloc_printf(ZYLIN_CONFIG_DIR
"/%s", var
);
1782 if (loadFile(name
, &data
, &len
) == ERROR_OK
)
1786 result
= strncmp((char *) data
, "1", len
) == 0;
1793 command_context_t
*setup_command_handler();
1795 int add_default_dirs(void)
1797 add_script_search_dir(ZYLIN_CONFIG_DIR
);
1798 add_script_search_dir("/rom/lib/openocd");
1799 add_script_search_dir("/rom");
1803 static cyg_uint8
*ramblockdevice
;
1804 static const int ramblockdevice_size
=4096*1024;
1805 int main(int argc
, char *argv
[])
1807 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1808 * need to allocate towards the end of the heap. */
1810 ramblockdevice
=(cyg_uint8
*)malloc(ramblockdevice_size
);
1811 memset(ramblockdevice
, 0xff, ramblockdevice_size
);
1813 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
);
1814 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH
);
1815 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA
);
1818 err
= cyg_io_lookup("/dev/ser0", &serial_handle
);
1821 diag_printf("/dev/ser0 not found\n");
1825 setPower(true); // on by default
1827 atexit(keep_webserver
);
1829 err
= mount("", "/ram", "ramfs");
1832 diag_printf("unable to mount ramfs\n");
1837 sprintf(address
, "%p", &filedata
[0]);
1838 err
= mount(address
, "/rom", "romfs");
1841 diag_printf("unable to mount /rom\n");
1844 err
= mount("", "/log", "logfs");
1847 diag_printf("unable to mount logfs\n");
1850 err
= mount("", "/tftp", "tftpfs");
1853 diag_printf("unable to mount logfs\n");
1856 log
= fopen("/log/log", "w");
1859 diag_printf("Could not open log file /ram/log\n");
1863 diag_init_putc(_zylinjtag_diag_write_char
);
1865 // We want this in the log.
1866 diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1867 diag_printf("%s\n", ZYLIN_OPENOCD_VERSION
);
1869 copydir("/rom", "/ram/cgi");
1871 err
= mount("/dev/flash1", "/config", "jffs2");
1874 diag_printf("unable to mount jffs\n");
1878 /* are we using a ram disk instead of a flash disk? This is used
1879 * for ZY1000 live demo...
1881 * copy over flash disk to ram block device
1883 if (boolParam("ramdisk"))
1885 diag_printf("Unmounting /config from flash and using ram instead\n");
1886 err
=umount("/config");
1889 diag_printf("unable to unmount jffs\n");
1893 err
= mount("/dev/flash1", "/config2", "jffs2");
1896 diag_printf("unable to mount jffs\n");
1900 err
= mount("/dev/ram", "/config", "jffs2");
1903 diag_printf("unable to mount ram block device\n");
1907 // copydir("/config2", "/config");
1908 copyfile("/config2/ip", "/config/ip");
1909 copydir("/config2/settings", "/config/settings");
1914 /* we're not going to use a ram block disk */
1915 free(ramblockdevice
);
1919 mkdir(ZYLIN_CONFIG_DIR
, 0777);
1920 mkdir(ZYLIN_CONFIG_DIR
"/target", 0777);
1921 mkdir(ZYLIN_CONFIG_DIR
"/event", 0777);
1923 logAllToSerial
= boolParam("logserial");
1925 // We need the network & web server in case there is something wrong with
1926 // the config files that invoke exit()
1927 zylinjtag_startNetwork();
1929 /* we're going to access the jim interpreter from here on... */
1930 openocd_sleep_postlude();
1935 /* initialize commandline interface */
1936 command_context_t
*cmd_ctx
;
1937 cmd_ctx
= setup_command_handler();
1938 command_set_output_handler(cmd_ctx
, configuration_output_handler
, NULL
);
1939 command_context_mode(cmd_ctx
, COMMAND_CONFIG
);
1942 register_command(cmd_ctx
, NULL
, "zy1000_version", handle_zy1000_version_command
,
1943 COMMAND_EXEC
, "show zy1000 version numbers");
1945 register_command(cmd_ctx
, NULL
, "rm", handle_rm_command
, COMMAND_ANY
,
1948 register_command(cmd_ctx
, NULL
, "fast_load_image", handle_fast_load_image_command
, COMMAND_ANY
,
1949 "same args as load_image, image stored in memory");
1951 register_command(cmd_ctx
, NULL
, "fast_load", handle_fast_load_command
, COMMAND_ANY
,
1952 "loads active fast load image to current target");
1954 register_command(cmd_ctx
, NULL
, "cat", handle_cat_command
, COMMAND_ANY
,
1955 "display file content");
1957 register_command(cmd_ctx
, NULL
, "trunc", handle_trunc_command
, COMMAND_ANY
,
1958 "truncate a file to 0 size");
1960 register_command(cmd_ctx
, NULL
, "append_file", handle_append_command
,
1961 COMMAND_ANY
, "append a variable number of strings to a file");
1963 register_command(cmd_ctx
, NULL
, "power", handle_power_command
, COMMAND_ANY
,
1964 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1966 register_command(cmd_ctx
, NULL
, "meminfo", handle_meminfo_command
,
1967 COMMAND_ANY
, "display available ram memory");
1969 register_command(cmd_ctx
, NULL
, "cp", handle_cp_command
,
1970 COMMAND_ANY
, "copy a file <from> <to>");
1972 #ifdef CYGPKG_PROFILE_GPROF
1973 register_command(cmd_ctx
, NULL
, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command
,
1976 register_command(cmd_ctx
, NULL
, "uart", handle_uart_command
,
1977 COMMAND_ANY
, "uart <baud> - forward uart on port 5555");
1981 errVal
= log_init(cmd_ctx
);
1982 if (errVal
!= ERROR_OK
)
1984 diag_printf("log_init() failed %d\n", errVal
);
1988 set_log_output(cmd_ctx
, log
);
1990 LOG_DEBUG("log init complete");
1992 // diag_printf("Executing config files\n");
1996 diag_printf(ZYLIN_CONFIG_DIR
"/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1997 command_run_line(cmd_ctx
, "debug_level 3");
2000 zylinjtag_parse_config_file(cmd_ctx
, "/rom/openocd.cfg");
2002 target_register_timer_callback(sense_handler
, 200, 1, cmd_ctx
);
2005 // diag_printf() is really invoked from many more places than we trust it
2006 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
2008 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
2009 // fingers that it doesn't cause any crashes.
2010 diag_printf("Init complete, GDB & telnet servers launched.\n");
2011 command_set_output_handler(cmd_ctx
, zy1000_configuration_output_handler_log
, NULL
);
2012 if (!logAllToSerial
)
2017 /* handle network connections */
2018 server_loop(cmd_ctx
);
2019 openocd_sleep_prelude();
2021 /* shut server down */
2024 /* free commandline interface */
2025 command_done(cmd_ctx
);
2035 cyg_httpd_exec_cgi_tcl(char *file_name
);
2036 cyg_int32
homeForm(CYG_HTTPD_STATE
*p
)
2038 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
2042 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label
, "/", homeForm
);
2044 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label
, "text", "text/plain");
2045 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label
, "bin", "application/octet-stream");
2047 #include <pkgconf/system.h>
2048 #include <pkgconf/hal.h>
2049 #include <pkgconf/kernel.h>
2050 #include <pkgconf/io_fileio.h>
2051 #include <pkgconf/fs_rom.h>
2053 #include <cyg/kernel/ktypes.h> // base kernel types
2054 #include <cyg/infra/cyg_trac.h> // tracing macros
2055 #include <cyg/infra/cyg_ass.h> // assertion macros
2057 #include <sys/types.h>
2059 #include <sys/stat.h>
2068 #include <cyg/fileio/fileio.h>
2070 #include <cyg/kernel/kapi.h>
2071 #include <cyg/infra/diag.h>
2073 //==========================================================================
2074 // Eventually we want to eXecute In Place from the ROM in a protected
2075 // environment, so we'll need executables to be aligned to a boundary
2076 // suitable for MMU protection. A suitable boundary would be the 4k
2077 // boundary in all the CPU architectures I am currently aware of.
2079 // Forward definitions
2081 // Filesystem operations
2082 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2083 static int tftpfs_umount(cyg_mtab_entry
*mte
);
2084 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2085 int mode
, cyg_file
*fte
);
2086 static int tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2087 static int tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2090 static int tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2091 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
);
2092 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
);
2094 //==========================================================================
2095 // Filesystem table entries
2097 // -------------------------------------------------------------------------
2099 // This defines the entry in the filesystem table.
2100 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2101 // we should never block in any filesystem operations.
2103 FSTAB_ENTRY( tftpfs_fste
, "tftpfs", 0,
2108 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2109 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2110 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2111 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2112 (cyg_fsop_link
*)cyg_fileio_erofs
,
2113 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2114 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2115 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2116 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2117 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2120 // -------------------------------------------------------------------------
2122 // This defines a single ROMFS loaded into ROM at the configured address
2124 // MTAB_ENTRY( rom_mte, // structure name
2125 // "/rom", // mount point
2126 // "romfs", // FIlesystem type
2127 // "", // hardware device
2128 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
2132 // -------------------------------------------------------------------------
2134 // This set of file operations are used for normal open files.
2136 static cyg_fileops tftpfs_fileops
=
2141 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2145 (cyg_fileop_fstat
*) cyg_fileio_erofs
,
2146 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2147 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2150 // -------------------------------------------------------------------------
2152 // Process a mount request. This mainly finds root for the
2155 static int tftpfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2160 static int tftpfs_umount(cyg_mtab_entry
*mte
)
2175 static void freeTftp(struct Tftp
*t
)
2188 static const int tftpMaxSize
= 8192 * 1024;
2189 static int tftpfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2190 int mode
, cyg_file
*file
)
2193 tftp
= malloc(sizeof(struct Tftp
));
2196 memset(tftp
, 0, sizeof(struct Tftp
));
2198 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2199 file
->f_type
= CYG_FILE_TYPE_FILE
;
2200 file
->f_ops
= &tftpfs_fileops
;
2205 tftp
->mem
= malloc(tftpMaxSize
);
2206 if (tftp
->mem
== NULL
)
2212 char *server
= strchr(name
, '/');
2219 tftp
->server
= malloc(server
- name
+ 1);
2220 if (tftp
->server
== NULL
)
2225 strncpy(tftp
->server
, name
, server
- name
);
2226 tftp
->server
[server
- name
] = 0;
2228 tftp
->file
= strdup(server
+ 1);
2229 if (tftp
->file
== NULL
)
2235 file
->f_data
= (CYG_ADDRWORD
) tftp
;
2240 static int fetchTftp(struct Tftp
*tftp
)
2242 if (!tftp
->readFile
)
2245 tftp
->actual
= tftp_client_get( tftp
->file
, tftp
->server
, 0, tftp
->mem
, tftpMaxSize
, TFTP_OCTET
, &err
);
2247 if (tftp
->actual
< 0)
2256 // -------------------------------------------------------------------------
2257 // tftpfs_fo_write()
2258 // Read data from file.
2261 tftpfs_fo_read(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2263 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2265 if (fetchTftp(tftp
) != ENOERR
)
2269 off_t pos
= fp
->f_offset
;
2271 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2273 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2274 char *buf
= (char *) iov
->iov_base
;
2275 off_t len
= iov
->iov_len
;
2277 if (len
+ pos
> tftp
->actual
)
2279 len
= tftp
->actual
- pos
;
2281 resid
+= iov
->iov_len
- len
;
2283 memcpy(buf
, tftp
->mem
+ pos
, len
);
2287 uio
->uio_resid
= resid
;
2295 tftpfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2297 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2300 off_t pos
= fp
->f_offset
;
2302 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2304 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2305 char *buf
= (char *) iov
->iov_base
;
2306 off_t len
= iov
->iov_len
;
2308 if (len
+ pos
> tftpMaxSize
)
2310 len
= tftpMaxSize
- pos
;
2312 resid
+= iov
->iov_len
- len
;
2314 memcpy(tftp
->mem
+ pos
, buf
, len
);
2318 uio
->uio_resid
= resid
;
2327 tftpfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2333 // -------------------------------------------------------------------------
2335 // Close a file. We just clear out the data pointer.
2337 static int tftpfs_fo_close(struct CYG_FILE_TAG
*fp
)
2339 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2344 tftp_client_put( tftp
->file
, tftp
->server
, 0, tftp
->mem
, fp
->f_offset
, TFTP_OCTET
, &error
);
2352 // -------------------------------------------------------------------------
2354 // Seek to a new file position.
2356 static int tftpfs_fo_lseek(struct CYG_FILE_TAG
*fp
, off_t
*apos
, int whence
)
2358 struct Tftp
*tftp
= (struct Tftp
*) fp
->f_data
;
2361 if (fetchTftp(tftp
) != ENOERR
)
2367 // Pos is already where we want to be.
2371 // Add pos to current offset.
2372 pos
+= fp
->f_offset
;
2376 // Add pos to file size.
2377 pos
+= tftp
->actual
;
2384 // Check that pos is still within current file size, or at the
2386 if (pos
< 0 || pos
> tftp
->actual
)
2389 // All OK, set fp offset and return new position.
2390 *apos
= fp
->f_offset
= pos
;
2398 cyg_thread_delay(us
/ 10000 + 1);
2405 show_log_entry(CYG_HTTPD_STATE
*phttpstate
)
2407 cyg_httpd_start_chunked("text");
2408 if (logCount
>= logSize
)
2410 cyg_httpd_write_chunked(logBuffer
+logCount
%logSize
, logSize
-logCount
%logSize
);
2412 cyg_httpd_write_chunked(logBuffer
, writePtr
);
2413 cyg_httpd_end_chunked();
2417 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log
, "/ram/log", show_log_entry
);
2419 // Filesystem operations
2420 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
);
2421 static int logfs_umount(cyg_mtab_entry
*mte
);
2422 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2423 int mode
, cyg_file
*fte
);
2425 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
);
2428 static int logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
);
2429 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
);
2431 #include <cyg/io/devtab.h>
2433 //==========================================================================
2434 // Filesystem table entries
2436 // -------------------------------------------------------------------------
2438 // This defines the entry in the filesystem table.
2439 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2440 // we should never block in any filesystem operations.
2441 FSTAB_ENTRY( logfs_fste
, "logfs", 0,
2442 CYG_SYNCMODE_FILE_FILESYSTEM
|CYG_SYNCMODE_IO_FILESYSTEM
,
2446 (cyg_fsop_unlink
*)cyg_fileio_erofs
,
2447 (cyg_fsop_mkdir
*)cyg_fileio_erofs
,
2448 (cyg_fsop_rmdir
*)cyg_fileio_erofs
,
2449 (cyg_fsop_rename
*)cyg_fileio_erofs
,
2450 (cyg_fsop_link
*)cyg_fileio_erofs
,
2451 (cyg_fsop_opendir
*)cyg_fileio_erofs
,
2452 (cyg_fsop_chdir
*)cyg_fileio_erofs
,
2453 (cyg_fsop_stat
*)cyg_fileio_erofs
,
2454 (cyg_fsop_getinfo
*)cyg_fileio_erofs
,
2455 (cyg_fsop_setinfo
*)cyg_fileio_erofs
);
2457 // -------------------------------------------------------------------------
2459 // This set of file operations are used for normal open files.
2461 static cyg_fileops logfs_fileops
=
2463 (cyg_fileop_read
*)cyg_fileio_erofs
,
2464 (cyg_fileop_write
*)logfs_fo_write
,
2465 (cyg_fileop_lseek
*) cyg_fileio_erofs
,
2466 (cyg_fileop_ioctl
*)cyg_fileio_erofs
,
2470 (cyg_fileop_fstat
*)cyg_fileio_erofs
,
2471 (cyg_fileop_getinfo
*) cyg_fileio_erofs
,
2472 (cyg_fileop_setinfo
*)cyg_fileio_erofs
,
2475 // -------------------------------------------------------------------------
2477 // Process a mount request. This mainly finds root for the
2480 static int logfs_mount(cyg_fstab_entry
*fste
, cyg_mtab_entry
*mte
)
2485 static int logfs_umount(cyg_mtab_entry
*mte
)
2490 static int logfs_open(cyg_mtab_entry
*mte
, cyg_dir dir
, const char *name
,
2491 int mode
, cyg_file
*file
)
2493 file
->f_flag
|= mode
& CYG_FILE_MODE_MASK
;
2494 file
->f_type
= CYG_FILE_TYPE_FILE
;
2495 file
->f_ops
= &logfs_fileops
;
2502 // -------------------------------------------------------------------------
2504 // Write data to file.
2507 logfs_fo_write(struct CYG_FILE_TAG
*fp
, struct CYG_UIO_TAG
*uio
)
2510 for (i
= 0; i
< uio
->uio_iovcnt
; i
++)
2512 cyg_iovec
*iov
= &uio
->uio_iov
[i
];
2513 char *buf
= (char *) iov
->iov_base
;
2514 off_t len
= iov
->iov_len
;
2516 diag_write(buf
, len
);
2523 logfs_fo_fsync(struct CYG_FILE_TAG
*fp
, int mode
)
2528 // -------------------------------------------------------------------------
2530 // Close a file. We just clear out the data pointer.
2532 static int logfs_fo_close(struct CYG_FILE_TAG
*fp
)
2538 ramiodev_init( struct cyg_devtab_entry
*tab
)
2544 ramiodev_bread( cyg_io_handle_t handle
, void *buf
, cyg_uint32
*len
,
2547 if (*len
+pos
>ramblockdevice_size
)
2549 *len
=ramblockdevice_size
-pos
;
2551 memcpy(buf
, ramblockdevice
+pos
, *len
);
2556 ramiodev_bwrite( cyg_io_handle_t handle
, const void *buf
, cyg_uint32
*len
,
2559 if (((pos
%4)!=0)||(((*len
)%4)!=0))
2561 diag_printf("Unaligned write %d %d!", pos
, *len
);
2564 memcpy(ramblockdevice
+pos
, buf
, *len
);
2569 ramiodev_get_config( cyg_io_handle_t handle
,
2575 case CYG_IO_GET_CONFIG_FLASH_ERASE
:
2577 if ( *len
!= sizeof( cyg_io_flash_getconfig_erase_t
) )
2580 cyg_io_flash_getconfig_erase_t
*e
= (cyg_io_flash_getconfig_erase_t
*)buf
;
2581 char *startpos
= ramblockdevice
+ e
->offset
;
2583 if (((e
->offset
%(64*1024))!=0)||((e
->len
%(64*1024))!=0))
2585 diag_printf("Erease is not aligned %d %d\n", e
->offset
, e
->len
);
2588 memset(startpos
, 0xff, e
->len
);
2594 case CYG_IO_GET_CONFIG_FLASH_DEVSIZE
:
2596 if ( *len
!= sizeof( cyg_io_flash_getconfig_devsize_t
) )
2599 cyg_io_flash_getconfig_devsize_t
*d
=
2600 (cyg_io_flash_getconfig_devsize_t
*)buf
;
2602 d
->dev_size
= ramblockdevice_size
;
2607 case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE
:
2609 cyg_io_flash_getconfig_blocksize_t
*b
=
2610 (cyg_io_flash_getconfig_blocksize_t
*)buf
;
2611 if ( *len
!= sizeof( cyg_io_flash_getconfig_blocksize_t
) )
2614 // offset unused for now
2615 b
->block_size
= 64*1024;
2625 ramiodev_set_config( cyg_io_handle_t handle
,
2635 } // ramiodev_set_config()
2637 // get_config/set_config should be added later to provide the other flash
2638 // operations possible, like erase etc.
2640 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops
,
2644 &ramiodev_get_config
,
2645 &ramiodev_set_config
2649 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1
,
2652 &cyg_io_ramdev1_ops
,
2654 0, // No lookup required
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)