⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bdmcf.c

📁 bdm源代码. coldfire处理器用
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
    Turbo BDM Light ColdFire - bdm routines
    Copyright (C) 2005  Daniel Malik

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "MC68HC908JB16.h"
#include "options.h"
#include "bdmcf.h"
#include "timer.h"
#include "commands.h"
#include "cmd_processing.h"

#ifdef MULTIPLE_SPEEDS
  /* until more than one set of rx/tx functions is needed the speed of operation can be improved by not using the pointers */

  #pragma DATA_SEG Z_RAM
  /* pointers to Rx & Tx routines */
  unsigned char near (*bdmcf_rx8_ptr)(void) = bdmcf_rx8_1;
  void near (*bdmcf_tx8_ptr)(unsigned char) = bdmcf_tx8_1;
  unsigned char near (*bdmcf_txrx8_ptr)(unsigned char) = bdmcf_txrx8_1;
  unsigned char near (*bdmcf_txrx_start_ptr)(void) = bdmcf_txrx_start_1;

  #pragma DATA_SEG DEFAULT
  /* tables with pointers to Tx & Rx functions */
  unsigned char (* const bdmcf_rx8_ptrs[])(void)=
    {bdmcf_rx8_1};
  void (* const bdmcf_tx8_ptrs[])(unsigned char)=
    {bdmcf_tx8_1};
  unsigned char (* const bdmcf_txrx8_ptrs[])(unsigned char)=
    {bdmcf_txrx8_1};
  unsigned char (* const bdmcf_txrx_start_ptrs[])(void)=
    {bdmcf_txrx_start_1};

#endif

/* halts the target CPU (stops execution of the code and brings the part into BDM mode) */
void bdmcf_halt(void) {
  #ifdef INVERT
    BKPT_OUT=1;   /* assert BKPT */
  #else
    BKPT_OUT=0;
  #endif
  wait_10us(70);   /* wait 700us, this should be enough even for a target running at 2kHz clock and yet it is short enough to fit into a single USB slot */
  #ifdef INVERT
    BKPT_OUT=0;   /* deassert BKPT */
  #else
    BKPT_OUT=1;
  #endif
  bdmcf_complete_chk_rx();  /* added in revision 0.3 */
                            /* it is a workaround for a strange problem: CF CPU V2 seems to ignore the first transfer after a halt */
                            /* I do not admit I know why it happens, but the extra NOP command fixes the problem... */
                            /* the problem has nothing to do with the delay: adding up to 400ms of delay between the halt nad the read did not fix it */
}

/* resets the target CPU either into BDM mode (parameter bkpt=0) or into notmal mode (parameter bkpt!=0) */
/* length of the reset pulse is 50ms, if BKPT is to be asserted it is held active for 50ms after reset is released */
void bdmcf_reset(unsigned char bkpt) {
  RSTI_OUT=0;  		  /* reset is active low */
  RSTI_DIRECTION=1; /* assert it */
  if (bkpt==0) {
    #ifdef INVERT
      BKPT_OUT=1;   /* assert BKPT */
    #else
      BKPT_OUT=0;
    #endif
  }
  wait_1ms(50);     /* 50ms */
  RSTI_DIRECTION=0; /* deassert reset */
  wait_1ms(50);     /* give the reset pin enough time to rise even with slow RC */
  #ifdef INVERT		 
    BKPT_OUT=0;     /* deassert BKPT */
  #else
    BKPT_OUT=1;
  #endif
  cable_status.reset=NO_RESET_ACTIVITY;  /* clear the reset flag */  
  bdmcf_complete_chk_rx();  /* added in revision 0.3 */
}

/* asserts the TA signal for the specified duration */
/* the time is in 10us ticks */
void bdmcf_ta(unsigned char time_10us) {
  TA_OUT=0;  		    /* TA is active low */
  TA_DIRECTION=1;   /* assert it */
  wait_10us(time_10us); /* wait the specified time */
  TA_DIRECTION=0;   /* de-assert it */
}

/* transmits series of 17 bit messages, contents of messages is pointed to by *data */
/* first byte in the buffer is the MSB oft the first message */
void bdmcf_tx(unsigned char count, unsigned char *data) {
  while(count--) {
    bdmcf_txrx_start_ptr();
    bdmcf_tx8_ptr(*(data++));
    bdmcf_tx8_ptr(*(data++));
  }
}

