plat.c

00001 /*
00002 # This file is Copyright 2006, 2007, 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 <stdio.h>
00024 #include <unistd.h>
00025 #include <signal.h>
00026 #include <string.h>
00027 
00028 #include "pm.h"
00029 
00030 
00031 void plat_sigalrm_handler(int signal);
00032 
00033 
00034 /* Desktop target shall use stdio for I/O routines. */
00035 PmReturn_t
00036 plat_init(void)
00037 {
00038     /* Let POSIX' SIGALRM fire every full millisecond. */
00039     /*
00040      * #67 Using sigaction complicates the use of getchar (below),
00041      * so signal() is used instead.
00042      */
00043     signal(SIGALRM, plat_sigalrm_handler);
00044     ualarm(1000, 1000);
00045 
00046     return PM_RET_OK;
00047 }
00048 
00049 
00050 /* Disables the peripherals and interrupts */
00051 PmReturn_t
00052 plat_deinit(void)
00053 {
00054     /* Cancel alarm and set the alarm handler to the default */
00055     ualarm(0, 0);
00056     signal(SIGALRM, SIG_DFL);
00057 
00058     return PM_RET_OK;
00059 }
00060 
00061 
00062 void
00063 plat_sigalrm_handler(int signal)
00064 {
00065     PmReturn_t retval;
00066     retval = pm_vmPeriodic(1000);
00067     PM_REPORT_IF_ERROR(retval);
00068 }
00069 
00070 
00071 /*
00072  * Gets a byte from the address in the designated memory space
00073  * Post-increments *paddr.
00074  */
00075 uint8_t
00076 plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
00077 {
00078     uint8_t b = 0;
00079 
00080     switch (memspace)
00081     {
00082         case MEMSPACE_RAM:
00083         case MEMSPACE_PROG:
00084             b = **paddr;
00085             *paddr += 1;
00086             return b;
00087 
00088         case MEMSPACE_EEPROM:
00089         case MEMSPACE_SEEPROM:
00090         case MEMSPACE_OTHER0:
00091         case MEMSPACE_OTHER1:
00092         case MEMSPACE_OTHER2:
00093         case MEMSPACE_OTHER3:
00094         default:
00095             return 0;
00096     }
00097 }
00098 
00099 
00100 /* Desktop target shall use stdio for I/O routines */
00101 PmReturn_t
00102 plat_getByte(uint8_t *b)
00103 {
00104     int c;
00105     PmReturn_t retval = PM_RET_OK;
00106 
00107     c = getchar();
00108     *b = c & 0xFF;
00109 
00110     if (c == EOF)
00111     {
00112         PM_RAISE(retval, PM_RET_EX_IO);
00113     }
00114 
00115     return retval;
00116 }
00117 
00118 
00119 /* Desktop target shall use stdio for I/O routines */
00120 PmReturn_t
00121 plat_putByte(uint8_t b)
00122 {
00123     int i;
00124     PmReturn_t retval = PM_RET_OK;
00125 
00126     i = putchar(b);
00127     fflush(stdout);
00128 
00129     if ((i != b) || (i == EOF))
00130     {
00131         PM_RAISE(retval, PM_RET_EX_IO);
00132     }
00133 
00134     return retval;
00135 }
00136 
00137 
00138 PmReturn_t
00139 plat_getMsTicks(uint32_t *r_ticks)
00140 {
00141     *r_ticks = pm_timerMsTicks;
00142 
00143     return PM_RET_OK;
00144 }
00145 
00146 
00147 void
00148 plat_reportError(PmReturn_t result)
00149 {
00150 
00151 #ifdef HAVE_DEBUG_INFO
00152 #define LEN_FNLOOKUP 26
00153 #define LEN_EXNLOOKUP 17
00154 
00155     uint8_t res;
00156     pPmFrame_t pframe;
00157     pPmObj_t pstr;
00158     PmReturn_t retval;
00159     uint8_t bcindex;
00160     uint16_t bcsum;
00161     uint16_t linesum;
00162     uint16_t len_lnotab;
00163     uint8_t const *plnotab;
00164     uint16_t i;
00165 
00166     /* This table should match src/vm/fileid.txt */
00167     char const * const fnlookup[LEN_FNLOOKUP] = {
00168         "<no file>",
00169         "codeobj.c",
00170         "dict.c",
00171         "frame.c",
00172         "func.c",
00173         "global.c",
00174         "heap.c",
00175         "img.c",
00176         "int.c",
00177         "interp.c",
00178         "pmstdlib_nat.c",
00179         "list.c",
00180         "main.c",
00181         "mem.c",
00182         "module.c",
00183         "obj.c",
00184         "seglist.c",
00185         "sli.c",
00186         "strobj.c",
00187         "tuple.c",
00188         "seq.c",
00189         "pm.c",
00190         "thread.c",
00191         "float.c",
00192         "class.c",
00193         "bytearray.c",
00194     };
00195 
00196     /* This table should match src/vm/pm.h PmReturn_t */
00197     char const * const exnlookup[LEN_EXNLOOKUP] = {
00198         "Exception",
00199         "SystemExit",
00200         "IoError",
00201         "ZeroDivisionError",
00202         "AssertionError",
00203         "AttributeError",
00204         "ImportError",
00205         "IndexError",
00206         "KeyError",
00207         "MemoryError",
00208         "NameError",
00209         "SyntaxError",
00210         "SystemError",
00211         "TypeError",
00212         "ValueError",
00213         "StopIteration",
00214         "Warning",
00215     };
00216 
00217     /* Print traceback */
00218     printf("Traceback (most recent call first):\n");
00219 
00220     /* Get the top frame */
00221     pframe = gVmGlobal.pthread->pframe;
00222 
00223     /* If it's the native frame, print the native function name */
00224     if (pframe == (pPmFrame_t)&(gVmGlobal.nativeframe))
00225     {
00226 
00227         /* The last name in the names tuple of the code obj is the name */
00228         retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00229                                f_co->co_names, -1, &pstr);
00230         if ((retval) != PM_RET_OK)
00231         {
00232             printf("  Unable to get native func name.\n");
00233             return;
00234         }
00235         else
00236         {
00237             printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
00238         }
00239 
00240         /* Get the frame that called the native frame */
00241         pframe = (pPmFrame_t)gVmGlobal.nativeframe.nf_back;
00242     }
00243 
00244     /* Print the remaining frame stack */
00245     for (; pframe != C_NULL; pframe = pframe->fo_back)
00246     {
00247         /* The last name in the names tuple of the code obj is the name */
00248         retval = tuple_getItem((pPmObj_t)pframe->fo_func->f_co->co_names,
00249                                -1,
00250                                &pstr);
00251         if ((retval) != PM_RET_OK) break;
00252 
00253         /*
00254          * Get the line number of the current bytecode. Algorithm comes from:
00255          * http://svn.python.org/view/python/trunk/Objects/lnotab_notes.txt?view=markup
00256          */
00257         bcindex = pframe->fo_ip - pframe->fo_func->f_co->co_codeaddr;
00258         plnotab = pframe->fo_func->f_co->co_lnotab;
00259         len_lnotab = mem_getWord(MEMSPACE_PROG, &plnotab);
00260         bcsum = 0;
00261         linesum = pframe->fo_func->f_co->co_firstlineno;
00262         for (i = 0; i < len_lnotab; i += 2)
00263         {
00264             bcsum += mem_getByte(MEMSPACE_PROG, &plnotab);
00265             if (bcsum > bcindex) break;
00266             linesum += mem_getByte(MEMSPACE_PROG, &plnotab);
00267         }
00268         printf("  File \"%s\", line %d, in %s\n",
00269                ((pPmFrame_t)pframe)->fo_func->f_co->co_filename,
00270                linesum,
00271                ((pPmString_t)pstr)->val);
00272     }
00273 
00274     /* Print error */
00275     res = (uint8_t)result;
00276     if ((res > 0) && ((res - PM_RET_EX) < LEN_EXNLOOKUP))
00277     {
00278         printf("%s", exnlookup[res - PM_RET_EX]);
00279     }
00280     else
00281     {
00282         printf("Error code 0x%02X", result);
00283     }
00284     printf(" detected by ");
00285 
00286     if ((gVmGlobal.errFileId > 0) && (gVmGlobal.errFileId < LEN_FNLOOKUP))
00287     {
00288         printf("%s:", fnlookup[gVmGlobal.errFileId]);
00289     }
00290     else
00291     {
00292         printf("FileId 0x%02X line ", gVmGlobal.errFileId);
00293     }
00294     printf("%d\n", gVmGlobal.errLineNum);
00295 
00296 #else /* HAVE_DEBUG_INFO */
00297 
00298     /* Print error */
00299     printf("Error:     0x%02X\n", result);
00300     printf("  Release: 0x%02X\n", gVmGlobal.errVmRelease);
00301     printf("  FileId:  0x%02X\n", gVmGlobal.errFileId);
00302     printf("  LineNum: %d\n", gVmGlobal.errLineNum);
00303 
00304     /* Print traceback */
00305     {
00306         pPmObj_t pframe;
00307         pPmObj_t pstr;
00308         PmReturn_t retval;
00309 
00310         printf("Traceback (top first):\n");
00311 
00312         /* Get the top frame */
00313         pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
00314 
00315         /* If it's the native frame, print the native function name */
00316         if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
00317         {
00318 
00319             /* The last name in the names tuple of the code obj is the name */
00320             retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00321                                    f_co->co_names, -1, &pstr);
00322             if ((retval) != PM_RET_OK)
00323             {
00324                 printf("  Unable to get native func name.\n");
00325                 return;
00326             }
00327             else
00328             {
00329                 printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
00330             }
00331 
00332             /* Get the frame that called the native frame */
00333             pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
00334         }
00335 
00336         /* Print the remaining frame stack */
00337         for (;
00338              pframe != C_NULL;
00339              pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
00340         {
00341             /* The last name in the names tuple of the code obj is the name */
00342             retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
00343                                    fo_func->f_co->co_names, -1, &pstr);
00344             if ((retval) != PM_RET_OK) break;
00345 
00346             printf("  %s()\n", ((pPmString_t)pstr)->val);
00347         }
00348         printf("  <module>.\n");
00349     }
00350 #endif /* HAVE_DEBUG_INFO */
00351 }
00352 

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