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

📄 sd.c

📁 u盘MCU端源代码,开发U盘的可以参考.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   SSSS  M   M          CCCC          Standard Microsystems Corporation
  S      MM MM   SSSS  C                    Austin Design Center
   SSS   M M M  S      C                 11000 N. Mopac Expressway
      S  M   M   SSS   C                Stonelake Bldg. 6, Suite 500
  SSSS   M   M      S   CCCC                Austin, Texas 78759
                SSSS            ______________________________________________
  ____________________________________________________________________________
  Copyright(C) 1999, Standard Microsystems Corporation
  All Rights Reserved.
  This program code listing is proprietary to SMSC and may not be copied,
  distributed, or used without a license to do so.  Such license may have
  Limited or Restricted Rights. Please refer to the license for further
  clarification.
  ____________________________________________________________________________
  Notice: The program contained in this listing is a proprietary trade
  secret of SMSC, Hauppauge, New York, and is copyrighted
  under the United States Copyright Act of 1976 as an unpublished work,
  pursuant to Section 104 and Section 408 of Title XVII of the United
  States code. Unauthorized copying, adaption, distribution, use, or
  display is prohibited by this law.
  ____________________________________________________________________________
  Use, duplication, or disclosure by the Government is subject to
  restrictions as set forth in subparagraph(c)(1)(ii) of the Rights
  in Technical Data and Computer Software clause at DFARS 52.227-7013.
  Contractor/Manufacturer is Standard Microsystems Corporation,
  80 Arkay Drive, Hauppauge, New York, 1178-8847.
  ____________________________________________________________________________
  ____________________________________________________________________________
  sd.c - secure digital mass storage class implementation file
  ____________________________________________________________________________
  comments tbd
  ____________________________________________________________________________
  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  11/##/01  cds initial version - stubs for a few overrides.
  04/28/02  tbh xdata is not initialized to zero on power up so set fmc_options to
                zero at start of every transfer.
  05/06/02  ds  It has been noted that the power-cycling of the card is not sufficient to reset the card.
                So,we roll back the change and issue the reset command along with power-cycle.
  05/06/02  ds  If the media is write-protected we should pass the Verify command, to ensure proper operation
                in Win2k
  05/09/02  ds  Enabled "Emergency Exit" with setjmp when waiting for tx and rx interrupts during FS xfers
  05/28/02  ds  In an attempt to speed up SD, I have made the code to poll for the tx and rx bits instead of
                taking an interrupt. Note that the changes are reflected in the irq_timeout fn. Also, implemented
                pre-erase which speeds-up 'certain SD cards'.
  06/17/02  ds  The pre-erase is applicable only to SD and not MMC cards.
  06/18/02  DS  More error detection code added to the Read/Write parts. On a media removal made sure we are
                reporting the right sense code
  06/18/02  ds  Added comments to explain the timeout value. Also added a margin to the timeout. This reflects
                the current 1.1 xfer speed of 200 KBPS
  06/19/02  ds  Fixed win2k 1.1 surprise removal bug. _sd_data_loaded is reinitialized on a surprise removal
  06/19/02  ds  Changed the fmc_set_callback to use fmc_dflt_callback instead of NULL, BOT optimization.
  06/20/02  ds  Set the minimum timeout to 50 ms in g_fmc_timeout, to care of the device overhead
  06/20/02  ds  Since the Upper layer sets the sense code for no-media, it has been removed from SD layer.
  06/25/02  ds  Now that we receive a sync_abort on sd_blk_ovrrun error and crc_error, they are handled accordingly
                in the SD layer.
  06/25/02  ds  Based on measurements set the "card programming " timeout to 1sec
  06/27/02  ds  USB97c210 exibited the latency issue ( a la 201). This appeared as a format issue in Mac OS 10.1.5
                Thus added NOPs to bur some time after we set the bits in ep2_ctl register.
  07/01/02  ds  In sync with the optimization of reads and writes, the read and write dfas are now functions.
                So, they shall use __thread_return_dfa a new macro which simply returns to the caller.
                Also, took out the check for wr_protection on writes. This should be done in the generic lun layer.
  07/11/02  ds  Changed the device ID name to be consistent with recent change (by Trenton), to the drive names.
  07/16/02  tbh added k_pfm_led code to de/activate led on card discovery/absence so led
                operates correctly with old-n-busted OSs that don't send periodic TURs.
  07/30/02  ds  On a high speed read we now wait for an innak before issuing the read command. This is
                to take care of slow hosts ( some wait for about 2ms after the read command to send the first IN token).
                Due to lack of flow control in the SDC hardware, the sd_blk_ovrrun error occurs, forcing us to send
                a read_error and fail the transfer. It has been noted that the Wincomp software does not retry a read.
                This causes it to fail. This does not happen in Full speed as we take a lot of time to hand-fill the buffers.
  09/11/02  ds  The firing of the timer1 interrupt in the middle of 2.0 data xfer (FMDU), causes data loss and
                makes it appear to the host like there is data corruption, even though the file itself is not corrupted.
                So, turned off the timer for now, if we know it is an SD 2.0 read. So, the light will not blink to the desired interval on SD.
  09/12/02  ds  To be safe turn of timer1 even on 2.0 writes.
  09/12/02  ds  Manage the state of the gpio0 led, during the xfer.
  09/12/02  tbh replaced strncpy() with memcpy() to save data space.
  09/12/02  tbh/ds timer1 disabled during sd transfers to avoid data corruption issue.  bug report #343
                added comments (including this one)
  09/17/02  tbh fixed improperly coded accesses to x_fmc_clk_ctl.
  09/18/02  tbh bug report 343, sd data corruption.  initial workaround was to
                disable timer1 interrupts during sd transfers.  later examination
                revealed that issuing the read to the sd card *before* enabling
                the block transfer is problematic due to a window of vulnerability
                during which the following can occur:
                if the transfer is off for too long bu the sd is reading data then
                the sd card will dump its data into the bit bucket.  once the
                block transfer is enabled the sd card provides the desired quantity
                of data, but starting from the incorrect offset.  thus the data
                appears corrupt.  today's modification was to postpone issuing
                the read command until after the block transfer is enabled.
  09/19/02  tbh  typo - disable was diable
  10/02/02  ds  Set the timeout value for data transfers to 10 seconds, following the other luns.
                This value is safer than then the empirical value we had before.
  10/17/02  cds updated lun_data macros to use the new vtbl and lun_data formats. 
  10/24/02  ds  Implemented Retry of 2.0 reads, when an sd_blk_ovrrun error occurs. The new address is 
                computed and a multiple-block-read is issued.               
============================================================================*/
#define __sd_dot_c__
#include "project.h"
#include "dev.h"

// provide vtable definition '_vtbl_cf'
code _vtbl_defn(sd);

#define sd_1point1_included


//#define Debug_On //A local directive to turn on certain debug features
//#define sd_fast_1point1

#define FS_pktsz 64
uint8 xdata _sd_card_active = k_true;  //This is a flag to know if the card is not responding
uint8 xdata _sd_data_loaded = k_false;  //Tells me if the buffers are already loaded

//------------------------------------------------------------------------------
// sd/mmc controller (sdc) interface registers
unsigned char volatile xdata sdc_data             at_sd(F6);  // rw     SDC Data Register
unsigned char volatile xdata sdc_mode_ctl        at_sd(F8);  // rw     SDC Model Control Register
unsigned char volatile xdata sdc_ctl              at_sd(F9);  // rw     SDC Control Register
unsigned char volatile xdata sdc_cmd_rsp_buf[17]  _at_ 0x3640;

//RCA bytes
uint8 xdata  g_sdc_rca_h = 0x00;
uint8 xdata g_sdc_rca_l = 0x00;
uint8 xdata _sd_state = 0x00;     //Tells us the current _sd_state of the card
uint8 xdata _sd_data_xfer_cmd;    //Instead of passing a parameter this tells what cmd to issue
uint8 xdata _sd_write_protected = k_false;  //The media could be Write Protected both in Soft and Hard way
jmp_buf xdata _sd_context;        // This the context to which timeout fns will jump to on error
xdata t_udw32 xdata _sd_start_addr_this_xfer;  //The device takes byte address instead of block address. This variable stores that.

//+-----------------------------------------------------------------------------
// Name:
//   TBD
//
// Declaration:
//   TBD
//
// Purpose:
//   TBD
//
// Arguments:
//   TBD
//
// Return:
//   TBD
//
// Notes:
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void sdc_read_rsp(uint8 length) reentrant
{
  uint8 i,temp;
  for(i=0;i<=length;i++)
  {
    temp = XBYTE[(0X3640+i)];
  }
}

