00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #undef __FILE_ID__
00017 #define __FILE_ID__ 0x70
00018
00019
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <avr/io.h>
00026 #include <avr/interrupt.h>
00027 #include <avr/pgmspace.h>
00028 #include <avr/eeprom.h>
00029
00030 #include "pm.h"
00031
00032
00033 #define UART_BAUD 57600UL
00034
00035
00036
00037
00038
00039 #define PLAT_TIME_PER_TICK_USEC (1000000ULL*256ULL*8ULL/F_CPU)
00040
00041
00042
00043 static int uart_putc(char c, FILE *stream);
00044 static int uart_getc(FILE *stream);
00045 FILE avr_uart = FDEV_SETUP_STREAM(uart_putc, uart_getc, _FDEV_SETUP_RW);
00046
00047
00048
00049
00050
00051
00052 PmReturn_t
00053 plat_init(void)
00054 {
00055
00056 UBRR0 = (F_CPU / (16UL * UART_BAUD)) - 1;
00057
00058
00059 UCSR0C = (_BV(UCSZ01) | _BV(UCSZ00));
00060
00061
00062 UCSR0B = _BV(TXEN0) | _BV(RXEN0);
00063
00064 stdin = stdout = stderr = &avr_uart;
00065
00066
00067 TCCR0B &= ~(_BV(CS02) | _BV(CS01) | _BV(CS00));
00068 TCCR0B |= _BV(CS01);
00069 TIMSK0 = _BV(TOIE0);
00070
00071
00072 sei();
00073
00074 return PM_RET_OK;
00075 }
00076
00077
00078 PmReturn_t
00079 plat_deinit(void)
00080 {
00081
00082 UCSR0B &= ~(_BV(TXEN0) | _BV(RXEN0));
00083
00084
00085 TCCR0B &= ~(_BV(CS02) | _BV(CS01) | _BV(CS00));
00086
00087 return PM_RET_OK;
00088 }
00089
00090
00091 ISR(TIMER0_OVF_vect)
00092 {
00093
00094
00095
00096
00097 pm_vmPeriodic(PLAT_TIME_PER_TICK_USEC);
00098 }
00099
00100
00101
00102
00103
00104
00105 uint8_t
00106 plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
00107 {
00108 uint8_t b = 0;
00109
00110 switch (memspace)
00111 {
00112 case MEMSPACE_RAM:
00113 b = **paddr;
00114 *paddr += 1;
00115 return b;
00116
00117 case MEMSPACE_PROG:
00118 b = pgm_read_byte(*paddr);
00119 *paddr += 1;
00120 return b;
00121
00122 case MEMSPACE_EEPROM:
00123 b = eeprom_read_byte(*paddr);
00124 *paddr += 1;
00125 return b;
00126
00127 case MEMSPACE_SEEPROM:
00128 case MEMSPACE_OTHER0:
00129 case MEMSPACE_OTHER1:
00130 case MEMSPACE_OTHER2:
00131 case MEMSPACE_OTHER3:
00132 default:
00133 return 0;
00134 }
00135 }
00136
00137
00138 static int
00139 uart_getc(FILE *stream)
00140 {
00141 char c;
00142
00143
00144 loop_until_bit_is_set(UCSR0A, RXC0);
00145 c = UDR0;
00146
00147
00148 if (UCSR0A & _BV(FE0)) return _FDEV_EOF;
00149 if (UCSR0A & _BV(DOR0)) return _FDEV_ERR;
00150
00151 return c;
00152 }
00153
00154
00155 static int
00156 uart_putc(char c, FILE *stream)
00157 {
00158
00159 loop_until_bit_is_set(UCSR0A, UDRE0);
00160
00161
00162 UDR0 = c;
00163
00164 return 0;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 PmReturn_t
00174 plat_getByte(uint8_t *b)
00175 {
00176 PmReturn_t retval = PM_RET_OK;
00177
00178
00179 loop_until_bit_is_set(UCSR0A, RXC0);
00180
00181
00182 if (UCSR0A & (_BV(FE0) | _BV(DOR0)))
00183 {
00184 PM_RAISE(retval, PM_RET_EX_IO);
00185 return retval;
00186 }
00187 *b = UDR0;
00188
00189 return retval;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198 PmReturn_t
00199 plat_putByte(uint8_t b)
00200 {
00201
00202 loop_until_bit_is_set(UCSR0A, UDRE0);
00203
00204
00205 UDR0 = b;
00206
00207 return PM_RET_OK;
00208 }
00209
00210
00211
00212
00213
00214
00215 PmReturn_t
00216 plat_getMsTicks(uint32_t *r_ticks)
00217 {
00218
00219 unsigned char _sreg = SREG;
00220 cli();
00221 *r_ticks = pm_timerMsTicks;
00222 SREG = _sreg;
00223
00224 return PM_RET_OK;
00225 }
00226
00227
00228 #ifdef HAVE_DEBUG_INFO
00229 #define LEN_FNLOOKUP 26
00230 #define LEN_EXNLOOKUP 17
00231 #define FN_MAX_LEN 15
00232 #define EXN_MAX_LEN 18
00233 #ifndef MAX
00234 #define MAX(a,b) (((a) >= (b)) ? (a) : (b))
00235 #endif
00236
00237
00238 static char fnstr_00[] PROGMEM = "<no file>";
00239 static char fnstr_01[] PROGMEM = "codeobj.c";
00240 static char fnstr_02[] PROGMEM = "dict.c";
00241 static char fnstr_03[] PROGMEM = "frame.c";
00242 static char fnstr_04[] PROGMEM = "func.c";
00243 static char fnstr_05[] PROGMEM = "global.c";
00244 static char fnstr_06[] PROGMEM = "heap.c";
00245 static char fnstr_07[] PROGMEM = "img.c";
00246 static char fnstr_08[] PROGMEM = "int.c";
00247 static char fnstr_09[] PROGMEM = "interp.c";
00248 static char fnstr_10[] PROGMEM = "pmstdlib_nat.c";
00249 static char fnstr_11[] PROGMEM = "list.c";
00250 static char fnstr_12[] PROGMEM = "main.c";
00251 static char fnstr_13[] PROGMEM = "mem.c";
00252 static char fnstr_14[] PROGMEM = "module.c";
00253 static char fnstr_15[] PROGMEM = "obj.c";
00254 static char fnstr_16[] PROGMEM = "seglist.c";
00255 static char fnstr_17[] PROGMEM = "sli.c";
00256 static char fnstr_18[] PROGMEM = "strobj.c";
00257 static char fnstr_19[] PROGMEM = "tuple.c";
00258 static char fnstr_20[] PROGMEM = "seq.c";
00259 static char fnstr_21[] PROGMEM = "pm.c";
00260 static char fnstr_22[] PROGMEM = "thread.c";
00261 static char fnstr_23[] PROGMEM = "float.c";
00262 static char fnstr_24[] PROGMEM = "class.c";
00263 static char fnstr_25[] PROGMEM = "bytearray.c";
00264
00265 static PGM_P fnlookup[LEN_FNLOOKUP] PROGMEM =
00266 {
00267 fnstr_00, fnstr_01, fnstr_02, fnstr_03,
00268 fnstr_04, fnstr_05, fnstr_06, fnstr_07,
00269 fnstr_08, fnstr_09, fnstr_10, fnstr_11,
00270 fnstr_12, fnstr_13, fnstr_14, fnstr_15,
00271 fnstr_16, fnstr_17, fnstr_18, fnstr_19,
00272 fnstr_20, fnstr_21, fnstr_22, fnstr_23,
00273 fnstr_24, fnstr_25
00274 };
00275
00276
00277 static char exnstr_00[] PROGMEM = "Exception";
00278 static char exnstr_01[] PROGMEM = "SystemExit";
00279 static char exnstr_02[] PROGMEM = "IoError";
00280 static char exnstr_03[] PROGMEM = "ZeroDivisionError";
00281 static char exnstr_04[] PROGMEM = "AssertionError";
00282 static char exnstr_05[] PROGMEM = "AttributeError";
00283 static char exnstr_06[] PROGMEM = "ImportError";
00284 static char exnstr_07[] PROGMEM = "IndexError";
00285 static char exnstr_08[] PROGMEM = "KeyError";
00286 static char exnstr_09[] PROGMEM = "MemoryError";
00287 static char exnstr_10[] PROGMEM = "NameError";
00288 static char exnstr_11[] PROGMEM = "SyntaxError";
00289 static char exnstr_12[] PROGMEM = "SystemError";
00290 static char exnstr_13[] PROGMEM = "TypeError";
00291 static char exnstr_14[] PROGMEM = "ValueError";
00292 static char exnstr_15[] PROGMEM = "StopIteration";
00293 static char exnstr_16[] PROGMEM = "Warning";
00294
00295 static PGM_P exnlookup[LEN_EXNLOOKUP] PROGMEM =
00296 {
00297 exnstr_00, exnstr_01, exnstr_02, exnstr_03,
00298 exnstr_04, exnstr_05, exnstr_06, exnstr_07,
00299 exnstr_08, exnstr_09, exnstr_10, exnstr_11,
00300 exnstr_12, exnstr_13, exnstr_14, exnstr_15,
00301 exnstr_16
00302 };
00303 #endif
00304
00305
00306 void
00307 plat_reportError(PmReturn_t result)
00308 {
00309 #ifdef HAVE_DEBUG_INFO
00310 uint8_t res;
00311 pPmFrame_t pframe;
00312 pPmObj_t pstr;
00313 PmReturn_t retval;
00314 uint8_t bcindex;
00315 uint16_t bcsum;
00316 uint16_t linesum;
00317 uint16_t len_lnotab;
00318 uint8_t const *plnotab;
00319 uint16_t i;
00320 char pstrbuf[MAX(FN_MAX_LEN, EXN_MAX_LEN)];
00321
00322
00323 puts_P(PSTR("Traceback (most recent call first):"));
00324
00325
00326 pframe = gVmGlobal.pthread->pframe;
00327
00328
00329 if (pframe == (pPmFrame_t)&(gVmGlobal.nativeframe))
00330 {
00331
00332
00333 retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00334 f_co->co_names, -1, &pstr);
00335 if ((retval) != PM_RET_OK)
00336 {
00337 puts_P(PSTR(" Unable to get native func name."));
00338 return;
00339 }
00340 else
00341 {
00342 printf_P(PSTR(" %s() __NATIVE__\n"), ((pPmString_t)pstr)->val);
00343 }
00344
00345
00346 pframe = (pPmFrame_t)gVmGlobal.nativeframe.nf_back;
00347 }
00348
00349
00350 for (; pframe != C_NULL; pframe = pframe->fo_back)
00351 {
00352
00353 retval = tuple_getItem((pPmObj_t)pframe->fo_func->f_co->co_names,
00354 -1,
00355 &pstr);
00356 if ((retval) != PM_RET_OK) break;
00357
00358
00359
00360
00361
00362 bcindex = pframe->fo_ip - pframe->fo_func->f_co->co_codeaddr;
00363 plnotab = pframe->fo_func->f_co->co_lnotab;
00364 len_lnotab = mem_getWord(MEMSPACE_PROG, &plnotab);
00365 bcsum = 0;
00366 linesum = pframe->fo_func->f_co->co_firstlineno;
00367 for (i = 0; i < len_lnotab; i += 2)
00368 {
00369 bcsum += mem_getByte(MEMSPACE_PROG, &plnotab);
00370 if (bcsum > bcindex) break;
00371 linesum += mem_getByte(MEMSPACE_PROG, &plnotab);
00372 }
00373
00374
00375 if (pframe->fo_func->f_co->co_memspace == MEMSPACE_PROG)
00376 {
00377 strncpy_P(pstrbuf,
00378 (char *)pframe->fo_func->f_co->co_filename,
00379 MAX(FN_MAX_LEN, EXN_MAX_LEN));
00380 }
00381 printf_P(PSTR(" File \"%s\", line %d, in %s\n"),
00382 ((pframe->fo_func->f_co->co_memspace == MEMSPACE_PROG)
00383 ? pstrbuf
00384 : (char *)pframe->fo_func->f_co->co_filename),
00385 linesum,
00386 ((pPmString_t)pstr)->val);
00387 }
00388
00389
00390 res = (uint8_t)result;
00391 if ((res > 0) && ((res - PM_RET_EX) < LEN_EXNLOOKUP))
00392 {
00393 strncpy_P(pstrbuf,
00394 (PGM_P)pgm_read_word(&exnlookup[res - PM_RET_EX]),
00395 EXN_MAX_LEN);
00396 printf_P(PSTR("%s"), pstrbuf);
00397 }
00398 else
00399 {
00400 printf_P(PSTR("Error code 0x%02X"), result);
00401 }
00402 printf_P(PSTR(" detected by "));
00403
00404 if ((gVmGlobal.errFileId > 0) && (gVmGlobal.errFileId < LEN_FNLOOKUP))
00405 {
00406 strncpy_P(pstrbuf,
00407 (PGM_P)pgm_read_word(&fnlookup[gVmGlobal.errFileId]),
00408 FN_MAX_LEN);
00409 printf_P(PSTR("%s:"), pstrbuf);
00410 }
00411 else
00412 {
00413 printf_P(PSTR("FileId 0x%02X line "), gVmGlobal.errFileId);
00414 }
00415 printf_P(PSTR("%d\n"), gVmGlobal.errLineNum);
00416
00417 #else
00418
00419
00420 printf_P(PSTR("Error: 0x%02X\n"), result);
00421 printf_P(PSTR(" Release: 0x%02X\n"), gVmGlobal.errVmRelease);
00422 printf_P(PSTR(" FileId: 0x%02X\n"), gVmGlobal.errFileId);
00423 printf_P(PSTR(" LineNum: %d\n"), gVmGlobal.errLineNum);
00424
00425
00426 {
00427 pPmObj_t pframe;
00428 pPmObj_t pstr;
00429 PmReturn_t retval;
00430
00431 puts_P(PSTR("Traceback (top first):"));
00432
00433
00434 pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
00435
00436
00437 if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
00438 {
00439
00440
00441 retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00442 f_co->co_names, -1, &pstr);
00443 if ((retval) != PM_RET_OK)
00444 {
00445 puts_P(PSTR(" Unable to get native func name."));
00446 return;
00447 }
00448 else
00449 {
00450 printf_P(PSTR(" %s() __NATIVE__\n"), ((pPmString_t)pstr)->val);
00451 }
00452
00453
00454 pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
00455 }
00456
00457
00458 for (;
00459 pframe != C_NULL;
00460 pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
00461 {
00462
00463 retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
00464 fo_func->f_co->co_names, -1, &pstr);
00465 if ((retval) != PM_RET_OK) break;
00466
00467 printf_P(PSTR(" %s()\n"), ((pPmString_t)pstr)->val);
00468 }
00469 puts_P(PSTR(" <module>."));
00470 }
00471 #endif
00472 }