booter.c

Description | Download | Table of Contents | Modules | Compound List | File List | Functions


Overview
Compiler
Documentation
Examples
Misc
Help
IDE & Tools

Download
Install

Links
Projects






00001 /* booter.c -- External RAM booter
00002    Copyright 2000, 2001 Free Software Foundation, Inc.
00003    Written by Stephane Carrez (stcarrez@worldnet.fr)
00004 
00005 This file is part of GTAM.
00006 
00007 GTAM is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2, or (at your option)
00010 any later version.
00011 
00012 GTAM is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GTAM; see the file COPYING.  If not, write to
00019 the Free Software Foundation, 59 Temple Place - Suite 330,
00020 Boston, MA 02111-1307, USA.  */
00021 
00076 #include <sys/ports.h>
00077 
00078 typedef void __attribute__ ((noreturn)) (* func)();
00079 
00080 static unsigned short get_char ();
00081 static unsigned char* get_addr ();
00082 static void restart ();
00083 static volatile int __attribute__((noreturn)) main ();
00084 static void flush ();
00085 
00086 void
00087 _start()
00088 {
00089   /* Switch to 9600 baud.  */
00090   flush ();
00091 #if 0
00092   _io_ports[M6811_BAUD] = 0x30;
00093 #endif
00094   set_bus_expanded ();
00095 
00096   __asm__ __volatile__ ("bra main");
00097   /* main (); */
00098 }
00099 
00100 static void
00101 flush ()
00102 {
00103   while (!(_io_ports[M6811_SCSR] & M6811_TDRE))
00104     continue;
00105 }
00106 
00107 static void
00108 put_char (unsigned char c)
00109 {
00110   flush ();
00111   _io_ports[M6811_SCDR] = c;
00112   _io_ports[M6811_SCCR2] |= M6811_TE;
00113 }
00114 
00115 static volatile int
00116 main ()
00117 {
00118   volatile unsigned char* addr;
00119   unsigned char c;
00120   
00121   while (1)
00122     {
00123       /* Print banner for synchronization.  */
00124       put_char ('\n');
00125       put_char ('>');
00126 
00127       /* Wait for command.  */
00128       c = get_char ();
00129 
00130       /* Write memory command.  Command format is:
00131 
00132          M<ADDR-HIGH><ADDR-LOW><SIZE>[<DATA>]
00133 
00134          Address, size and data are passed in binary form.
00135          A size of 0 corresponds to 256 bytes.
00136          
00137          After writing the memory, we read it back and compute
00138          a crc that is then returned.  */
00139       if (c == 'M')
00140         {
00141           unsigned char crc;
00142           unsigned char size;
00143           
00144           addr = get_addr ();
00145           size = get_char ();
00146           crc = 0;
00147           do
00148             {
00149               *addr = get_char ();
00150               crc ^= *addr++;
00151             }
00152           while (--size != 0);
00153 
00154           /* Report the crc in pseudo hexa.  GTAM checks the crc to verify
00155              that what was written is correct.  */
00156           put_char (((crc >> 4) & 0x0F) + '0');
00157           put_char ((crc & 0x0F) + '0');
00158         }
00159 
00160       /* Go command.  Command format is:
00161 
00162          G<ADDR-HIGH><ADDR-LOW>
00163 
00164          We reply with a G.  Depending on the program, the final \n
00165          may not be received since we don't wait for it to be sent.  */
00166       else if (c == 'G')
00167         {
00168           func handler;
00169             
00170           addr = get_addr ();
00171           put_char ('G');
00172           put_char ('\n');
00173           flush ();
00174 
00175           handler = (func) addr;
00176           handler ();
00177         }
00178 
00179       /* For others, emit something to tell we are alive.  */
00180       else
00181         {
00182           put_char ('?');
00183         }
00184     }
00185 }
00186 
00187 static unsigned char*
00188 get_addr ()
00189 {
00190   unsigned short c1, c2;
00191 
00192   c1 = get_char ();
00193   c2 = get_char ();
00194   return (unsigned char*) (((unsigned short) c1 << 8) | ((unsigned short) c2));
00195 }
00196 
00197 static inline void
00198 restart ()
00199 {
00200   volatile unsigned char* ports = &_io_ports[0];
00201 
00202   /* Wait for the transmitter to be ready.  */
00203   while (!(ports[M6811_SCSR] & M6811_TDRE))
00204     continue;
00205   
00206   /* Send a break.  */
00207   ports[M6811_SCCR2] |= M6811_SBK;
00208 
00209   /* Wait some time (??? is it necessary ???).  */
00210 #if 0
00211   for (i = 1000; --i != 0;)
00212     (void) ports[M6811_TCTN];
00213 #endif
00214   ports[M6811_SCCR2] &= ~M6811_SBK;
00215 
00216   /* Go back to the main with some longjump.  We can't go to _start()
00217      because it was clobbered by the ZTMP and ZREG registers.  */
00218   __asm__ __volatile__ ("lds #0x0ff");
00219   __asm__ __volatile__ ("bra main");
00220 }
00221 
00222 static unsigned short
00223 get_char ()
00224 {
00225   unsigned char c;
00226   volatile unsigned char* ports = &_io_ports[0];
00227   
00228   while (1)
00229     {
00230       c = ports[M6811_SCSR];
00231 
00232       /* If there is a read error or a break, abort everything and
00233          restart.  When restarting we send a break so that the host
00234          knows we are restarting.  */
00235       if (c & M6811_FE)
00236         restart ();
00237 
00238       if (c & M6811_RDRF)
00239         break;
00240     }
00241   return ports[M6811_SCDR];
00242 }

Description | Download | Table of Contents | Modules | Compound List | File List | Functions

    Last modified,
    Apr 16, 2001
[ Copying ]     [ Feedback to Stephane.Carrez@worldnet.fr ]