AnsweredAssumed Answered

extern Diskio_drvTypeDef USER_Driver;==> unknown type error on Diskio_drvTypeDef ?

Question asked by H.Rick on Feb 2, 2016
Guys,

How can I fix :
unknown type error on Diskio_drvTypeDef on user_diskio.h ?

Here's the file user_diskio.h
/**
 ******************************************************************************
  * @file    user_diskio.h
  * @brief   This file contains the common defines and functions prototypes for 
  *          the user_diskio driver.
  ******************************************************************************
  *
  * COPYRIGHT(c) 2016 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
   
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USER_DISKIO_H
#define __USER_DISKIO_H
 
#ifdef __cplusplus
 extern "C" {
#endif
 
/* USER CODE BEGIN 0 */
 
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
extern Diskio_drvTypeDef  USER_Driver;
 
/* USER CODE END 0 */
    
#ifdef __cplusplus
}
#endif
 
#endif /* __USER_DISKIO_H */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
user_diskio.c
/**
 ******************************************************************************
  * @file    user_diskio.c
  * @brief   This file includes a diskio driver skeleton to be completed by the user.
  ******************************************************************************
  *
  * COPYRIGHT(c) 2016 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
 
/* USER CODE BEGIN 0 */
 
/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "ff_gen_drv.h"
#include "usart.h"
#include "spi.h"
 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define CS_LOW()        { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10 , 0 ); }         /* CS=low */
#define CS_HIGH()     { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10 , 1 ); }           /* CS=high */
#define SOCKINS     {HAL_GPIO_ReadPin(GPIOB, 11);}  /* Card detected.   yes:true, no:false, default:true */
#define SOCKWP      {HAL_GPIO_ReadPin(GPIOB, 12);}      /* Write protected. yes:true, no:false, default:false */
#define FCLK_SLOW() MX_SPI2_Init_Low();
#define FCLK_FAST() MX_SPI2_Init();
 
/* Definitions for MMC/SDC command */
#define CMD0    (0)         /* GO_IDLE_STATE */
#define CMD1    (1)         /* SEND_OP_COND (MMC) */
#define ACMD41  (0x80+41)   /* SEND_OP_COND (SDC) */
#define CMD8    (8)         /* SEND_IF_COND */
#define CMD9    (9)         /* SEND_CSD */
#define CMD10   (10)        /* SEND_CID */
#define CMD12   (12)        /* STOP_TRANSMISSION */
#define ACMD13  (0x80+13)   /* SD_STATUS (SDC) */
#define CMD16   (16)        /* SET_BLOCKLEN */
#define CMD17   (17)        /* READ_SINGLE_BLOCK */
#define CMD18   (18)        /* READ_MULTIPLE_BLOCK */
#define CMD23   (23)        /* SET_BLOCK_COUNT (MMC) */
#define ACMD23  (0x80+23)   /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24   (24)        /* WRITE_BLOCK */
#define CMD25   (25)        /* WRITE_MULTIPLE_BLOCK */
#define CMD32   (32)        /* ERASE_ER_BLK_START */
#define CMD33   (33)        /* ERASE_ER_BLK_END */
#define CMD38   (38)        /* ERASE */
#define CMD55   (55)        /* APP_CMD */
#define CMD58   (58)        /* READ_OCR */
#define CTRL_POWER          5   /* Get/Set power status */
/* MMC card type flags (MMC_GET_TYPE) */
#define CT_MMC      0x01        /* MMC ver 3 */
#define CT_SD1      0x02        /* SD ver 1 */
#define CT_SD2      0x04        /* SD ver 2 */
#define CT_SDC      (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK    0x08        /* Block addressing */
/* Private variables ---------------------------------------------------------*/
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;
static volatile BYTE Timer1, Timer2;    /* 100Hz decrement timer */
static BYTE CardType;           /* Card type flags */
 
/* Private function prototypes -----------------------------------------------*/
 
