/*************************************************************//**
* \file sd.c
*
* SD SPI interface
*
* A simple SD interface using SPI. This relies on the associated
* SPI interface, but should be relatively simple to recreate.
*
* This interface is somewhat bloated. It is not intended to be
* fast, but instead helpful for debugging and learning.
*
******************************************************************/
#include <inttypes.h>
#include <avr/sfr_defs.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "sd.h"
#include "spi.h"
#include "utils.h"
#define SD_USE_CRC
// Not all defines are used... yet...
#define CMD_GO_IDLE_STATE 0 // Reset the SD
#define CMD_SEND_OP_COND 1 // Activate initialization process
#define CMD_SEND_IF_COND 8 // Send interface operating condition
#define CMD_SEND_CSD 9 // Send Card specific data
#define CMD_SEND_CID 10 // Send Card ID
#define CMD_STOP_TRANSMISSION 12 // Stop read/write transmission
#define CMD_SEND_STATUS 13 // Request card send status
#define CMD_SET_BLOCKLEN 16 // Set block length (in bytes)
#define CMD_READ_BLOCK 17 // Read a block of data
#define CMD_WRITE_BLOCK 24 // Write a block of data
#define CMD_ERASE_BLOCK_START 32 // Set first sector for erase
#define CMD_ERASE_BLOCK_END 33 // Set last sector for erase
#define CMD_ERASE 38 // Erase all selected sectors
#define CMD_READ_OCR 58 // Read OCR register
#define CMD_CRC_ONOFF 59 // 0 to turn off CRC, 1 to turn on CRC
#define APP_CMD 55 // Signal start of application specific command
#define SD_SEND_OP_COND 41 // Send operation conditions on host side
#define R1_IDLE 0x01
#define R1_ERASE_RESET 0x02
#define R1_ILLEGAL_CMD 0x04
#define R1_CRC_ERROR 0x08
#define R1_ERASE_ERROR 0x10
#define R1_ADDR_ERROR 0x20
#define R1_PARAM_ERROR 0x40
#define NO_RESPONSE 0xFF
#define BLOCK_SIZE 512
#define FILL_BYTE 0xFF
#define START_BLOCK 0xFE
static void SD_DelayBytes(uint16_t bytes);
static void SD_SendCommand(uint8_t command, uint32_t arg);
static uint8_t SD_CheckForCard(void);
static uint8_t SD_GetResponse(uint8_t *buf, uint16_t length);
static uint8_t SD_ReadData(uint8_t *buf, uint16_t length);
static void SD_DecodeR1(uint8_t res);
//static void SD_DecodeR2(uint16_t res);
static void SD_DecodeDataRes(uint8_t res);
static void SD_DecodeDataErr(uint8_t res);
static uint8_t SD_CRC7 (uint8_t *bytes, uint32_t length);
static uint16_t SD_CRC16(uint8_t *bytes, uint32_t length);
static uint16_t SD_CRC16_Fill(uint16_t crc, uint8_t const_value, uint32_t length);
// SD_* is already non-reentrant, so a global buffer is... OK...
static uint8_t scratch[32];
/**
* Initialize the SD card.
*
* Attempts to initialize an SD card on the SPI bus. Will
* go through the standard initialization procedures, and
* then print out the CID and CSD in hex.
*
* @return 1 if sucessful, 0 otherwise
*/
uint8_t
SD_Init(void)
{
uint16_t i;
uint8_t res;
// Delay a buncha clocks
SPI_SSOff();
SD_DelayBytes(20);
// Check if the card is inserted
if(!SD_CheckForCard())
{
printf("Card NOT found\n");
return 0;
}
printf("Card found\n");
// Standard init commands
SD_SendCommand(CMD_SEND_IF_COND, 0);
res = SD_GetResponse(scratch, 5);
SD_SendCommand(CMD_READ_OCR, 0);
res = SD_GetResponse(scratch, 5);
// Wait for card to init fully
i=0;
do {
SD_SendCommand(CMD_SEND_OP_COND, 0);
res = SD_GetResponse(scratch, 1);
i++;
}while(res && i < 10000);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SEND_OP_COND, res);
return 0;
}
#ifdef SD_USE_CRC
SD_SendCommand(CMD_CRC_ONOFF, 1);
#else
SD_SendCommand(CMD_CRC_ONOFF, 0);
#endif
res = SD_GetResponse(scratch, 1);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
SD_DecodeR1(res);
return 0;
}
SD_SendCommand(CMD_SEND_CID, 0);
// 128bits + 16 CRC
res = SD_GetResponse(scratch, 1) || !SD_ReadData(scratch, 18);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
return 0;
}else{
printf("CID: ");
print_hex(scratch, 16);
printf("\n");
//printf(" CRC16: %d\n", SD_CRC16(scratch, 18));
}
SD_SendCommand(CMD_SEND_CSD, 0);
// 128bits + 16 CRC
res = SD_GetResponse(scratch, 1) || !SD_ReadData(scratch, 18);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
return 0;
}else{
printf("CSD: ");
print_hex(scratch, 16);
printf("\n");
//printf(" CRC16: %d\n", SD_CRC16(scratch, 18));
}
return 1;
}
/**
* Read a block of data from the SD card.
*
* Will read a block of data into the specified
* buffer.
*
* @param buf a character pointer to the destination
* @param addr a 32bit start address
* @param size the size of the desired block (16bit)
*
* @return 1 if sucessful, 0 otherwise
*/
uint8_t
SD_ReadBlock(uint8_t *buf, uint32_t addr, uint16_t size)
{
uint8_t res;
// Set the block length... won't work on SDHC
SD_SendCommand(CMD_SET_BLOCKLEN, size);
res = SD_GetResponse(scratch, 1);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SET_BLOCKLEN, res);
SD_DecodeR1(res);
return 0;
}
SD_SendCommand(CMD_READ_BLOCK, addr);
res = SD_GetResponse(scratch, 1);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_READ_BLOCK, res);
SD_DecodeR1(res);
return 0;
}
return SD_ReadData(buf, size);
}
/**
* Writes a block of data to the SD card.
*
* Writes to the SD card in 512byte block sizes. If the
* data is not large enough, fills the rest of the block
* with FILL_BYTE.
*
* @param data pointer to the source of data to write
* @param addr the start address (32bit, must be block aligned)
* @param size the size of the source data (16bit)
*
* @return 1 if sucessful, 0 otherwise
*/
uint8_t
SD_WriteBlock(uint8_t *data, uint32_t addr, uint16_t size)
{
uint8_t res;
uint8_t funcRes = 1;
uint16_t i;
uint16_t crc;
crc = SD_CRC16(data, (uint32_t)size);
// Set the block length... won't work on SDHC
SD_SendCommand(CMD_SET_BLOCKLEN, BLOCK_SIZE);
res = SD_GetResponse(scratch, 1);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SET_BLOCKLEN, res);
SD_DecodeR1(res);
return 0;
}
// Tell it we want to write
SD_SendCommand(CMD_WRITE_BLOCK, addr);
res = SD_GetResponse(scratch, 1);
if(res) {
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_WRITE_BLOCK, res);
SD_DecodeR1(res);
return 0;
}
SPI_SSOn();
// Send "Start Block" byte
SPI_TrxByte(START_BLOCK);
// Send data
SPI_SendBlock(data, size);
// Fill empty space
for(i=size; i<BLOCK_SIZE; i++) {
SPI_TrxByte(FILL_BYTE);
}
// Send CRC (recalc for fill bytes
crc = SD_CRC16_Fill(crc, FILL_BYTE, BLOCK_SIZE-size);
SPI_TrxByte((uint8_t)(crc>>8));
SPI_TrxByte((uint8_t)crc);
SPI_SSOff();
// Response?
res = SD_GetResponse(scratch, 1);
if((res & 0x0F) != 0x05) {
printf("Error: Data rejected (%02hX)\n", res);
SD_DecodeDataRes(res);
funcRes = 0;
}
SPI_SSOn();
// Wait for completion
i=0;
do {
res = SPI_TrxByte(0xFF);
i++;
}while(res != NO_RESPONSE && i < 50000);
SPI_SSOff();
// Did it take a crazy amount of time?
if(res != NO_RESPONSE) {
printf(" Error: cmd=%02hX, res=%02hX\n", 0xFF, res);
return 0;
}
return funcRes;
}
/**
* Erases a block of
没有合适的资源?快使用搜索试试~ 我知道了~
资源详情
资源评论
资源推荐
收起资源包目录
sd.zip_interface_sd card_sd memory card_site:www.pudn.com_spi dr (636个子文件)
sd.aps 4KB
sd.aws 1KB
sd.c 17KB
main.c 7KB
terminal.c 3KB
sci.c 3KB
command.c 2KB
spi.c 2KB
utils.c 2KB
queue.c 1KB
doxygen.css 6KB
tabs.css 2KB
graph_legend.dot 2KB
Doxyfile 63KB
tab_r.gif 3KB
tab_l.gif 706B
tab_b.gif 35B
desc.h 4KB
command.h 916B
queue.h 721B
terminal.h 671B
sd.h 589B
spi.h 543B
utils.h 506B
sci.h 391B
a00011.html 50KB
a00026.html 50KB
sd_8c.html 48KB
a00006.html 29KB
a00005.html 29KB
main_8c.html 20KB
a00012.html 17KB
spi_8c.html 14KB
sci_8c.html 13KB
terminal_8c.html 12KB
a00013.html 11KB
a00015.html 11KB
a00009.html 11KB
spi_8h.html 10KB
a00024.html 10KB
a00016.html 10KB
sd_8h.html 10KB
globals.html 10KB
a00014.html 10KB
a00030.html 10KB
terminal_8h.html 9KB
queue_8h.html 9KB
command_8c.html 9KB
a00003.html 9KB
command_8h.html 9KB
globals_func.html 8KB
a00004.html 8KB
a00008.html 8KB
tree.html 7KB
utils_8h.html 7KB
a00028.html 7KB
a00018.html 7KB
a00017.html 7KB
utils_8c.html 6KB
main.html 6KB
a00007.html 6KB
queue_8c.html 6KB
a00032.html 5KB
structqueue.html 5KB
sci_8h.html 4KB
graph_legend.html 4KB
queue_8h-source.html 4KB
command_8h-source.html 4KB
a00025.html 4KB
a00023.html 4KB
a00010.html 4KB
a00020.html 4KB
a00021.html 4KB
struct_command_def.html 4KB
a00002.html 4KB
files.html 4KB
terminal_8h-source.html 3KB
a00033.html 3KB
spi_8h-source.html 3KB
a00031.html 3KB
a00001.html 3KB
utils_8h-source.html 3KB
sd_8h-source.html 3KB
a00029.html 2KB
a00035.html 2KB
sci_8h-source.html 2KB
a00027.html 2KB
functions.html 2KB
classes.html 2KB
functions_vars.html 2KB
globals_defs.html 2KB
globals_vars.html 2KB
globals_type.html 2KB
annotated.html 2KB
a00022.html 1KB
index.html 415B
Makefile 2KB
a00013_ea2e7526d122ddcc3bc84989abd83c6a_icgraph.map 3KB
a00012_a14a3a4150662024315e78864403ff5f_icgraph.map 3KB
a00012_05039575653a077fb25a28c31d583243_icgraph.map 2KB
共 636 条
- 1
- 2
- 3
- 4
- 5
- 6
- 7
JaniceLu
- 粉丝: 79
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0