source: rtos_arduino/trunk/arduino_lib/libraries/Robot_Control/src/SdCard.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 8.7 KB
Line 
1/* Arduino FAT16 Library
2 * Copyright (C) 2008 by William Greiman
3 *
4 * This file is part of the Arduino FAT16 Library
5 *
6 * This Library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with the Arduino Fat16 Library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20#include <avr/pgmspace.h>
21#if ARDUINO < 100
22#include <WProgram.h>
23#else // ARDUINO
24#include <Arduino.h>
25#endif // ARDUINO
26#include <Fat16Config.h>
27#include <SdCard.h>
28//------------------------------------------------------------------------------
29// r1 status values
30uint8_t const R1_READY_STATE = 0;
31uint8_t const R1_IDLE_STATE = 1;
32// start data token for read or write
33uint8_t const DATA_START_BLOCK = 0XFE;
34// data response tokens for write block
35uint8_t const DATA_RES_MASK = 0X1F;
36uint8_t const DATA_RES_ACCEPTED = 0X05;
37uint8_t const DATA_RES_CRC_ERROR = 0X0B;
38uint8_t const DATA_RES_WRITE_ERROR = 0X0D;
39//
40// stop compiler from inlining where speed optimization is not required
41#define STATIC_NOINLINE static __attribute__((noinline))
42//------------------------------------------------------------------------------
43// SPI static functions
44//
45// clock byte in
46STATIC_NOINLINE uint8_t spiRec(void) {
47 SPDR = 0xff;
48 while (!(SPSR & (1 << SPIF)));
49 return SPDR;
50}
51// clock byte out
52STATIC_NOINLINE void spiSend(uint8_t b) {
53 SPDR = b;
54 while (!(SPSR & (1 << SPIF)));
55}
56//------------------------------------------------------------------------------
57// wait for card to go not busy
58// return false if timeout
59static uint8_t waitForToken(uint8_t token, uint16_t timeoutMillis) {
60 uint16_t t0 = millis();
61 while (spiRec() != token) {
62 if (((uint16_t)millis() - t0) > timeoutMillis) return false;
63 }
64 return true;
65}
66//------------------------------------------------------------------------------
67uint8_t SdCard::cardCommand(uint8_t cmd, uint32_t arg) {
68 uint8_t r1;
69
70 // select card
71 chipSelectLow();
72
73 // wait if busy
74 waitForToken(0XFF, SD_COMMAND_TIMEOUT);
75
76 // send command
77 spiSend(cmd | 0x40);
78
79 // send argument
80 for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
81
82 // send CRC - must send valid CRC for CMD0
83 spiSend(cmd == CMD0 ? 0x95 : 0XFF);
84
85 // wait for not busy
86 for (uint8_t retry = 0; (0X80 & (r1 = spiRec())) && retry != 0XFF; retry++);
87 return r1;
88}
89//------------------------------------------------------------------------------
90uint8_t SdCard::cardAcmd(uint8_t cmd, uint32_t arg) {
91 cardCommand(CMD55, 0);
92 return cardCommand(cmd, arg);
93}
94//==============================================================================
95// SdCard member functions
96//------------------------------------------------------------------------------
97/**
98 * Determine the size of a standard SD flash memory card
99 * \return The number of 512 byte data blocks in the card
100 */
101uint32_t SdCard::cardSize(void) {
102 uint16_t c_size;
103 csd_t csd;
104 if (!readReg(CMD9, &csd)) return 0;
105 uint8_t read_bl_len = csd.read_bl_len;
106 c_size = (csd.c_size_high << 10) | (csd.c_size_mid << 2) | csd.c_size_low;
107 uint8_t c_size_mult = (csd.c_size_mult_high << 1) | csd.c_size_mult_low;
108 return (uint32_t)(c_size+1) << (c_size_mult + read_bl_len - 7);
109}
110//------------------------------------------------------------------------------
111void SdCard::chipSelectHigh(void) {
112 digitalWrite(chipSelectPin_, HIGH);
113 // make sure MISO goes high impedance
114 spiSend(0XFF);
115}
116//------------------------------------------------------------------------------
117void SdCard::chipSelectLow(void) {
118 // Enable SPI, Master, clock rate F_CPU/4
119 SPCR = (1 << SPE) | (1 << MSTR);
120
121 // Doubled Clock Frequency to F_CPU/2 unless speed_ is nonzero
122 if (!speed_) SPSR |= (1 << SPI2X);
123
124 digitalWrite(chipSelectPin_, LOW);
125}
126//------------------------------------------------------------------------------
127void SdCard::error(uint8_t code, uint8_t data) {
128 errorData = data;
129 error(code);
130}
131//------------------------------------------------------------------------------
132void SdCard::error(uint8_t code) {
133 errorCode = code;
134 chipSelectHigh();
135}
136//------------------------------------------------------------------------------
137/**
138 * Initialize a SD flash memory card.
139 *
140 * \param[in] speed Set SPI Frequency to F_CPU/2 if speed = 0 or F_CPU/4
141 * if speed = 1.
142 * \param[in] chipSelectPin SD chip select pin number.
143 *
144 * \return The value one, true, is returned for success and
145 * the value zero, false, is returned for failure.
146 *
147 */
148uint8_t SdCard::init(uint8_t speed, uint8_t chipSelectPin) {
149 if (speed > 1) {
150 error(SD_ERROR_SPI_SPEED);
151 return false;
152 }
153 speed_ = speed;
154 chipSelectPin_ = chipSelectPin;
155 errorCode = 0;
156 uint8_t r;
157 // 16-bit init start time allows over a minute
158 uint16_t t0 = (uint16_t)millis();
159
160 pinMode(chipSelectPin_, OUTPUT);
161 digitalWrite(chipSelectPin_, HIGH);
162 pinMode(SPI_MISO_PIN, INPUT);
163 pinMode(SPI_SS_PIN, OUTPUT);
164 pinMode(SPI_MOSI_PIN, OUTPUT);
165 pinMode(SPI_SCK_PIN, OUTPUT);
166
167 // Enable SPI, Master, clock rate F_CPU/128
168 SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
169
170 // must supply min of 74 clock cycles with CS high.
171 for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
172 digitalWrite(chipSelectPin_, LOW);
173
174 // command to go idle in SPI mode
175 while ((r = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
176 if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
177 error(SD_ERROR_CMD0, r);
178 return false;
179 }
180 }
181 // start initialization and wait for completed initialization
182 while ((r = cardAcmd(ACMD41, 0)) != R1_READY_STATE) {
183 if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
184 error(SD_ERROR_ACMD41, r);
185 return false;
186 }
187 }
188 chipSelectHigh();
189 return true;
190}
191//------------------------------------------------------------------------------
192/**
193 * Reads a 512 byte block from a storage device.
194 *
195 * \param[in] blockNumber Logical block to be read.
196 * \param[out] dst Pointer to the location that will receive the data.
197 * \return The value one, true, is returned for success and
198 * the value zero, false, is returned for failure.
199 */
200uint8_t SdCard::readBlock(uint32_t blockNumber, uint8_t* dst) {
201 if (cardCommand(CMD17, blockNumber << 9)) {
202 error(SD_ERROR_CMD17);
203 return false;
204 }
205 return readTransfer(dst, 512);
206}
207//------------------------------------------------------------------------------
208uint8_t SdCard::readReg(uint8_t cmd, void* buf) {
209 uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
210 if (cardCommand(cmd, 0)) {
211 chipSelectHigh();
212 return false;
213 }
214 return readTransfer(dst, 16);
215}
216//------------------------------------------------------------------------------
217uint8_t SdCard::readTransfer(uint8_t* dst, uint16_t count) {
218 // wait for start of data
219 if (!waitForToken(DATA_START_BLOCK, SD_READ_TIMEOUT)) {
220 error(SD_ERROR_READ_TIMEOUT);
221 }
222 // start first spi transfer
223 SPDR = 0XFF;
224 for (uint16_t i = 0; i < count; i++) {
225 while (!(SPSR & (1 << SPIF)));
226 dst[i] = SPDR;
227 SPDR = 0XFF;
228 }
229 // wait for first CRC byte
230 while (!(SPSR & (1 << SPIF)));
231 spiRec(); // second CRC byte
232 chipSelectHigh();
233 return true;
234}
235//------------------------------------------------------------------------------
236/**
237 * Writes a 512 byte block to a storage device.
238 *
239 * \param[in] blockNumber Logical block to be written.
240 * \param[in] src Pointer to the location of the data to be written.
241 * \return The value one, true, is returned for success and
242 * the value zero, false, is returned for failure.
243 */
244uint8_t SdCard::writeBlock(uint32_t blockNumber, const uint8_t* src) {
245 uint32_t address = blockNumber << 9;
246#if SD_PROTECT_BLOCK_ZERO
247 // don't allow write to first block
248 if (address == 0) {
249 error(SD_ERROR_BLOCK_ZERO_WRITE);
250 return false;
251 }
252#endif // SD_PROTECT_BLOCK_ZERO
253 if (cardCommand(CMD24, address)) {
254 error(SD_ERROR_CMD24);
255 return false;
256 }
257 // optimize write loop
258 SPDR = DATA_START_BLOCK;
259 for (uint16_t i = 0; i < 512; i++) {
260 while (!(SPSR & (1 << SPIF)));
261 SPDR = src[i];
262 }
263 while (!(SPSR & (1 << SPIF))); // wait for last data byte
264 spiSend(0xFF); // dummy crc
265 spiSend(0xFF); // dummy crc
266
267 // get write response
268 uint8_t r1 = spiRec();
269 if ((r1 & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
270 error(SD_ERROR_WRITE_RESPONSE, r1);
271 return false;
272 }
273 // wait for card to complete write programming
274 if (!waitForToken(0XFF, SD_WRITE_TIMEOUT)) {
275 error(SD_ERROR_WRITE_TIMEOUT);
276 }
277 chipSelectHigh();
278 return true;
279}
Note: See TracBrowser for help on using the repository browser.