jtag_gpio0.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 2009 by egnite GmbH
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * Initially the code had been taken from the GPL'ed JTAG-O-MAT project.
00031  * Its author explicitly confirmed to publish this under BSDL.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00047 #include <cfg/arch/gpio.h>
00048 #include <cfg/progif.h>
00049 
00050 #include <sys/timer.h>
00051 #include <stdlib.h>
00052 
00053 #include <dev/jtag_gpio.h>
00054 
00055 #if defined(ETHERNUT3)
00056 /*
00057  * We do not have any config settings right now. So I add my
00058  * Ethernut 3 settings here, which I used for testing the code.
00059  *
00060  * - P16 TMS output.
00061  * - P18 TCK output.
00062  * - P19 TDO input.
00063  * - P20 RST output.
00064  * - P23 TDI output.
00065  */
00066 #define JTAG0_TDO_PIO_BIT   19
00067 #define JTAG0_TDI_PIO_BIT   23
00068 #define JTAG0_TMS_PIO_BIT   16
00069 #define JTAG0_TCK_PIO_BIT   18
00070 #define JTAG0_CLOCK_RATE    100000
00071 #endif
00072 
00073 #if !defined(JTAG0_TDO_PIO_ID) && defined(PIO_ID)
00074 #define JTAG0_TDO_PIO_ID    PIO_ID
00075 #endif
00076 #if defined(JTAG0_TDO_PIO_BIT) && defined(JTAG0_TDO_PIO_ID)
00077 #undef GPIO_ID
00078 #define GPIO_ID JTAG0_TDO_PIO_ID
00079 #include <cfg/arch/porttran.h>
00080 static INLINE int JTAG0_TDO_IS_ON(void) { return GPIO_GET(JTAG0_TDO_PIO_BIT); }
00081 static INLINE void JTAG0_TDO_SI(void) { GPIO_INPUT(JTAG0_TDO_PIO_BIT); GPIO_ENABLE(JTAG0_TDO_PIO_BIT); }
00082 #else
00083 #define JTAG0_TDO_IS_ON()   (1)
00084 #define JTAG0_TDO_SI()
00085 #endif
00086 
00087 #if !defined(JTAG0_TDI_PIO_ID) && defined(PIO_ID)
00088 #define JTAG0_TDI_PIO_ID    PIO_ID
00089 #endif
00090 #if defined(JTAG0_TDI_PIO_BIT) && defined(JTAG0_TDI_PIO_ID)
00091 #undef GPIO_ID
00092 #define GPIO_ID JTAG0_TDI_PIO_ID
00093 #include <cfg/arch/porttran.h>
00094 static INLINE void JTAG0_TDI_LO(void) { GPIO_SET_LO(JTAG0_TDI_PIO_BIT); }
00095 static INLINE void JTAG0_TDI_HI(void) { GPIO_SET_HI(JTAG0_TDI_PIO_BIT); }
00096 static INLINE void JTAG0_TDI_SO(void) { GPIO_OUTPUT(JTAG0_TDI_PIO_BIT); GPIO_ENABLE(JTAG0_TDI_PIO_BIT); }
00097 #else
00098 #define JTAG0_TDI_LO()
00099 #define JTAG0_TDI_HI()
00100 #define JTAG0_TDI_SO()
00101 #endif
00102 
00103 #if !defined(JTAG0_TMS_PIO_ID) && defined(PIO_ID)
00104 #define JTAG0_TMS_PIO_ID    PIO_ID
00105 #endif
00106 #if defined(JTAG0_TMS_PIO_BIT) && defined(JTAG0_TMS_PIO_ID)
00107 #undef GPIO_ID
00108 #define GPIO_ID JTAG0_TMS_PIO_ID
00109 #include <cfg/arch/porttran.h>
00110 static INLINE void JTAG0_TMS_LO(void) { GPIO_SET_LO(JTAG0_TMS_PIO_BIT); }
00111 static INLINE void JTAG0_TMS_HI(void) { GPIO_SET_HI(JTAG0_TMS_PIO_BIT); }
00112 static INLINE void JTAG0_TMS_SO(void) { GPIO_OUTPUT(JTAG0_TMS_PIO_BIT); GPIO_ENABLE(JTAG0_TMS_PIO_BIT); }
00113 #else
00114 #define JTAG0_TMS_LO()
00115 #define JTAG0_TMS_HI()
00116 #define JTAG0_TMS_SO()
00117 #endif
00118 
00119 #if !defined(JTAG0_TCK_PIO_ID) && defined(PIO_ID)
00120 #define JTAG0_TCK_PIO_ID    PIO_ID
00121 #endif
00122 #if defined(JTAG0_TCK_PIO_BIT) && defined(JTAG0_TCK_PIO_ID)
00123 #undef GPIO_ID
00124 #define GPIO_ID JTAG0_TCK_PIO_ID
00125 #include <cfg/arch/porttran.h>
00126 static INLINE void JTAG0_TCK_LO(void) { GPIO_SET_LO(JTAG0_TCK_PIO_BIT); }
00127 static INLINE void JTAG0_TCK_HI(void) { GPIO_SET_HI(JTAG0_TCK_PIO_BIT); }
00128 static INLINE void JTAG0_TCK_SO(void) { GPIO_OUTPUT(JTAG0_TCK_PIO_BIT); GPIO_ENABLE(JTAG0_TCK_PIO_BIT); }
00129 #else
00130 #define JTAG0_TCK_LO()
00131 #define JTAG0_TCK_HI()
00132 #define JTAG0_TCK_SO()
00133 #endif
00134 
00135 #if !defined(JTAG0_NSRST_PIO_ID) && defined(PIO_ID)
00136 #define JTAG0_NSRST_PIO_ID    PIO_ID
00137 #endif
00138 #if defined(JTAG0_NSRST_PIO_BIT) && defined(JTAG0_NSRST_PIO_ID)
00139 #undef GPIO_ID
00140 #define GPIO_ID JTAG0_NSRST_PIO_ID
00141 #include <cfg/arch/porttran.h>
00142 static INLINE void JTAG0_NSRST_LO(void) { GPIO_SET_LO(JTAG0_NSRST_PIO_BIT); }
00143 static INLINE void JTAG0_NSRST_HI(void) { GPIO_SET_HI(JTAG0_NSRST_PIO_BIT); }
00144 static INLINE void JTAG0_NSRST_SO(void) { GPIO_OPENDRAIN(JTAG0_NSRST_PIO_BIT); GPIO_OUTPUT(JTAG0_NSRST_PIO_BIT); GPIO_ENABLE(JTAG0_NSRST_PIO_BIT); }
00145 #else
00146 #define JTAG0_NSRST_LO()
00147 #define JTAG0_NSRST_HI()
00148 #define JTAG0_NSRST_SO()
00149 #endif
00150 
00151 #if !defined(JTAG0_NTRST_PIO_ID) && defined(PIO_ID)
00152 #define JTAG0_NTRST_PIO_ID    PIO_ID
00153 #endif
00154 #if defined(JTAG0_NTRST_PIO_BIT) && defined(JTAG0_NTRST_PIO_ID)
00155 #undef GPIO_ID
00156 #define GPIO_ID JTAG0_NTRST_PIO_ID
00157 #include <cfg/arch/porttran.h>
00158 static INLINE void JTAG0_NTRST_LO(void) { GPIO_SET_LO(JTAG0_NTRST_PIO_BIT); }
00159 static INLINE void JTAG0_NTRST_HI(void) { GPIO_SET_HI(JTAG0_NTRST_PIO_BIT); }
00160 static INLINE void JTAG0_NTRST_SO(void) { GPIO_OPENDRAIN(JTAG0_NTRST_PIO_BIT); GPIO_OUTPUT(JTAG0_NTRST_PIO_BIT); GPIO_ENABLE(JTAG0_NTRST_PIO_BIT); }
00161 #else
00162 #define JTAG0_NTRST_LO()
00163 #define JTAG0_NTRST_HI()
00164 #define JTAG0_NTRST_SO()
00165 #endif
00166 
00167 #if defined(JTAG0_CLOCK_RATE) && (JTAG0_CLOCK_RATE <= 500000)
00168 #define JTAG0_CLOCK_DELAY()     NutMicroDelay(1000000 / JTAG0_CLOCK_RATE / 2)
00169 #else
00170 #define JTAG0_CLOCK_DELAY()
00171 #endif
00172 
00173 typedef struct {
00174     uint8_t cib_buf[256];
00175     int cib_bidx;
00176     int cib_bbit;
00177 } CABLE_INFO;
00178 
00185 static void *JtagCable0Open(void)
00186 {
00187     CABLE_INFO *cib;
00188 
00189     cib = calloc(1, sizeof(CABLE_INFO));
00190     if (cib) {
00191 #if defined(MCU_AT91) && defined(JTAG0_TDO_PIO_ID)
00192 #if defined(PS_PCER)
00193         outr(PS_PCER, _BV(JTAG0_TDO_PIO_ID));
00194 #elif defined(PMC_PCER)
00195         outr(PMC_PCER, _BV(JTAG0_TDO_PIO_ID));
00196 #endif
00197 #endif
00198         JTAG0_TDO_SI();
00199         JTAG0_TDI_SO();
00200         JTAG0_TMS_SO();
00201         JTAG0_TCK_SO();
00202         JTAG0_NSRST_SO();
00203         JTAG0_NTRST_SO();
00204     }
00205     return (void *)cib;
00206 }
00207 
00214 static void JtagCable0TmsFlush(void *cbl)
00215 {
00216     CABLE_INFO *cib = (CABLE_INFO *)cbl;
00217     uint_fast8_t tms;
00218     int i;
00219     int j;
00220     int n;
00221 
00222     n = cib->cib_bidx + (cib->cib_bbit == 0);
00223     for (i = 0; i < n; i++) {
00224         tms = cib->cib_buf[i];
00225         for (j = 8; j--;) {
00226             JTAG0_TCK_LO();
00227             if (tms & 1) {
00228                 JTAG0_TMS_HI();
00229             } else {
00230                 JTAG0_TMS_LO();
00231             }
00232             JTAG0_CLOCK_DELAY();
00233             tms >>= 1;
00234             JTAG0_TCK_HI();
00235             JTAG0_CLOCK_DELAY();
00236         }
00237     }
00238     if (cib->cib_bbit) {
00239         tms = cib->cib_buf[cib->cib_bidx];
00240         for (j = cib->cib_bbit; j--;) {
00241             JTAG0_TCK_LO();
00242             if (tms & 1) {
00243                 JTAG0_TMS_HI();
00244             } else {
00245                 JTAG0_TMS_LO();
00246             }
00247             JTAG0_CLOCK_DELAY();
00248             tms >>= 1;
00249             JTAG0_TCK_HI();
00250             JTAG0_CLOCK_DELAY();
00251         }
00252         cib->cib_bbit = 0;
00253     }
00254     cib->cib_bidx = 0;
00255 }
00256 
00266 static void JtagCable0Close(void *cbl)
00267 {
00268     JtagCable0TmsFlush(cbl);
00269     free(cbl);
00270 }
00271 
00283 static void JtagCable0TargetReset(void *cbl, uint_fast8_t on)
00284 {
00285     if (on) {
00286         JtagCable0TmsFlush(cbl);
00287         JTAG0_NSRST_LO();
00288     } else {
00289         JTAG0_NSRST_HI();
00290     }
00291 }
00292 
00304 static void JtagCable0TmsPut(void *cbl, uint_fast8_t tms, uint_fast8_t len)
00305 {
00306     CABLE_INFO *cib = (CABLE_INFO *)cbl;
00307     int bbit;
00308     uint_fast8_t byte;
00309 
00310     bbit = cib->cib_bbit;
00311     while (len) {
00312         if (bbit) {
00313             byte = cib->cib_buf[cib->cib_bidx];
00314         } else {
00315             byte = 0;
00316         }
00317         while (len && bbit < 8) {
00318             if (tms & 1) {
00319                 byte |= 1 << bbit;
00320             }
00321             tms >>= 1;
00322             bbit++;
00323             len--;
00324         }
00325         cib->cib_buf[cib->cib_bidx] = (uint8_t)byte;
00326         if (bbit >= 8) {
00327             cib->cib_bidx++;
00328             if (cib->cib_bidx >= sizeof(cib->cib_buf)) {
00329                 JtagCable0TmsFlush(cbl);
00330             }
00331             bbit = 0;
00332         }
00333     }
00334     cib->cib_bbit = bbit;
00335 }
00336 
00354 static void JtagCable0TransferData(void *cbl, uint8_t *rbuf, CONST uint8_t *wbuf, uint32_t len, uint_fast8_t last)
00355 {
00356     JtagCable0TmsFlush(cbl);
00357 
00358     while (len) {
00359         uint8_t mask = 1;
00360         uint8_t val = 0;
00361 
00362         if (wbuf) {
00363             val = *wbuf++;
00364         }
00365     
00366         while (len && mask) {
00367             JTAG0_TCK_LO();
00368             if (val & mask) {
00369                 JTAG0_TDI_HI();
00370             } else {
00371                 JTAG0_TDI_LO();
00372             }
00373             if (--len || !last) {
00374                 JTAG0_TMS_LO();
00375             } else {
00376                 JTAG0_TMS_HI();
00377             }
00378             JTAG0_CLOCK_DELAY();
00379             JTAG0_TCK_HI();
00380             JTAG0_CLOCK_DELAY();
00381             if (JTAG0_TDO_IS_ON()) {
00382                 val |= mask;
00383             } else {
00384                 val &= ~mask;
00385             }
00386             mask <<= 1;
00387         }
00388 
00389         if (rbuf) {
00390             *rbuf++ = val;
00391         }
00392     }
00393 }
00394 
00401 JTAG_CABLE jtag_gpio0 = {
00402     JtagCable0Open, /* cable_open */
00403     JtagCable0Close, /* cable_close */
00404     JtagCable0TargetReset, /* cable_reset_target */
00405     JtagCable0TmsPut, /* cable_tms_put */
00406     JtagCable0TmsFlush, /* cable_tms_flush */
00407     JtagCable0TransferData /* cable_transfer_data */
00408 };

© 2000-2010 by contributors - visit http://www.ethernut.de/