//+-----------------------------------------------------------------------------
// Name:
//   sdc_wait_status_with_timeout
//
// Declaration:
//   t_result sdc_wait_status_with_timeout(uint8 mask,uint16 ticks);
//
// Purpose:
//   Poll the sdc status register to watch for specific bits being set.
//
// Arguments:
//   mask    - a uint8 with 1's in the bits to be compared
//   ticks   - a uint16 representing the timeout limit
//
// Return:
//   A t_result indicating:
//     k_success - the sdc status register logically anded with the mask
//     k_usbreset  - usb reset signalling was detected while waiting.
//     k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
//     k_timeout - timeout limit exceeded.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Why does this not return a result? and Why does this set a global instead? This is because this fn is
//   is called several levels down from the main caller, and requires a lot of code to transmit the result up
//   the hierarchy. So, now we just check for the flag and return, so the highest caller may take appropriate
//   action.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void sdc_wait_status_with_timeout(uint8 mask, uint16 ticks) reentrant
{
  uint8 status;
  t_sync sync = 0;
  t_sync sync1 = 0;
  _stack_check();
  //_stack_dump();
  //TRACE2(295, sd, 1, "sdc_wait_status_with_timeout(mask:%02X ticks:%d)", mask, ticks);
  // do this to get kbm_sync_abort delivered of there is traffic on the control pipe
  _isr_bind_dma_owner(g_tid, kbm_sync_none);
  // wait until the device is no longer busy
  thread_set_timer(ticks);
  _mcu_begin_critical_section();
  sync = _thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
  _mcu_end_critical_section();
  status = x_sdc_stat;
  //TRACE1(296, sd, 1, "The value of status %02x ",status);
  while((status & mask) != mask)
  {
    _mcu_begin_critical_section();
    sync = _thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
    _mcu_end_critical_section();
    _stack_check();
    if(sync & kbm_sync_usbrst)
    {
      trace0(0, sd, 1, "sdc_wait_status_with_timeout() - error: kbm_sync_usbrst");
      break;
    }
    if(sync & kbm_sync_abort)
    {
      trace0(0, sd, 1, "sdc_wait_status_with_timeout() - error: kbm_sync_abort");
      break;
    }
    if(sync & kbm_sync_timer)
    {
      trace0(0, sd, 1, "sdc_wait_status_with_timeout() - error: hung busy");
      //when a command fails init stage it could be because of a mmc card
      _sd_card_active = k_false;
      break;
    }
    status = x_sdc_stat;
    // trace1(0, sd, 1, "The value of status %02x ",status);
  }
  if(sync)                       //did we get out on a failure?
  {
    //Reset the media here
    trace0(0, sd, 1, "Resetting the SDC Block");
    sdc_ctl = 0x20;
    thread_set_timer(10);
    while(!(sync1 & kbm_sync_timer))
    {
      _mcu_begin_critical_section();
      sync1 = _thread_got_sync(kbm_sync_timer);
      _mcu_end_critical_section();
    }
    _thread_clr_sync(kbm_sync_timer);
  }
  _thread_clr_sync(sync);         //clear the synchronizers
  if(sync & (kbm_sync_usbrst |kbm_sync_abort))
    longjmp(_sd_context, 1);      //Go to the caller dfa and return failed
  //_stack_dump();
  //TRACE1(301, sd, 1, "The value of status %02x ",status);
  _stack_check();
  //_stack_dump();
  return;
}

//+-----------------------------------------------------------------------------
// Name:
//   sdc_wait_irq_with_timeout
//
// Declaration:
//   t_result sdc_wait_irq_with_timeout(uint16 ticks);
//
// Purpose:
//   Poll for any synchronizer .
//
// Arguments:
//   ticks   - a uint16 representing the timeout limit
//
// Return:
//   A t_result indicating:
//     k_success - the sync was spotted.
//     k_usbreset  - usb reset signalling was detected while waiting.
//     k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
//     k_timeout - timeout limit exceeded.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
#ifndef sd_fast_1point1
t_result sdc_wait_irq_with_timeout(uint8 irq_name, uint16 ticks) reentrant
{
  t_sync sync;
  //TRACE2(302, sd, 1, "sd_wait_irq_with_timeout(ticks:%d) for %02x", ticks, irq_name);
  // do this to get kbm_sync_abort delivered of there is traffic on the control pipe
  _isr_bind_dma_owner(g_tid, kbm_sync_none);
  thread_set_timer(ticks);
  sync = kbm_sync_none;
  //while(!(sync & irq_name))
  while(!(_mcu_register_rd(x_isr0) & irq_name))
  {
    sync = thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
    _thread_clr_sync(sync);
    if(sync & kbm_sync_usbrst)
    {
      trace0(0, sd, 1, "sd_wait_irq_with_timeout() - error: kbm_sync_usbrst");
    }
    if(sync & kbm_sync_abort)
    {
      trace0(0, sd, 1, "sd_wait_irq_with_timeout() - error: kbm_sync_abort");
    }
    if(sync & kbm_sync_timer)
    {
      trace0(0, sd, 1, "sd_wait_irq_with_timeout() - error: timeout awaiting irq");
      return k_timeout;

⌨️ 快捷键说明

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