/* ***********************************************************************
**
** Copyright (C) 2006 Jesper Hansen <jesper@redegg.net>
**
**
** Interface functions for MMC/SD cards
**
** File mmc_if.h
**
** Hacked by Michael Spiceland at http://tinkerish.com to support
** writing as well.
**
*************************************************************************
**
** 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.
**
*************************************************************************/
/** \file mmc_if.c
Simple MMC/SD-card functionality
*/
#include <avr/io.h>
#include <inttypes.h>
#include <stdio.h>
#include "mmc_if.h"
/** Hardware SPI I/O.
\param byte Data to send over SPI bus
\return Received data from SPI bus
*/
uint8_t spi_byte(uint8_t byte)
{
SPDR = byte;
while(!(SPSR & (1<<SPIF)))
{}
return SPDR;
}
/** Send a command to the MMC/SD card.
\param command Command to send
\param px Command parameter 1
\param py Command parameter 2
*/
void mmc_send_command(uint8_t command, uint16_t px, uint16_t py)
{
register union u16convert r;
MMC_CS_PORT &= ~(1 << MMC_CS); // enable CS
spi_byte(0xff); // dummy byte
spi_byte(command | 0x40);
r.value = px;
spi_byte(r.bytes.high); // high byte of param x
spi_byte(r.bytes.low); // low byte of param x
r.value = py;
spi_byte(r.bytes.high); // high byte of param y
spi_byte(r.bytes.low); // low byte of param y
spi_byte(0x95); // correct CRC for first command in SPI
// after that CRC is ignored, so no problem with
// always sending 0x95
spi_byte(0xff); // ignore return byte
}
/** Get Token.
Wait for and return a non-ff token from the MMC/SD card
\return The received token or 0xFF if timeout
*/
uint8_t mmc_get(void)
{
uint16_t i = 0xffff;
uint8_t b = 0xff;
while ((b == 0xff) && (--i))
{
b = spi_byte(0xff);
}
return b;
}
/** Get Datatoken.
Wait for and return a data token from the MMC/SD card
\return The received token or 0xFF if timeout
*/
uint8_t mmc_datatoken(void)
{
uint16_t i = 0xffff;
uint8_t b = 0xff;
while ((b != 0xfe) && (--i))
{
b = spi_byte(0xff);
}
return b;
}
/** Finish Clocking and Release card.
Send 10 clocks to the MMC/SD card
and release the CS line
*/
void mmc_clock_and_release(void)
{
uint8_t i;
// SD cards require at least 8 final clocks
for(i=0;i<10;i++)
spi_byte(0xff);
MMC_CS_PORT |= (1 << MMC_CS); // release CS
}
/** Read MMC/SD sector.
Read a single 512 byte sector from the MMC/SD card
\param lba Logical sectornumber to read
\param buffer Pointer to buffer for received data
\return 0 on success, -1 on error
*/
int mmc_readsector(uint32_t lba, uint8_t *buffer)
{
uint16_t i;
// send read command and logical sector address
mmc_send_command(17,(lba>>7) & 0xffff, (lba<<9) & 0xffff);
if (mmc_datatoken() != 0xfe) // if no valid token
{
mmc_clock_and_release(); // cleanup and
//for (i=0;i<512;i++) // we don't want a false impression that everything was fine.
// *buffer++ = 0x00;
return -1; // return error code
}
for (i=0;i<512;i++) // read sector data
*buffer++ = spi_byte(0xff);
spi_byte(0xff); // ignore dummy checksum
spi_byte(0xff); // ignore dummy checksum
mmc_clock_and_release(); // cleanup
return 0; // return success
}
/************************** MMC get response **************************************/
/**** Repeatedly reads the MMC until we get the response we want or timeout ****/
/* this function taken from the PIC CCS example */
int mmc_response(unsigned char response)
{
unsigned long count = 0xFFFF; // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
while(spi_byte(0xFF) != response && --count > 0);
if(count==0) return 1; // loop was exited due to timeout
else return 0; // loop was exited before timeout
}
/** Write MMC/SD sector.
Write a single 512 byte sector from the MMC/SD card
\param lba Logical sectornumber to write
\param buffer Pointer to buffer to write from
\return 0 on success, -1 on error
*/
int mmc_writesector(uint32_t lba, uint8_t *buffer)
{
uint16_t i;
// send read command and logical sector address
mmc_send_command(24,(lba>>7) & 0xffff, (lba<<9) & 0xffff);
// need wait for resonse here
if((mmc_response(0x00))==1)
{
mmc_clock_and_release(); // cleanup and
return -1;
}
// need to send token here
spi_byte(0xfe); // send data token /* based on PIC code example */
for (i=0;i<512;i++) // write sector data
spi_byte(*buffer++);
spi_byte(0xff); // ignore dummy checksum
spi_byte(0xff); // ignore dummy checksum
// do we check the status here?
if((spi_byte(0xFF)&0x0F)!=0x05) return -1;
i = 0xffff; // max timeout
while(!spi_byte(0xFF) && (--i)){;} // wait until we are not busy
mmc_clock_and_release(); // cleanup
return 0; // return success
}
/** Init MMC/SD card.
Initialize I/O ports for the MMC/SD interface and
send init commands to the MMC/SD card
\return 0 on success, other values on error
*/
uint8_t mmc_init(void)
{
int i;
// setup I/O ports
SPI_PORT &= ~((1 << MMC_SCK) | (1 << MMC_MOSI)); // low bits
SPI_PORT |= (1 << MMC_MISO); // high bits
SPI_DDR |= (1<<MMC_SCK) | (1<<MMC_MOSI); // direction
MMC_CS_PORT |= (1 << MMC_CS); // Initial level is high
MMC_CS_DIR |= (1 << MMC_CS); // Direction is output
// also need to set SS as output
#if defined(__AVR_ATmega8__)
// is already set as CS, but we set it again to accomodate for other boards
SPI_DDR |= (1<<2);
#else
SPI_DDR |= (1<<0); // assume it's bit0 (mega128, portB and others)
#endif
SPCR = (1<<MSTR)|(1<<SPE); // enable SPI interface
SPSR = 1; // set double speed
for(i=0;i<10;i++) // send 80 clocks while card power stabilizes
spi_byte(0xff);
mmc_send_command(0,0,0); // send CMD0 - reset card
if (mmc_get() != 1) // if no valid response code
{
mmc_clock_and_release();
return 1; // card cannot be detected
}
//
// send CMD1 until we get a 0 back, indicating card is done initializing
//
i = 0xffff; // max timeout
while ((spi_byte(0xff) != 0) && (--i)) // wait for it
{
mmc_send_command(1,0,0); // send CMD1 - activate card init
}
mmc_clock_and_release(); // clean up
if (i == 0) // if we timed out above
return 2; // return failure code
return 0;
}
局外狗
- 粉丝: 82
- 资源: 1万+
最新资源
- 负荷需求响应模型matlab 通过分时电价方式下的负荷需求响应模型得到负荷响应前后变化情况,可以看到明显呈现削峰填谷的作用
- SXU-python实验报告及笔记
- Halcon安全环检测例程资源包
- 六轴EtherCAT总线伺服涂布收卷机程序,采用六个伺服+变频器+编码器,动态测量频率,计算转速,再算频率,用变频器同步伺服电机速度,进行通讯控制,具备一定参考价值
- 社会事件检测任务数据集 14个SocialED python库相关的数据集
- MMCM Dynamic Reconfig Source
- 基于HSV颜色的保险丝分类的完整Halcon例程代码和示例图像文件
- 基于springboot的冬奥会科普平台源码(java毕业设计完整源码+LW).zip
- 三菱R系列PLC案例程序 三菱R系列ST、RD77MS定位以及三菱触摸屏配方功能,此案例还提供两个触摸屏实现异地操作,使操作更加方便快捷 此案例还通过CClink远程连接远程IO站以及机器人,将机器
- 高噪声环境下形状匹配的完整Halcon例程代码、示例图像以及相关配套文件
- SXU-大数据开源框架实验报告
- SocialED:一个社会事件检测任务的python库
- a6efce1b9d16fdfae3915991f36fde5995ee7b39.jpeg
- 基于springboot的社区医院管理服务系统源码(java毕业设计完整源码+LW).zip
- 台达DVP PLC与3台西门子V20变频器通讯程序 台达PLC与3台西门子变频器通讯,可靠稳定,同时解决西门子变频器断电重启后,自准备工作,无需人为准备 器件:台达DVP 14es PLC,昆仑通态
- 基于形状匹配与OCR的多图像处理Halcon例程代码及示例图像文件
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