plat.cpp

00001 /*
00002 # This file is Copyright 2009 Dean Hall.
00003 #
00004 # This file is part of the Python-on-a-Chip program.
00005 # Python-on-a-Chip is free software: you can redistribute it and/or modify
00006 # it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1.
00007 #
00008 # Python-on-a-Chip is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00011 # A copy of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1
00012 # is seen in the file COPYING up one directory from this.
00013 */
00014 
00015 
00016 #undef __FILE_ID__
00017 #define __FILE_ID__ 0x70
00018 
00019 
00023 #include "mbed.h"
00024 #include "pm.h"
00025 
00026 
00027 #define CALLBACK_MS 10
00028 
00029 
00030 Serial serial(USBTX, USBRX, "serial");
00031 Ticker ticker;
00032 
00033 
00034 static void
00035 ticker_callback(void)
00036 {
00037     PmReturn_t retval;
00038 
00039     retval = pm_vmPeriodic(CALLBACK_MS * 1000);
00040     PM_REPORT_IF_ERROR(retval);
00041 }
00042 
00043 
00044 PmReturn_t
00045 plat_init(void)
00046 {
00047     serial.baud(19200);
00048     serial.format(8, serial.None, 1);
00049 
00050     ticker.attach_us(ticker_callback, CALLBACK_MS * 1000);
00051 
00052     return PM_RET_OK;
00053 }
00054 
00055 
00056 PmReturn_t
00057 plat_deinit(void)
00058 {
00059     /* Detach the callback from the ticker */
00060     ticker.detach();
00061 
00062     return PM_RET_OK;
00063 }
00064 
00065 
00066 uint8_t
00067 plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
00068 {
00069     uint8_t b = 0;
00070 
00071     switch (memspace)
00072     {
00073         case MEMSPACE_RAM:
00074         case MEMSPACE_PROG:
00075             b = **paddr;
00076             *paddr += 1;
00077             return b;
00078 
00079         case MEMSPACE_EEPROM:
00080         case MEMSPACE_SEEPROM:
00081         case MEMSPACE_OTHER0:
00082         case MEMSPACE_OTHER1:
00083         case MEMSPACE_OTHER2:
00084         case MEMSPACE_OTHER3:
00085         default:
00086             return 0;
00087     }
00088 }
00089 
00090 
00091 PmReturn_t
00092 plat_getByte(uint8_t *b)
00093 {
00094     int c;
00095     PmReturn_t retval = PM_RET_OK;
00096 
00097     c = serial.getc();
00098     *b = c & 0xFF;
00099 
00100     if (c > 0xFF)
00101     {
00102         PM_RAISE(retval, PM_RET_EX_IO);
00103     }
00104 
00105     return retval;
00106 }
00107 
00108 
00109 PmReturn_t
00110 plat_putByte(uint8_t b)
00111 {
00112     while (!serial.writeable());
00113     serial.putc(b);
00114 
00115     return PM_RET_OK;
00116 }
00117 
00118 
00119 PmReturn_t
00120 plat_getMsTicks(uint32_t *r_ticks)
00121 {
00122     *r_ticks = pm_timerMsTicks;
00123 
00124     return PM_RET_OK;
00125 }
00126 
00127 
00128 void
00129 plat_reportError(PmReturn_t result)
00130 {
00131 
00132 #ifdef HAVE_DEBUG_INFO
00133 #define LEN_FNLOOKUP 26
00134 #define LEN_EXNLOOKUP 17
00135 
00136     uint8_t res;
00137     pPmFrame_t pframe;
00138     pPmObj_t pstr;
00139     PmReturn_t retval;
00140     uint8_t bcindex;
00141     uint16_t bcsum;
00142     uint16_t linesum;
00143     uint16_t len_lnotab;
00144     uint8_t const *plnotab;
00145     uint16_t i;
00146 
00147     /* This table should match src/vm/fileid.txt */
00148     char const * const fnlookup[LEN_FNLOOKUP] = {
00149         "<no file>",
00150         "codeobj.c",
00151         "dict.c",
00152         "frame.c",
00153         "func.c",
00154         "global.c",
00155         "heap.c",
00156         "img.c",
00157         "int.c",
00158         "interp.c",
00159         "pmstdlib_nat.c",
00160         "list.c",
00161         "main.c",
00162         "mem.c",
00163         "module.c",
00164         "obj.c",
00165         "seglist.c",
00166         "sli.c",
00167         "strobj.c",
00168         "tuple.c",
00169         "seq.c",
00170         "pm.c",
00171         "thread.c",
00172         "float.c",
00173         "class.c",
00174         "bytearray.c",
00175     };
00176 
00177     /* This table should match src/vm/pm.h PmReturn_t */
00178     char const * const exnlookup[LEN_EXNLOOKUP] = {
00179         "Exception",
00180         "SystemExit",
00181         "IoError",
00182         "ZeroDivisionError",
00183         "AssertionError",
00184         "AttributeError",
00185         "ImportError",
00186         "IndexError",
00187         "KeyError",
00188         "MemoryError",
00189         "NameError",
00190         "SyntaxError",
00191         "SystemError",
00192         "TypeError",
00193         "ValueError",
00194         "StopIteration",
00195         "Warning",
00196     };
00197 
00198     /* Print traceback */
00199     printf("Traceback (most recent call first):\n");
00200 
00201     /* Get the top frame */
00202     pframe = gVmGlobal.pthread->pframe;
00203 
00204     /* If it's the native frame, print the native function name */
00205     if (pframe == (pPmFrame_t)&(gVmGlobal.nativeframe))
00206     {
00207 
00208         /* The last name in the names tuple of the code obj is the name */
00209         retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00210                                f_co->co_names, -1, &pstr);
00211         if ((retval) != PM_RET_OK)
00212         {
00213             printf("  Unable to get native func name.\n");
00214             return;
00215         }
00216         else
00217         {
00218             printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
00219         }
00220 
00221         /* Get the frame that called the native frame */
00222         pframe = (pPmFrame_t)gVmGlobal.nativeframe.nf_back;
00223     }
00224 
00225     /* Print the remaining frame stack */
00226     for (; pframe != C_NULL; pframe = pframe->fo_back)
00227     {
00228         /* The last name in the names tuple of the code obj is the name */
00229         retval = tuple_getItem((pPmObj_t)pframe->fo_func->f_co->co_names,
00230                                -1,
00231                                &pstr);
00232         if ((retval) != PM_RET_OK) break;
00233 
00234         /*
00235          * Get the line number of the current bytecode. Algorithm comes from:
00236          * http://svn.python.org/view/python/trunk/Objects/lnotab_notes.txt?view=markup
00237          */
00238         bcindex = pframe->fo_ip - pframe->fo_func->f_co->co_codeaddr;
00239         plnotab = pframe->fo_func->f_co->co_lnotab;
00240         len_lnotab = mem_getWord(MEMSPACE_PROG, &plnotab);
00241         bcsum = 0;
00242         linesum = pframe->fo_func->f_co->co_firstlineno;
00243         for (i = 0; i < len_lnotab; i += 2)
00244         {
00245             bcsum += mem_getByte(MEMSPACE_PROG, &plnotab);
00246             if (bcsum > bcindex) break;
00247             linesum += mem_getByte(MEMSPACE_PROG, &plnotab);
00248         }
00249         printf("  File \"%s\", line %d, in %s\n",
00250                ((pPmFrame_t)pframe)->fo_func->f_co->co_filename,
00251                linesum,
00252                ((pPmString_t)pstr)->val);
00253     }
00254 
00255     /* Print error */
00256     res = (uint8_t)result;
00257     if ((res > 0) && ((res - PM_RET_EX) < LEN_EXNLOOKUP))
00258     {
00259         printf("%s", exnlookup[res - PM_RET_EX]);
00260     }
00261     else
00262     {
00263         printf("Error code 0x%02X", result);
00264     }
00265     printf(" detected by ");
00266 
00267     if ((gVmGlobal.errFileId > 0) && (gVmGlobal.errFileId < LEN_FNLOOKUP))
00268     {
00269         printf("%s:", fnlookup[gVmGlobal.errFileId]);
00270     }
00271     else
00272     {
00273         printf("FileId 0x%02X line ", gVmGlobal.errFileId);
00274     }
00275     printf("%d\n", gVmGlobal.errLineNum);
00276 
00277 #else /* HAVE_DEBUG_INFO */
00278 
00279     /* Print error */
00280     printf("Error:     0x%02X\n", result);
00281     printf("  Release: 0x%02X\n", gVmGlobal.errVmRelease);
00282     printf("  FileId:  0x%02X\n", gVmGlobal.errFileId);
00283     printf("  LineNum: %d\n", gVmGlobal.errLineNum);
00284 
00285     /* Print traceback */
00286     {
00287         pPmObj_t pframe;
00288         pPmObj_t pstr;
00289         PmReturn_t retval;
00290 
00291         printf("Traceback (top first):\n");
00292 
00293         /* Get the top frame */
00294         pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
00295 
00296         /* If it's the native frame, print the native function name */
00297         if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
00298         {
00299 
00300             /* The last name in the names tuple of the code obj is the name */
00301             retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00302                                    f_co->co_names, -1, &pstr);
00303             if ((retval) != PM_RET_OK)
00304             {
00305                 printf("  Unable to get native func name.\n");
00306                 return;
00307             }
00308             else
00309             {
00310                 printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
00311             }
00312 
00313             /* Get the frame that called the native frame */
00314             pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
00315         }
00316 
00317         /* Print the remaining frame stack */
00318         for (;
00319              pframe != C_NULL;
00320              pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
00321         {
00322             /* The last name in the names tuple of the code obj is the name */
00323             retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
00324                                    fo_func->f_co->co_names, -1, &pstr);
00325             if ((retval) != PM_RET_OK) break;
00326 
00327             printf("  %s()\n", ((pPmString_t)pstr)->val);
00328         }
00329         printf("  <module>.\n");
00330     }
00331 #endif /* HAVE_DEBUG_INFO */
00332 }

Generated on Mon Oct 18 07:40:46 2010 for Python-on-a-chip by  doxygen 1.5.9