/* waits for command complete indication, to be used with commands which only write data and do not read any result */
/* returns 0 on success and non-zero on error */
/* only checks the status, not the data bits */
unsigned char bdmcf_complete_chk(unsigned int next_cmd) {
  unsigned char i=BDMCF_RETRY;
  unsigned char status;
  do {
    status=bdmcf_txrx_start_ptr();
    bdmcf_tx8_ptr(next_cmd>>8);    /* send in the next command */
    bdmcf_tx8_ptr(next_cmd&0xff);
    if (status==0) return(0);
  } while ((i--)>0);
  return(1);
}

/* waits for command complete indication, to be used with commands which only write data and do not read any result */
/* returns 0 on success and non-zero on error */
/* checks buss error as well as not-ready, but does not send the next command */
unsigned char bdmcf_complete_chk_rx(void) {
  unsigned char i=BDMCF_RETRY;
  unsigned char status;
  unsigned char data;
  do {
    status=bdmcf_txrx_start_ptr();
    bdmcf_tx8_ptr(0);
    data=bdmcf_rx8_ptr();
    if (status==0) return(0);
  } while ((data==0x00)&&((i--)>0));
  return(1);
}

/* receives series of 17 bit messages and stores them into the supplied buffer (MSB of the first message first) */
/* returns zero on success and non-zero on retry error */
unsigned char bdmcf_rx(unsigned char count, unsigned char *data) {
  unsigned char i,status;
  while(count) {
    i=BDMCF_RETRY;
    do {
      status=bdmcf_txrx_start_ptr();
      *(data+0)=bdmcf_rx8_ptr();
      *(data+1)=bdmcf_rx8_ptr();
    } while ((status!=0)&&((*(data+1))==0x00)&&((i--)>0));  /* repeat while status==1 & data+1 == 00 (not ready, come again) */
    if (status!=0) return(1);
    count--;
    data+=2;
  }
  return(0);
}

/* receives series of 17 bit messages and stores them into the supplied buffer (MSB of the first message first) */
/* returns zero on success and non-zero on retry error */
/* transmits the next command while receiving the last message */
unsigned char bdmcf_rxtx(unsigned char count, unsigned char *data, unsigned int next_cmd) {
  unsigned char i,status;
  while(count) {
    i=BDMCF_RETRY;
    count--;
    if (count) {
      do {
        status=bdmcf_txrx_start_ptr();
        *(data+0)=bdmcf_rx8_ptr();
        *(data+1)=bdmcf_rx8_ptr();
      } while ((status!=0)&&((*(data+1))==0x00)&&((i--)>0));
    } else {
      do {                                        /* last message - send the next command */
        status=bdmcf_txrx_start_ptr();
        *(data+0)=bdmcf_txrx8_ptr(next_cmd>>8);
        *(data+1)=bdmcf_txrx8_ptr(next_cmd&0xff);
      } while ((status!=0)&&((*(data+1))==0x00)&&((i--)>0));
    }
    if (status!=0) return(1);
    data+=2;
  }
  return(0);
}

/* transmits a 17 bit message, returns the status bit */
unsigned char bdmcf_tx_msg(unsigned int data) {
  unsigned char status;
  status=bdmcf_txrx_start_ptr();
  bdmcf_tx8_ptr(data>>8);
  bdmcf_tx8_ptr(data&0xff);
  return(status);
}

/* transmits a 17 bit message, returns the least significant byte of the response */
/* to be used for transmitting second message in a multi-message command which can fail (e.g. because target is not halted) */
/* the returned byte identifies what is happening: 00 = Not ready, 01 = Bus error, FF = Illegal command */
/* the correct response in these cases is Not Ready */
unsigned char bdmcf_tx_msg_half_rx(unsigned int data) {
  unsigned char ret_val;
  bdmcf_txrx_start_ptr();
  bdmcf_tx8_ptr(data>>8);
  ret_val=bdmcf_txrx8_ptr(data&0xff);
  return(ret_val);
}

/* receives a 17 bit message, returns the status bit, data is stored into the supplied data buffer MSB first */
unsigned char bdmcf_rx_msg(unsigned char *data) {
  unsigned char status;
  status=bdmcf_txrx_start_ptr();
  *data=bdmcf_rx8_ptr();
  *(data+1)=bdmcf_rx8_ptr();
  return(status);
}

/* transmits & receives a 17 bit message, data in the buffer is transmited and then replaced with received data, returns the status bit */
unsigned char bdmcf_txrx_msg(unsigned char *data) {
  unsigned char status;
  status=bdmcf_txrx_start_ptr();
  *data=bdmcf_txrx8_ptr(*data);
  *(data+1)=bdmcf_txrx8_ptr(*(data+1));
  return(status);
}

