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

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