DSTATUS USER_initialize (void);
DSTATUS USER_status (void);
DRESULT USER_read (BYTE*, DWORD, UINT);
#if _USE_WRITE == 1
  DRESULT USER_write (/*const*/ BYTE*, DWORD, UINT);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
  DRESULT USER_ioctl (BYTE, void*);
#endif /* _USE_IOCTL == 1 */
 
Diskio_drvTypeDef  USER_Driver =
{
  USER_initialize,
  USER_status,
  USER_read,
#if  _USE_WRITE
  USER_write,
#endif  /* _USE_WRITE == 1 */ 
#if  _USE_IOCTL == 1
  USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};
 
/* Private functions ---------------------------------------------------------*/
//written by Riko Ho Start here
static
void power_on (void)
{
 
    FCLK_SLOW();
}
 
static
void power_off (void)
{
    FCLK_FAST();
 
}
 
 
/* Exchange a byte */
static
BYTE xchg_spi (     /* Returns received data */
    BYTE dat        /* Data to be sent */
)
{
    uint8_t result = 0;
    while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY);
    //HAL_SPI_Receive(&hspi2,&dat,1,100);
    HAL_SPI_TransmitReceive(&hspi2,&dat,&result,1,1000);
    return result;
}
 
/* Send a data block fast */
 
static
void xmit_spi_multi (
      BYTE *p,  /* Data block to be sent */
    UINT cnt       
)
 
//test only
//void xmit_spi_multi (
//    BYTE *p,  /* Data block to be sent */
//  UINT cnt       
//)
{
     
    while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY);
    HAL_SPI_Transmit(&hspi2,p,cnt,100);
}
 
/* Receive a data block fast */
static
void rcvr_spi_multi (
    BYTE *p,    /* Data buffer */
    UINT cnt    /* Size of data block (must be multiple of 2) */
)
{
    while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY);
    HAL_SPI_Receive(&hspi2,p,cnt,100);
}
 
/*-----------------------------------------------------------------------*/
/* Wait for card ready                                                   */
/*-----------------------------------------------------------------------*/
 
static
int wait_ready (    /* 1:Ready, 0:Timeout */
    UINT wt         /* Timeout [ms] */
)
{
    BYTE d;
 
 
    Timer2 = wt / 10;
    do
        d = xchg_spi(0xFF);
    while (d != 0xFF && Timer2);
 
    return (d == 0xFF) ? 1 : 0;
}
 
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus                                 */
/*-----------------------------------------------------------------------*/
 
static
void deselect (void)
{
    CS_HIGH();
    xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
}
 
 
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready                                    */
/*-----------------------------------------------------------------------*/
 
static
int select (void)   /* 1:Successful, 0:Timeout */
{
    CS_LOW();
    xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
 
    if (wait_ready(500)) return 1;  /* OK */
    deselect();
    return 0;   /* Timeout */
}
 
/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC                                        */
/*-----------------------------------------------------------------------*/
 
static
int rcvr_datablock (
    BYTE *buff,         /* Data buffer to store received data */
    UINT btr            /* Byte count (must be multiple of 4) */
)
{
    BYTE token;
 
 
    Timer1 = 20;
    do {                            /* Wait for data packet in timeout of 200ms */
        token = xchg_spi(0xFF);
    } while ((token == 0xFF) && Timer1);
    if (token != 0xFE) return 0;    /* If not valid data token, retutn with error */
 
    rcvr_spi_multi(buff, btr);      /* Receive the data block into buffer */
    xchg_spi(0xFF);                 /* Discard CRC */
    xchg_spi(0xFF);
 
    return 1;                       /* Return with success */
}
 
/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC                                             */
/*-----------------------------------------------------------------------*/
 
//#if   _USE_WRITE
//static
int xmit_datablock (
       BYTE *buff,  /* 512 byte data block to be transmitted */
    BYTE token          /* Data/Stop token */
)
{
    BYTE resp;
 
 
    if (!wait_ready(500)) return 0;
 
    xchg_spi(token);                    /* Xmit data token */
    if (token != 0xFD) {    /* Is data token */
        xmit_spi_multi(buff, 512);      /* Xmit the data block to the MMC */
        xchg_spi(0xFF);                 /* CRC (Dummy) */
        xchg_spi(0xFF);
        resp = xchg_spi(0xFF);          /* Reveive data response */
        if ((resp & 0x1F) != 0x05)      /* If not accepted, return with error */
            return 0;
    }
 
    return 1;
}
//#endif
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC                                          */
/*-----------------------------------------------------------------------*/
 
static
BYTE send_cmd (     /* Returns R1 resp (bit7==1:Send failed) */
    BYTE cmd,       /* Command index */
    DWORD arg       /* Argument */
)
{
    BYTE n, res;
 
 
    if (cmd & 0x80) {   /* ACMD<n> is the command sequense of CMD55-CMD<n> */
        cmd &= 0x7F;
        res = send_cmd(CMD55, 0);
        if (res > 1) return res;
    }
 
    /* Select the card and wait for ready except to stop multiple block read */
    if (cmd != CMD12) {
        deselect();
        if (!select()) return 0xFF;
    }
 
    /* Send command packet */
    xchg_spi(0x40 | cmd);               /* Start + Command index */
    xchg_spi((BYTE)(arg >> 24));        /* Argument[31..24] */
    xchg_spi((BYTE)(arg >> 16));        /* Argument[23..16] */
    xchg_spi((BYTE)(arg >> 8));         /* Argument[15..8] */
    xchg_spi((BYTE)arg);                /* Argument[7..0] */
    n = 0x01;                           /* Dummy CRC + Stop */
    if (cmd == CMD0) n = 0x95;          /* Valid CRC for CMD0(0) + Stop */
    if (cmd == CMD8) n = 0x87;          /* Valid CRC for CMD8(0x1AA) Stop */
    xchg_spi(n);
 
    /* Receive command response */
    if (cmd == CMD12) xchg_spi(0xFF);       /* Skip a stuff byte when stop reading */
    n = 10;                             /* Wait for a valid response in timeout of 10 attempts */
    do
        res = xchg_spi(0xFF);
    while ((res & 0x80) && --n);
    return res;         /* Return with the response value */
}
 
//written by Riko Ho End here
/**
  * @brief  Initializes a Drive
  * @param  None
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_initialize(void)
{
  Stat = STA_NOINIT;
    Stat &= ~STA_NOINIT;
  //================
   
    /* USER CODE HERE */
    BYTE pdrv;
  HAL_UART_Transmit(&huart1, "USER INITIALIZE START! \r\n", 100, 1000); //debug message
     
     DSTATUS Stat = RES_OK;
     
    BYTE n, cmd, ty, ocr[4];
  //; 
 
    if (pdrv) return STA_NOINIT;        /* Supports only single drive */
    power_off();                        /* Turn off the socket power to reset the card */
     
    if (Stat & STA_NODISK) return Stat; /* No card in the socket */;
    power_on();                         /* Turn on the socket power */
     
    FCLK_SLOW();
    for (n = 10; n; n--) xchg_spi(0xFF);    /* 80 dummy clocks */
 
    ty = 0;
    if (send_cmd(CMD0, 0) == 1) {           /* Enter Idle state */
        Timer1 = 100;                       /* Initialization timeout of 1000 msec */
        if (send_cmd(CMD8, 0x1AA) == 1) {   /* SDv2? */
            for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);        /* Get trailing return value of R7 resp */
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {             /* The card can work at vdd range of 2.7-3.6V */
                while (Timer1 && send_cmd(ACMD41, 1UL << 30));  /* Wait for leaving idle state (ACMD41 with HCS bit) */
                if (Timer1 && send_cmd(CMD58, 0) == 0) {        /* Check CCS bit in the OCR */
                    for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
                    ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;  /* SDv2 */
                }
            }
        } else {                            /* SDv1 or MMCv3 */
            if (send_cmd(ACMD41, 0) <= 1)   {
                ty = CT_SD1; cmd = ACMD41;  /* SDv1 */
            } else {
                ty = CT_MMC; cmd = CMD1;    /* MMCv3 */
            }
            while (Timer1 && send_cmd(cmd, 0));         /* Wait for leaving idle state */
            if (!Timer1 || send_cmd(CMD16, 512) != 0)   /* Set R/W block length to 512 */
                ty = 0;
        }
    }
    CardType = ty;
    deselect();
 
    if (ty) {           /* Initialization succeded */
        Stat &= ~STA_NOINIT;        /* Clear STA_NOINIT */
        FCLK_FAST();
 
         HAL_UART_Transmit(&huart1, "USER INITIALIZE SUCCEDED! \r\n", 100, 1000);
    } else {            /* Initialization failed */
        power_off();
         HAL_UART_Transmit(&huart1, "USER INITIALIZE FAILED! \r\n", 100, 1000);
    }
      HAL_UART_Transmit(&huart1, "USER INITIALIZE FINISHED! \n \n", 100, 1000);
 
   
    //================
   
  return Stat;
}
 