/* resynchronizes communication with the target in case of noise of the CLK line, etc. */
/* returns 0 in case of sucess, non-zero in case of error */
unsigned char bdmcf_resync(void) {
  unsigned char i;
  unsigned int data=BDMCF_CMD_NOP;
  bdmcf_tx_msg(BDMCF_CMD_NOP);    /* send in 3 NOPs to clear any error */
  bdmcf_tx_msg(BDMCF_CMD_NOP);
  bdmcf_txrx_msg(&data);
  if ((data&3)==0) return(1);     /* the last NOP did not return the expected value (at least one of the two bits should be 1) */
  for (i=18;i>0;i++) {            /* now start sending in another nop and watch the result */
    if (bdmcf_txrx_start_ptr()==0) break;   /* the first 0 is the status */
  }
  if (i==0) return(1);
  /* transmitted & received the status, finish the nop */
  bdmcf_tx8_ptr(0x00);
  bdmcf_tx8_ptr(0x00);
  return(0);
}
 
/* initialises the BDM interface */
void bdmcf_init(void) {
  PTA  = BDMCF_IDLE;    /* preload idle state into port A data register */
  #ifdef DEBUG
    DDRA = DSI_OUT_MASK | TCLK_OUT_MASK | DSCLK_OUT_MASK | BKPT_OUT_MASK; /* RSTI_OUT and TA_OUT are inactive, the remaining OUT signals are outputs */
  #else
    DDRA = DSI_OUT_MASK | TCLK_OUT_MASK | DSCLK_OUT_MASK | BKPT_OUT_MASK | DDRA_DDRA7; /* PTA7 is unused when not debugging, make sure it is output in such case */
  #endif
  PTC  = 0;
  DDRC = DDRC_DDRC1;    /* make pin PTC1 output (it is not bonded out on the 20 pin package anyway) */
  POCR = POCR_PTE20P;   /* enable pull-ups on PTE0-2 (unused pins) */
  /* RSTO edge capture */
  T1SC = 0;             /* enable timer 1 */
  T1SC0;                /* read the status and control register */
  #ifdef INVERT
    T1SC0 = T1SC0_ELS0A_MASK;   /* capture rising edge (invert), this write will also clear the interrupt flag if set */
  #else
    T1SC0 = T1SC0_ELS0B_MASK;   /* capture falling edge (non-invert), this write will also clear the interrupt flag if set */  
  #endif
  T1SC0 |= T1SC0_CH0IE_MASK;    /* enable input capture interrupt */
  cable_status.reset=NO_RESET_ACTIVITY;  /* clear the reset flag */  
}

/* this interrupt is called whenever an active edge is detected on the RSTO input */
interrupt void rsto_detect(void) {
  T1SC0 &= ~T1SC0_CH0F_MASK;          /* clear the interrupt flag */
  cable_status.reset=RESET_DETECTED;  /* reset of the target was detected, leave it for the debugger to what it believes is appropriate */  
}

/* transmits 8 bits */
void bdmcf_tx8_1(unsigned char data) {
  asm {
    tax           /* move the input data to X */
    #ifdef INVERT
      comx        /* invert the data */
    #endif
    #ifdef DEBUG       
      lda   #(BDMCF_IDLE*2)    
    #else      
      lda   #(BDMCF_IDLE/2)    
    #endif      
    /* transmit bit 7 */
    lslx    		  /* shift MSB into C */
    #ifdef DEBUG
      rora        /* rotate C into A */
    #else
			rola
    #endif      
    sta     PTA   /* create falling edge on DSCLK and write the next bit value to the port */  
    #ifdef DEBUG
      lda   #(BDMCF_IDLE*2)  /* reload idle value into A */
    #else
      lda   #(BDMCF_IDLE/2)
    #endif      
    #ifdef INVERT
      bclr  DSCLK_OUT_BITNUM,DSCLK_OUT_PORT  /* create rising edge on DSCLK */
    #else
      bset  DSCLK_OUT_BITNUM,DSCLK_OUT_PORT
    #endif
    /* transmit bit 6 */
    lslx    		  /* shift MSB into C */
    #ifdef DEBUG
      rora        /* rotate C into A */
    #else
			rola
    #endif      
    sta     PTA   /* create falling edge on DSCLK and write the next bit value to the port */  
    #ifdef DEBUG
      lda   #(BDMCF_IDLE*2)  /* reload idle value into A */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -