3 /* According to POSIX.1-2001 */
4 #include <sys/select.h>
12 #include "stlink-common.h"
14 #define STLINKY_MAGIC 0xDEADF00D
16 #define READ_UINT32_LE(buf) ((uint32_t) ( buf[0] \
30 void nonblock(int state);
32 static void cleanup(int signal __attribute__((unused))) {
34 /* Switch back to mass storage mode before closing. */
36 stlink_exit_debug_mode(sl);
46 sigemptyset(&sig_mask);
47 sigaddset(&sig_mask, SIGINT);
48 sigaddset(&sig_mask, SIGTERM);
49 signal(SIGINT, &cleanup);
50 signal(SIGTERM, &cleanup);
51 sigprocmask(SIG_BLOCK, &sig_mask, NULL);
57 if (sigismember(&pending, SIGINT) || sigismember(&pending, SIGTERM)) {
58 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
60 sigprocmask(SIG_BLOCK, &sig_mask, NULL);
64 /* Detects stlinky in RAM, returns handler */
65 struct stlinky* stlinky_detect(stlink_t* sl)
67 static const uint32_t sram_base = 0x20000000;
68 struct stlinky* st = malloc(sizeof(struct stlinky));
71 printf("sram: 0x%x bytes @ 0x%zx\n", sl->sram_base, sl->sram_size);
73 for (off = 0; off < sl->sram_size; off += 4) {
74 if (off % 1024 == 0) sig_process();
75 stlink_read_mem32(sl, sram_base + off, 4);
76 if (STLINKY_MAGIC == READ_UINT32_LE(sl->q_buf))
78 if (multiple > 0) printf("WARNING: another ");
79 printf("stlinky detected at 0x%x\n", sram_base + off);
80 st->off = sram_base + off;
81 stlink_read_mem32(sl, st->off + 4, 4);
82 st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
83 printf("stlinky buffer size 0x%zu \n", st->bufsize);
89 printf("Using last stlinky structure detected\n");
96 int stlinky_canrx(struct stlinky *st)
98 stlink_read_mem32(st->sl, st->off+4, 4);
99 unsigned char tx = (unsigned char) st->sl->q_buf[1];
103 size_t stlinky_rx(struct stlinky *st, char* buffer)
105 unsigned char tx = 0;
107 stlink_read_mem32(st->sl, st->off+4, 4);
108 tx = (unsigned char) st->sl->q_buf[1];
110 size_t rs = tx + (4 - (tx % 4)); /* voodoo */
111 stlink_read_mem32(st->sl, st->off+8, rs);
112 memcpy(buffer, st->sl->q_buf, (size_t) tx);
114 stlink_write_mem8(st->sl, st->off+5, 1);
118 size_t stlinky_tx(struct stlinky *st, char* buffer, size_t sz)
120 unsigned char rx = 1;
122 stlink_read_mem32(st->sl, st->off+4, 4);
123 rx = (unsigned char) st->sl->q_buf[2];
125 memcpy(st->sl->q_buf, buffer, sz);
126 size_t rs = sz + (4 - (sz % 4)); /* voodoo */
127 stlink_write_mem32(st->sl, st->off+8+st->bufsize, rs);
128 *st->sl->q_buf=(unsigned char) sz;
129 stlink_write_mem8(st->sl, st->off+6, 1);
140 FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
141 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
142 return FD_ISSET(STDIN_FILENO, &fds);
145 void nonblock(int state)
147 struct termios ttystate;
149 //get the terminal state
150 tcgetattr(STDIN_FILENO, &ttystate);
154 //turn off canonical mode
155 ttystate.c_lflag &= ~ICANON;
156 ttystate.c_lflag &= ~ECHO;
157 //minimum of number input read.
158 ttystate.c_cc[VMIN] = 1;
162 //turn on canonical mode
163 ttystate.c_lflag |= ICANON | ECHO;
165 //set the terminal attributes.
166 tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
170 int main(int ac, char** av) {
171 struct stlinky *st=NULL;
175 sl = stlink_open_usb(10, 1);
177 printf("ST-Linky proof-of-concept terminal :: Created by Necromant for lulz\n");
179 stlink_enter_swd_mode(sl);
180 printf("chip id: %#x\n", sl->chip_id);
181 printf("core_id: %#x\n", sl->core_id);
183 cortex_m3_cpuid_t cpuid;
184 stlink_cpu_id(sl, &cpuid);
185 printf("cpuid:impl_id = %0#x, variant = %#x\n", cpuid.implementer_id, cpuid.variant);
186 printf("cpuid:part = %#x, rev = %#x\n", cpuid.part, cpuid.revision);
189 stlink_force_debug(sl);
193 /* wait for device to boot */
194 /* TODO: Make timeout adjustable via command line */
198 st = stlinky_detect(sl);
200 st = malloc(sizeof(struct stlinky));
202 st->off = (int)strtol(av[1], NULL, 16);
203 printf("using stlinky at 0x%x\n", st->off);
204 stlink_read_mem32(sl, st->off + 4, 4);
205 st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
206 printf("stlinky buffer size 0x%zu \n", st->bufsize);
212 printf("stlinky magic not found in sram :(\n");
215 char* rxbuf = malloc(st->bufsize);
216 char* txbuf = malloc(st->bufsize);
219 int fd = fileno(stdin);
220 int saved_flags = fcntl(fd, F_GETFL);
221 fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK);
222 printf("Entering interactive terminal. CTRL+C to exit\n\n\n");
225 if (stlinky_canrx(st)) {
226 tmp = stlinky_rx(st, rxbuf);
227 fwrite(rxbuf,tmp,1,stdout);
231 tmp = read(fd, txbuf, st->bufsize);
232 stlinky_tx(st,txbuf,tmp);