semihost server example program
Dependencies: SWD mbed USBLocalFileSystem BaseDAP USBDAP
LPCXpresso LPC11U68 | LPCXpresso LPC1549 | FRDM-KL46Z | EA LPC4088 QSB app-board | LPC1768 app-board | LPC810 | LPC1114FN28 | |
---|---|---|---|---|---|---|---|
server | server | server | server | server | client | client | |
SWDIO | D12 | D12 | D12 | p25 | p21 | p4(P0_2) | p12 |
SWCLK | D10 | D10 | D10 | p26 | p22 | p3(P0_3) | p3 |
nRESET *option | D6 | D6 | D6 | p34 | p30 | p1(P0_5) | p23 |
GND | GND | GND | GND | p1 | p1 | p7 | p22 |
3.3V | P3V3 | P3V3 | P3V3 | p44 | p40 | p6 | p21 |
flash write | SW2(P0_1) | SW3(P1_9) | SW1 | p14 joystick center | p14 joystick center |
client example:
Import programlpc810-semihost_helloworld
semihost client example program
Semihost.cpp@18:5ed1759e863b, 2014-06-22 (annotated)
- Committer:
- va009039
- Date:
- Sun Jun 22 12:04:16 2014 +0000
- Revision:
- 18:5ed1759e863b
- Parent:
- 17:4e1205ce031f
add LPC11U68 interface.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 18:5ed1759e863b | 1 | // Semihost.cpp 2014/6/22 |
va009039 | 1:eb30547ba84d | 2 | #include "Semihost.h" |
va009039 | 1:eb30547ba84d | 3 | #include "mydebug.h" |
va009039 | 1:eb30547ba84d | 4 | |
va009039 | 17:4e1205ce031f | 5 | Semihost::Semihost(Target2* target, Serial* usbpc, USBLocalFileSystem* usb) : _target(target),_pc(usbpc),_usb(usb) |
va009039 | 1:eb30547ba84d | 6 | { |
va009039 | 1:eb30547ba84d | 7 | _dirpath = "/local"; |
va009039 | 9:7e71c20c96e4 | 8 | _writec_buf = -1; |
va009039 | 1:eb30547ba84d | 9 | } |
va009039 | 1:eb30547ba84d | 10 | |
va009039 | 1:eb30547ba84d | 11 | void Semihost::mount(const char* dirpath) |
va009039 | 1:eb30547ba84d | 12 | { |
va009039 | 1:eb30547ba84d | 13 | _dirpath = (char*)dirpath; |
va009039 | 1:eb30547ba84d | 14 | } |
va009039 | 1:eb30547ba84d | 15 | |
va009039 | 1:eb30547ba84d | 16 | int Semihost::poll() |
va009039 | 1:eb30547ba84d | 17 | { |
va009039 | 18:5ed1759e863b | 18 | TRACE(); |
va009039 | 1:eb30547ba84d | 19 | if (_target->getStatus() != TARGET_HALTED) { |
va009039 | 1:eb30547ba84d | 20 | return 0; |
va009039 | 1:eb30547ba84d | 21 | } |
va009039 | 1:eb30547ba84d | 22 | uint32_t pc = _target->pc; |
va009039 | 1:eb30547ba84d | 23 | if (pc & 1) { |
va009039 | 1:eb30547ba84d | 24 | return 0; |
va009039 | 1:eb30547ba84d | 25 | } |
va009039 | 1:eb30547ba84d | 26 | if (rd<uint16_t>(pc) != 0xbeab) { // BKPT #171 |
va009039 | 1:eb30547ba84d | 27 | return 0; |
va009039 | 1:eb30547ba84d | 28 | } |
va009039 | 2:32e9437348ad | 29 | uint32_t reason = _target->r0; |
va009039 | 2:32e9437348ad | 30 | _target->r0 = exec(reason, _target->r1); |
va009039 | 2:32e9437348ad | 31 | if (reason == SYS_EXIT) { |
va009039 | 2:32e9437348ad | 32 | return SYS_EXIT; |
va009039 | 2:32e9437348ad | 33 | } |
va009039 | 1:eb30547ba84d | 34 | _target->pc = pc + 3; // skip bkpt #171 |
va009039 | 1:eb30547ba84d | 35 | _target->resume(); |
va009039 | 2:32e9437348ad | 36 | return reason; |
va009039 | 1:eb30547ba84d | 37 | } |
va009039 | 1:eb30547ba84d | 38 | |
va009039 | 1:eb30547ba84d | 39 | int Semihost::exec(uint32_t reason, uint32_t arg) |
va009039 | 1:eb30547ba84d | 40 | { |
va009039 | 1:eb30547ba84d | 41 | switch(reason) { |
va009039 | 4:5e4107edcbdb | 42 | case 0x01: return sys_open(arg); |
va009039 | 4:5e4107edcbdb | 43 | case 0x02: return sys_close(arg); |
va009039 | 4:5e4107edcbdb | 44 | case 0x03: return sys_writec(arg); |
va009039 | 4:5e4107edcbdb | 45 | case 0x04: return sys_write0(arg); |
va009039 | 4:5e4107edcbdb | 46 | case 0x05: return sys_write(arg); |
va009039 | 4:5e4107edcbdb | 47 | case 0x06: return sys_read(arg); |
va009039 | 4:5e4107edcbdb | 48 | case 0x07: return sys_readc(arg); |
va009039 | 4:5e4107edcbdb | 49 | case 0x09: return sys_istty(arg); |
va009039 | 4:5e4107edcbdb | 50 | case 0x0a: return sys_fseek(arg); |
va009039 | 4:5e4107edcbdb | 51 | case 0x0b: return sys_ensure(arg); |
va009039 | 4:5e4107edcbdb | 52 | case 0x0c: return sys_flen(arg); |
va009039 | 4:5e4107edcbdb | 53 | case 0x0e: return sys_remove(arg); |
va009039 | 4:5e4107edcbdb | 54 | case 0x0f: return sys_rename(arg); |
va009039 | 4:5e4107edcbdb | 55 | case 0x18: return sys_exit(arg); |
va009039 | 1:eb30547ba84d | 56 | |
va009039 | 4:5e4107edcbdb | 57 | case 0x100: return usr_xffind(arg); |
va009039 | 4:5e4107edcbdb | 58 | case 0x101: return usr_uid(arg); |
va009039 | 4:5e4107edcbdb | 59 | case 0x102: return usr_reset(arg); |
va009039 | 4:5e4107edcbdb | 60 | case 0x103: return usr_vbus(arg); |
va009039 | 4:5e4107edcbdb | 61 | case 0x104: return usr_powerdown(arg); |
va009039 | 4:5e4107edcbdb | 62 | case 0x105: return usr_disabledebug(arg); |
va009039 | 1:eb30547ba84d | 63 | } |
va009039 | 4:5e4107edcbdb | 64 | _pc->printf("[semihost]error reason=%08x arg=%08x\n", reason, arg); |
va009039 | 4:5e4107edcbdb | 65 | return -1; |
va009039 | 1:eb30547ba84d | 66 | } |
va009039 | 1:eb30547ba84d | 67 | |
va009039 | 1:eb30547ba84d | 68 | int Semihost::sys_open(uint32_t arg) // 0x01 |
va009039 | 1:eb30547ba84d | 69 | { |
va009039 | 1:eb30547ba84d | 70 | char name[64]; |
va009039 | 1:eb30547ba84d | 71 | _build_name(name, sizeof(name), arg, arg+8); |
va009039 | 1:eb30547ba84d | 72 | const char* mode[] = {"r", "rb", "r+", "r+b", "w", "wb", "w+", "w+b", "a", "ab", "a+", "a+b"}; |
va009039 | 1:eb30547ba84d | 73 | uint32_t mode_index = rd<uint32_t>(arg+4); |
va009039 | 1:eb30547ba84d | 74 | FILE* fp = fopen(name, mode[mode_index]); |
va009039 | 1:eb30547ba84d | 75 | if (fp) { |
va009039 | 1:eb30547ba84d | 76 | return (uint32_t)fp; |
va009039 | 1:eb30547ba84d | 77 | } |
va009039 | 1:eb30547ba84d | 78 | _pc->printf("\n[semihost]file open error [%s]\n", name); |
va009039 | 1:eb30547ba84d | 79 | return -1; |
va009039 | 1:eb30547ba84d | 80 | } |
va009039 | 1:eb30547ba84d | 81 | |
va009039 | 1:eb30547ba84d | 82 | int Semihost::sys_close(uint32_t arg) // 0x02 |
va009039 | 1:eb30547ba84d | 83 | { |
va009039 | 1:eb30547ba84d | 84 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 85 | int r = fclose(fp); |
va009039 | 1:eb30547ba84d | 86 | if (r == 0) { |
va009039 | 1:eb30547ba84d | 87 | return 0; |
va009039 | 1:eb30547ba84d | 88 | } |
va009039 | 1:eb30547ba84d | 89 | return -1; |
va009039 | 1:eb30547ba84d | 90 | } |
va009039 | 1:eb30547ba84d | 91 | |
va009039 | 1:eb30547ba84d | 92 | int Semihost::sys_writec(uint32_t arg) // 0x03 |
va009039 | 1:eb30547ba84d | 93 | { |
va009039 | 9:7e71c20c96e4 | 94 | int c = rd<uint8_t>(arg); |
va009039 | 9:7e71c20c96e4 | 95 | _usb->putc(c); |
va009039 | 9:7e71c20c96e4 | 96 | return c; |
va009039 | 9:7e71c20c96e4 | 97 | } |
va009039 | 9:7e71c20c96e4 | 98 | |
va009039 | 9:7e71c20c96e4 | 99 | int Semihost::readable() |
va009039 | 9:7e71c20c96e4 | 100 | { |
va009039 | 9:7e71c20c96e4 | 101 | return (_writec_buf == (-1)) ? 0 : 1; |
va009039 | 9:7e71c20c96e4 | 102 | } |
va009039 | 9:7e71c20c96e4 | 103 | |
va009039 | 9:7e71c20c96e4 | 104 | int Semihost::getc() |
va009039 | 9:7e71c20c96e4 | 105 | { |
va009039 | 9:7e71c20c96e4 | 106 | int c = _writec_buf; |
va009039 | 9:7e71c20c96e4 | 107 | _writec_buf = -1; |
va009039 | 9:7e71c20c96e4 | 108 | return c; |
va009039 | 1:eb30547ba84d | 109 | } |
va009039 | 1:eb30547ba84d | 110 | |
va009039 | 1:eb30547ba84d | 111 | int Semihost::sys_write0(uint32_t arg) // 0x04 |
va009039 | 1:eb30547ba84d | 112 | { |
va009039 | 1:eb30547ba84d | 113 | uint32_t p = rd<uint32_t>(arg); |
va009039 | 1:eb30547ba84d | 114 | while(1) { |
va009039 | 1:eb30547ba84d | 115 | uint8_t c = rd<uint8_t>(p++); |
va009039 | 1:eb30547ba84d | 116 | if (c == '\0') { |
va009039 | 1:eb30547ba84d | 117 | break; |
va009039 | 1:eb30547ba84d | 118 | } |
va009039 | 1:eb30547ba84d | 119 | _pc->putc(c & 0xff); |
va009039 | 1:eb30547ba84d | 120 | } |
va009039 | 1:eb30547ba84d | 121 | return 0; |
va009039 | 1:eb30547ba84d | 122 | } |
va009039 | 1:eb30547ba84d | 123 | |
va009039 | 1:eb30547ba84d | 124 | int Semihost::sys_write(uint32_t arg) // 0x05 |
va009039 | 1:eb30547ba84d | 125 | { |
va009039 | 1:eb30547ba84d | 126 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 127 | uint32_t p = rd<uint32_t>(arg+4); |
va009039 | 1:eb30547ba84d | 128 | int count = rd<uint32_t>(arg+8); |
va009039 | 1:eb30547ba84d | 129 | while(count > 0) { |
va009039 | 1:eb30547ba84d | 130 | uint8_t c = rd<uint8_t>(p++); |
va009039 | 1:eb30547ba84d | 131 | if (fputc(c, fp) == EOF) { |
va009039 | 1:eb30547ba84d | 132 | return count; |
va009039 | 1:eb30547ba84d | 133 | } |
va009039 | 1:eb30547ba84d | 134 | count--; |
va009039 | 1:eb30547ba84d | 135 | } |
va009039 | 1:eb30547ba84d | 136 | return 0; |
va009039 | 1:eb30547ba84d | 137 | } |
va009039 | 1:eb30547ba84d | 138 | |
va009039 | 1:eb30547ba84d | 139 | int Semihost::sys_read(uint32_t arg) // 0x06 |
va009039 | 1:eb30547ba84d | 140 | { |
va009039 | 1:eb30547ba84d | 141 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 142 | uint32_t p = rd<uint32_t>(arg+4); |
va009039 | 1:eb30547ba84d | 143 | int count = rd<uint32_t>(arg+8); |
va009039 | 1:eb30547ba84d | 144 | while(count > 0) { |
va009039 | 1:eb30547ba84d | 145 | int c = fgetc(fp); |
va009039 | 1:eb30547ba84d | 146 | if (c == EOF) { |
va009039 | 1:eb30547ba84d | 147 | return count; |
va009039 | 1:eb30547ba84d | 148 | } |
va009039 | 1:eb30547ba84d | 149 | wr<uint8_t>(p++, c); |
va009039 | 1:eb30547ba84d | 150 | count--; |
va009039 | 1:eb30547ba84d | 151 | } |
va009039 | 1:eb30547ba84d | 152 | return 0; |
va009039 | 1:eb30547ba84d | 153 | } |
va009039 | 1:eb30547ba84d | 154 | |
va009039 | 1:eb30547ba84d | 155 | int Semihost::sys_readc(uint32_t arg) // 0x07 |
va009039 | 1:eb30547ba84d | 156 | { |
va009039 | 9:7e71c20c96e4 | 157 | return _usb->getc() & 0xff; |
va009039 | 1:eb30547ba84d | 158 | } |
va009039 | 1:eb30547ba84d | 159 | |
va009039 | 1:eb30547ba84d | 160 | int Semihost::sys_istty(uint32_t arg) // 0x09 |
va009039 | 1:eb30547ba84d | 161 | { |
va009039 | 1:eb30547ba84d | 162 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 163 | return 0; |
va009039 | 1:eb30547ba84d | 164 | } |
va009039 | 1:eb30547ba84d | 165 | |
va009039 | 1:eb30547ba84d | 166 | int Semihost::sys_fseek(uint32_t arg) // 0x0a |
va009039 | 1:eb30547ba84d | 167 | { |
va009039 | 1:eb30547ba84d | 168 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 169 | int offset = rd<uint32_t>(arg+4); |
va009039 | 1:eb30547ba84d | 170 | return fseek(fp, offset, SEEK_SET); |
va009039 | 1:eb30547ba84d | 171 | } |
va009039 | 1:eb30547ba84d | 172 | |
va009039 | 1:eb30547ba84d | 173 | int Semihost::sys_ensure(uint32_t arg) // 0x0b |
va009039 | 1:eb30547ba84d | 174 | { |
va009039 | 1:eb30547ba84d | 175 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 176 | return -1; |
va009039 | 1:eb30547ba84d | 177 | } |
va009039 | 1:eb30547ba84d | 178 | |
va009039 | 1:eb30547ba84d | 179 | int Semihost::sys_flen(uint32_t arg) // 0x0c |
va009039 | 1:eb30547ba84d | 180 | { |
va009039 | 1:eb30547ba84d | 181 | FILE* fp = reinterpret_cast<FILE*>(rd<uint32_t>(arg)); |
va009039 | 1:eb30547ba84d | 182 | return ftell(fp); |
va009039 | 1:eb30547ba84d | 183 | } |
va009039 | 1:eb30547ba84d | 184 | |
va009039 | 1:eb30547ba84d | 185 | int Semihost::sys_remove(uint32_t arg) // 0x0e |
va009039 | 1:eb30547ba84d | 186 | { |
va009039 | 1:eb30547ba84d | 187 | |
va009039 | 1:eb30547ba84d | 188 | char name[64]; |
va009039 | 1:eb30547ba84d | 189 | _build_name(name, sizeof(name), arg, arg+4); |
va009039 | 1:eb30547ba84d | 190 | return remove(name); |
va009039 | 1:eb30547ba84d | 191 | } |
va009039 | 1:eb30547ba84d | 192 | |
va009039 | 1:eb30547ba84d | 193 | int Semihost::sys_rename(uint32_t arg) // 0x0f |
va009039 | 1:eb30547ba84d | 194 | { |
va009039 | 1:eb30547ba84d | 195 | char oldname[64]; |
va009039 | 1:eb30547ba84d | 196 | char newname[64]; |
va009039 | 1:eb30547ba84d | 197 | _build_name(oldname, sizeof(oldname), arg, arg+4); |
va009039 | 1:eb30547ba84d | 198 | _build_name(newname, sizeof(newname), arg+8, arg+12); |
va009039 | 1:eb30547ba84d | 199 | return rename(oldname, newname); |
va009039 | 1:eb30547ba84d | 200 | } |
va009039 | 1:eb30547ba84d | 201 | |
va009039 | 1:eb30547ba84d | 202 | int Semihost::sys_exit(uint32_t arg) // 0x18 |
va009039 | 1:eb30547ba84d | 203 | { |
va009039 | 1:eb30547ba84d | 204 | _pc->printf("\n[semihost]EXIT!!!\n"); |
va009039 | 2:32e9437348ad | 205 | _pc->printf("r0=%08x r1=%08x r2=%08x r3=%08x\n", |
va009039 | 2:32e9437348ad | 206 | _target->r0.read(),_target->r1.read(),_target->r2.read(),_target->r3.read()); |
va009039 | 2:32e9437348ad | 207 | _pc->printf("r4=%08x r5=%08x r6=%08x r7=%08x\n", |
va009039 | 2:32e9437348ad | 208 | _target->r4.read(),_target->r5.read(),_target->r6.read(),_target->r7.read()); |
va009039 | 2:32e9437348ad | 209 | _pc->printf("sp=%08x lr=%08x pc=%08x xpsr=%08x\n", |
va009039 | 2:32e9437348ad | 210 | _target->sp.read(),_target->lr.read(),_target->pc.read(),_target->xpsr.read()); |
va009039 | 1:eb30547ba84d | 211 | return -1; |
va009039 | 1:eb30547ba84d | 212 | } |
va009039 | 1:eb30547ba84d | 213 | |
va009039 | 1:eb30547ba84d | 214 | void Semihost::_build_name(char* buf, int size, uint32_t arg1, uint32_t arg2) |
va009039 | 1:eb30547ba84d | 215 | { |
va009039 | 1:eb30547ba84d | 216 | strcpy(buf, _dirpath); |
va009039 | 1:eb30547ba84d | 217 | uint32_t p = rd<uint32_t>(arg1); |
va009039 | 1:eb30547ba84d | 218 | int len = rd<uint32_t>(arg2); |
va009039 | 1:eb30547ba84d | 219 | int pos = strlen(buf); |
va009039 | 1:eb30547ba84d | 220 | if (buf[pos-1] != '/') { |
va009039 | 1:eb30547ba84d | 221 | buf[pos++] = '/'; |
va009039 | 1:eb30547ba84d | 222 | buf[pos] = '\0'; |
va009039 | 1:eb30547ba84d | 223 | } |
va009039 | 1:eb30547ba84d | 224 | for(int i = 0; i < len && pos < size-1; i++) { |
va009039 | 1:eb30547ba84d | 225 | buf[pos++] = rd<uint8_t>(p++); |
va009039 | 1:eb30547ba84d | 226 | } |
va009039 | 1:eb30547ba84d | 227 | buf[pos] = '\0'; |
va009039 | 1:eb30547ba84d | 228 | } |
va009039 | 1:eb30547ba84d | 229 | |
va009039 | 1:eb30547ba84d | 230 | int Semihost::usr_xffind(uint32_t arg) // 0x100 |
va009039 | 1:eb30547ba84d | 231 | { |
va009039 | 1:eb30547ba84d | 232 | return -1; |
va009039 | 1:eb30547ba84d | 233 | } |
va009039 | 1:eb30547ba84d | 234 | |
va009039 | 1:eb30547ba84d | 235 | int Semihost::usr_uid(uint32_t arg) // 0x101 |
va009039 | 1:eb30547ba84d | 236 | { |
va009039 | 2:32e9437348ad | 237 | uint32_t p = rd<uint32_t>(arg); |
va009039 | 1:eb30547ba84d | 238 | uint32_t len = rd<uint32_t>(arg+4); |
va009039 | 2:32e9437348ad | 239 | const char* uid = "101000000000000000000002F7F00000"; |
va009039 | 2:32e9437348ad | 240 | for(int i = 0; i < 32 && i < len; i++) { |
va009039 | 2:32e9437348ad | 241 | wr<uint8_t>(p++, uid[i]); |
va009039 | 1:eb30547ba84d | 242 | } |
va009039 | 1:eb30547ba84d | 243 | return 0; |
va009039 | 1:eb30547ba84d | 244 | } |
va009039 | 1:eb30547ba84d | 245 | |
va009039 | 1:eb30547ba84d | 246 | int Semihost::usr_reset(uint32_t arg) // 0x102 |
va009039 | 1:eb30547ba84d | 247 | { |
va009039 | 3:d7a7cde0bfb8 | 248 | _target->SoftwareReset(); |
va009039 | 1:eb30547ba84d | 249 | _target->setup(); |
va009039 | 1:eb30547ba84d | 250 | return 0; |
va009039 | 1:eb30547ba84d | 251 | } |
va009039 | 1:eb30547ba84d | 252 | |
va009039 | 1:eb30547ba84d | 253 | int Semihost::usr_vbus(uint32_t arg) // 0x103 |
va009039 | 1:eb30547ba84d | 254 | { |
va009039 | 1:eb30547ba84d | 255 | return -1; |
va009039 | 1:eb30547ba84d | 256 | } |
va009039 | 1:eb30547ba84d | 257 | |
va009039 | 1:eb30547ba84d | 258 | int Semihost::usr_powerdown(uint32_t arg) // 0x104 |
va009039 | 1:eb30547ba84d | 259 | { |
va009039 | 1:eb30547ba84d | 260 | return -1; |
va009039 | 1:eb30547ba84d | 261 | } |
va009039 | 1:eb30547ba84d | 262 | |
va009039 | 1:eb30547ba84d | 263 | int Semihost::usr_disabledebug(uint32_t arg) // 0x105 |
va009039 | 1:eb30547ba84d | 264 | { |
va009039 | 1:eb30547ba84d | 265 | return -1; |
va009039 | 1:eb30547ba84d | 266 | } |