/**
  * @brief  Gets Disk Status
  * @param  None
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_status(void)
{
  Stat = STA_NOINIT;
   
  Stat &= ~STA_NOINIT;
 
  return Stat;
}
 
/**
  * @brief  Reads Sector(s)
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
DRESULT USER_read(BYTE *buff, DWORD sector, UINT count)
{
  /* USER CODE HERE */
    DRESULT res;
    DSTATUS stat;
  //;
  //res = disk.drv[pdrv]->disk_read(buff, sector, count);
    BYTE pdrv;
    if (pdrv || !count) return RES_PARERR;
    if (stat & STA_NOINIT) return RES_NOTRDY;
 
    if (!(CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
 
    if (count == 1) {   /* Single block read */
        if ((send_cmd(CMD17, sector) == 0)  /* READ_SINGLE_BLOCK */
            && rcvr_datablock(buff, 512))
            count = 0;
    }
    else {              /* Multiple block read */
        if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
            do {
                if (!rcvr_datablock(buff, 512)) break;
                buff += 512;
            } while (--count);
            send_cmd(CMD12, 0);             /* STOP_TRANSMISSION */
        }
    }
    deselect();
   
  return RES_OK;
}
 
/**
  * @brief  Writes Sector(s)
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
DRESULT USER_write(/*const*/ BYTE *buff, DWORD sector, UINT count)
{
  /* USER CODE HERE */
  BYTE pdrv;
if (pdrv || !count) return RES_PARERR;
    if (Stat & STA_NOINIT) return RES_NOTRDY;
    if (Stat & STA_PROTECT) return RES_WRPRT;
 
    if (!(CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
 
    if (count == 1) {   /* Single block write */
        if ((send_cmd(CMD24, sector) == 0)  /* WRITE_BLOCK */
            && xmit_datablock(buff, 0xFE))
            count = 0;
    }
    else {              /* Multiple block write */
        if (CardType & CT_SDC) send_cmd(ACMD23, count);
        if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
            do {
                if (!xmit_datablock(buff, 0xFC)) break;
                buff += 512;
            } while (--count);
            if (!xmit_datablock(0, 0xFD))   /* STOP_TRAN token */
                count = 1;
        }
    }
    deselect();
  return RES_OK;
}
#endif /* _USE_WRITE == 1 */
 
/**
  * @brief  I/O control operation
  * @param  cmd: Control code
  * @param  *buff: Buffer to send/receive control data
  * @retval DRESULT: Operation result
  */
#if _USE_IOCTL == 1
DRESULT USER_ioctl(BYTE cmd, void *buff)
{
  DRESULT res = RES_ERROR;
   
  /* USER CODE HERE */
 
  return res;
}
#endif /* _USE_IOCTL == 1 */
 
/* USER CODE END 0 */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Anyone can help ?
Anyone from ST who developed this code, please let me know how to fix it ? thanks

Outcomes