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 <avr/io.h>
00025 #include <avr/interrupt.h>
00026 #include <avr/pgmspace.h>
00027 #include <avr/eeprom.h>
00028 #include <util/delay.h>
00029 
00030 #include "pm.h"
00031 #include "usb_serial.h"
00032 
00033 #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
00034 
00042 #define AVR_DEFAULT_TIMER_SOURCE
00043 
00044 
00045 #ifdef AVR_DEFAULT_TIMER_SOURCE
00046 
00047 /* Hint: 1,000,000 µs/s * 256 T/C0 clock cycles per tick * 64 CPU clocks per
00048  * T/C0 clock cycle / x,000,000 CPU clock cycles per second -> µs per tick
00049  */
00050 #define PLAT_TIME_PER_TICK_USEC (1000000ULL*256ULL*64ULL/F_CPU)
00051 
00052 #endif /* AVR_DEFAULT_TIMER_SOURCE */
00053 
00054 
00055 /* Configure stdin, stdout, stderr */
00056 static int uart_putc(char c, FILE *stream);
00057 static int uart_getc(FILE *stream);
00058 FILE avr_uart = FDEV_SETUP_STREAM(uart_putc, uart_getc, _FDEV_SETUP_RW);
00059 
00060 
00061 /*
00062  * AVR target shall use stdio for I/O routines.
00063  * The UART or USART must be configured for the interactive interface to work.
00064  */
00065 PmReturn_t
00066 plat_init(void)
00067 {
00068     CPU_PRESCALE(0);
00069     usb_init();
00070     while(!usb_configured()) _delay_ms(1);
00071 
00072     stdin = stdout = stderr = &avr_uart;
00073 
00074 #ifdef AVR_DEFAULT_TIMER_SOURCE
00075     /* PORT BEGIN: Configure a timer that fits your needs. */
00076     /* Use T/C0 in synchronous mode, aim for a tick rate of
00077      * several hundred Hz */
00078     /* set prescaler to /64 */
00079     TCCR0B |= (1<<CS01) | (1<<CS00); // (this should be all you need for AT90USBxxx)
00080     TIMSK0 |= (1<<TOIE0);
00081 #endif
00082 
00083     return PM_RET_OK;
00084 }
00085 
00086 
00087 PmReturn_t
00088 plat_deinit(void)
00089 {
00090 #ifdef AVR_DEFAULT_TIMER_SOURCE
00091     /* Disable Timer */
00092     TCCR0B = 0;
00093     TIMSK0 &= ~(1<<TOIE0);
00094 #endif
00095 
00096     usb_serial_flush_input();
00097     usb_serial_flush_output();
00098     _delay_ms(5000);
00099 
00100     return PM_RET_OK;
00101 }
00102 
00103 
00104 #ifdef AVR_DEFAULT_TIMER_SOURCE
00105 ISR(TIMER0_OVF_vect)
00106 {
00107     /* TODO Find a clever way to handle bad return code, maybe use
00108      * PM_REPORT_IF_ERROR(retval) when that works on AVR inside an
00109      * interrupt.
00110      */
00111     pm_vmPeriodic(PLAT_TIME_PER_TICK_USEC);
00112 }
00113 #endif
00114 
00115 
00116 /*
00117  * Gets a byte from the address in the designated memory space
00118  * Post-increments *paddr.
00119  */
00120 uint8_t
00121 plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
00122 {
00123     uint8_t b = 0;
00124 
00125     switch (memspace)
00126     {
00127         case MEMSPACE_RAM:
00128             b = **paddr;
00129             *paddr += 1;
00130             return b;
00131 
00132         case MEMSPACE_PROG:
00133             b = pgm_read_byte(*paddr);
00134             *paddr += 1;
00135             return b;
00136 
00137         case MEMSPACE_EEPROM:
00138             b = eeprom_read_byte(*paddr);
00139             *paddr += 1;
00140             return b;
00141 
00142         case MEMSPACE_SEEPROM:
00143         case MEMSPACE_OTHER0:
00144         case MEMSPACE_OTHER1:
00145         case MEMSPACE_OTHER2:
00146         case MEMSPACE_OTHER3:
00147         default:
00148             return 0;
00149     }
00150 }
00151 
00152 
00153 static int
00154 uart_getc(FILE *stream)
00155 {
00156     int c = usb_serial_getchar();
00157     return (c == -1) ? _FDEV_ERR : c;
00158 }
00159 
00160 
00161 static int
00162 uart_putc(char c, FILE *stream)
00163 {
00164     return usb_serial_putchar(c) == 0 ? 0 : _FDEV_ERR;
00165 }
00166 
00167 
00168 /*
00169  * UART receive char routine MUST return exactly and only the received char;
00170  * it should not translate \n to \r\n.
00171  * This is because the interactive interface uses binary transfers.
00172  */
00173 PmReturn_t
00174 plat_getByte(uint8_t *b)
00175 {
00176     PmReturn_t retval = PM_RET_OK;
00177 
00178     int c = usb_serial_getchar();
00179     if(c == -1)
00180     {
00181         PM_RAISE(retval, PM_RET_EX_IO);
00182         return retval;
00183     }
00184     *b = c;
00185     return retval;
00186 }
00187 
00188 
00189 /*
00190  * UART send char routine MUST send exactly and only the given char;
00191  * it should not translate \n to \r\n.
00192  * This is because the interactive interface uses binary transfers.
00193  */
00194 PmReturn_t
00195 plat_putByte(uint8_t b)
00196 {
00197     PmReturn_t retval = PM_RET_OK;
00198     if(usb_serial_putchar(b) == 0)
00199     {
00200         return retval;
00201     }
00202     else
00203     {
00204         PM_RAISE(retval, PM_RET_EX_IO);
00205         return retval;
00206     }
00207 }
00208 
00209 
00210 /*
00211  * This operation is made atomic by temporarily disabling
00212  * the interrupts. The old state is restored afterwards.
00213  */
00214 PmReturn_t
00215 plat_getMsTicks(uint32_t *r_ticks)
00216 {
00217     /* Critical section start */
00218     unsigned char _sreg = SREG;
00219     cli();
00220     *r_ticks = pm_timerMsTicks;
00221     SREG = _sreg;
00222     /* Critical section end */
00223     return PM_RET_OK;
00224 }
00225 
00226 
00227 void
00228 plat_reportError(PmReturn_t result)
00229 {
00230     /* Print error */
00231     printf_P(PSTR("Error:     0x%02X\n"), result);
00232     printf_P(PSTR("  Release: 0x%02X\n"), gVmGlobal.errVmRelease);
00233     printf_P(PSTR("  FileId:  0x%02X\n"), gVmGlobal.errFileId);
00234     printf_P(PSTR("  LineNum: %d\n"), gVmGlobal.errLineNum);
00235 
00236     /* Print traceback */
00237     {
00238         pPmObj_t pframe;
00239         pPmObj_t pstr;
00240         PmReturn_t retval;
00241 
00242         puts_P(PSTR("Traceback (top first):"));
00243 
00244         /* Get the top frame */
00245         pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
00246 
00247         /* If it's the native frame, print the native function name */
00248         if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
00249         {
00250 
00251             /* The last name inthe names tuple of the code obj is the name */
00252             retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00253                                    f_co->co_names, -1, &pstr);
00254             if ((retval) != PM_RET_OK)
00255             {
00256                 puts_P(PSTR("  Unable to get native func name."));
00257                 return;
00258             }
00259             else
00260             {
00261                 printf_P(PSTR("  %s() __NATIVE__\n"), ((pPmString_t)pstr)->val);
00262             }
00263 
00264             /* Get the frame that called the native frame */
00265             pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
00266         }
00267 
00268         /* Print the remaining frame stack */
00269         for (;
00270              pframe != C_NULL;
00271              pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
00272         {
00273             /* The last name in the names tuple of the code obj is the name */
00274             retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
00275                                    fo_func->f_co->co_names, -1, &pstr);
00276             if ((retval) != PM_RET_OK) break;
00277 
00278             printf_P(PSTR("  %s()\n"), ((pPmString_t)pstr)->val);
00279         }
00280         puts_P(PSTR("  <module>."));
00281     }
00282 }

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