source: branches/v4/softs/tsar_boot/src/sdcard.c @ 1040

Last change on this file since 1040 was 292, checked in by cfuguet, 12 years ago

Changing directory structure of the TSAR boot loader.
A README.txt file has been included to explain the new structure
and the MAKEFILE parameters.

Erasing the heap segment for the boot elf loader. All the work space
is allocated in the stack.

The stack size is defined in the include/defs.h.

Important modification in the reset.S file. The non-boot
processors (processor id != 0) wait in a low comsumption energy
mode to be wake up by processor 0 using an IPI. Each processor
has a private mailbox in the local XICU. The value written in
the mailbox will be used as address to jump by the processors.

The waking up of non-boot processors is not done in this boot loader
so it must be done in the application loaded.

The boot_loader_elf function loads into memory an executable .elf file
which must be placed in the BOOT_LOADER_LBA block of the disk. This
constant can be defined in the include/defs.h file.

File size: 6.8 KB
Line 
1/**
2 * \file    : sdcard.c
3 * \date    : 30 August 2012
4 * \author  : Cesar Fuguet
5 *
6 * This file defines the driver of a SD Card device using an SPI controller
7 */
8
9#include <sdcard.h>
10
11/**
12 * \param   sdcard: Initialized pointer to the block device
13 *
14 * \return  void
15 *
16 * \brief   Enable SD Card select signal
17 */
18static void _sdcard_enable(struct sdcard_dev * sdcard)
19{
20    spi_ss_assert(sdcard->spi, sdcard->slave_id);
21}
22
23/**
24 * \param   sdcard: Initialized pointer to the block device
25 *
26 * \return  void
27 *
28 * \brief   Disable SD Card select signal
29 */
30static void _sdcard_disable(struct sdcard_dev * sdcard)
31{
32    spi_ss_deassert(sdcard->spi, sdcard->slave_id);
33}
34
35/**
36 * \param   tick_count: SD Card clock ticks number
37 *
38 * \return  void
39 *
40 * \brief   Enable SD Card clock
41 *          The tick count is byte measured (1 tick, 8 clock)
42 */
43static void _sdcard_gen_tick(struct sdcard_dev * sdcard, unsigned int tick_count)
44{
45    volatile register int i = 0;
46    while(i++ < tick_count) spi_put_tx(sdcard->spi, 0xFF, 0);
47}
48
49/**
50 * \param   sdcard: Initialized pointer to the block device
51 *
52 * \return  char from the SD card
53 *
54 * \brief   Get a byte from the SD Card
55 */
56static unsigned char _sdcard_receive_char(struct sdcard_dev * sdcard)
57{
58    _sdcard_gen_tick(sdcard, 1);
59
60    return spi_get_rx(sdcard->spi, 0);
61}
62
63/**
64 * \param   sdcard: Initialized pointer to the block device
65 *
66 * \return  sdcard response
67 *
68 * \brief   Wait for a valid response after the send of a command
69 *          This function can return if one of the next two conditions are true:
70 *           1. Bit valid received
71 *           2. Timeout (not valid bit received after SDCARD_COMMAND_TIMEOUT
72 *              wait ticks)
73 */
74static unsigned char _sdcard_wait_response(struct sdcard_dev * sdcard)
75{
76    unsigned char sdcard_rsp;
77    register int  iter;
78
79    iter       = 0;
80    sdcard_rsp = _sdcard_receive_char(sdcard);
81    while (
82            (iter < SDCARD_COMMAND_TIMEOUT) &&
83            !SDCARD_CHECK_R1_VALID(sdcard_rsp)
84          )
85    {
86        sdcard_rsp = _sdcard_receive_char(sdcard);
87        iter++;
88    }
89
90    return sdcard_rsp;
91}
92
93/**
94 * \params  sdcard: Initialized pointer to the block device
95 *
96 * \return  void
97 *
98 * \brief   Wait data block start marker
99 */
100static void _sdcard_wait_data_block(struct sdcard_dev * sdcard)
101{
102        while (_sdcard_receive_char(sdcard) != 0xFE);
103}
104
105/**
106 * \param   sdcard  : Initialized pointer to block device
107 * \param   index   : SD card CMD index
108 * \param   app     : Type of command, 0 for normal command or 1 for application specific
109 * \param   args    : SD card CMD arguments
110 *
111 * \return  response first byte
112 *
113 * \brief   Send command to the SD card
114 */
115static int _sdcard_send_command    (
116        struct sdcard_dev * sdcard ,
117        int                 index  ,
118        int                 app    ,
119        void *              args   ,
120        unsigned            crc7   )
121{
122    unsigned char sdcard_rsp;
123    unsigned char * _args;
124
125    _sdcard_gen_tick(sdcard, 5); 
126
127    if (app == SDCARD_ACMD)
128    {
129        spi_put_tx(sdcard->spi, 0x40 | 55         , 0 );/* CMD and START bit */
130        spi_put_tx(sdcard->spi, 0x00              , 0 );/* Argument[0]       */
131        spi_put_tx(sdcard->spi, 0x00              , 0 );/* Argument[1]       */
132        spi_put_tx(sdcard->spi, 0x00              , 0 );/* Argument[2]       */
133        spi_put_tx(sdcard->spi, 0x00              , 0 );/* Argument[3]       */
134        spi_put_tx(sdcard->spi, 0x01 | (crc7 << 1), 0 );/* END bit           */
135
136        sdcard_rsp = _sdcard_wait_response(sdcard);
137        if (SDCARD_CHECK_R1_ERROR(sdcard_rsp))
138        {
139            return sdcard_rsp;       
140        }
141    }
142
143    _args = (unsigned char *) args;
144
145    _sdcard_gen_tick(sdcard, 1); 
146
147    spi_put_tx(sdcard->spi, 0x40 | index      , 0 );
148    spi_put_tx(sdcard->spi, _args[0]          , 0 );
149    spi_put_tx(sdcard->spi, _args[1]          , 0 );
150    spi_put_tx(sdcard->spi, _args[2]          , 0 );
151    spi_put_tx(sdcard->spi, _args[3]          , 0 );
152    spi_put_tx(sdcard->spi, 0x01 | (crc7 << 1), 0 );
153
154    return _sdcard_wait_response(sdcard);
155}
156
157int sdcard_dev_open(struct sdcard_dev * sdcard, struct spi_dev * spi, int ss)
158{
159    unsigned char args[4];
160        unsigned char sdcard_rsp;
161        unsigned int  iter;
162
163        sdcard->spi      = spi;
164    sdcard->slave_id = ss;
165
166        /*
167     * Supply SD card ramp up time (min 74 cycles)
168     */
169        _sdcard_gen_tick(sdcard, 10);
170
171    /*
172     * Assert slave select signal
173     * Send CMD0 (Reset Command)
174     * Deassert slave select signal
175     */
176        _sdcard_enable(sdcard);
177
178    args[0] = 0;
179    args[1] = 0;
180    args[2] = 0;
181    args[3] = 0;
182        sdcard_rsp = _sdcard_send_command(sdcard, 0, SDCARD_CMD, args, 0x4A);
183        if ( sdcard_rsp != 0x01 )
184        {
185                return sdcard_rsp;
186        }
187
188        _sdcard_disable(sdcard);
189        _sdcard_enable(sdcard);
190
191        iter = 0;
192        while( iter++ < SDCARD_COMMAND_TIMEOUT )
193        {
194                sdcard_rsp = _sdcard_send_command(sdcard, 41, SDCARD_ACMD, args, 0x00);
195                if( sdcard_rsp == 0x01 )
196                {
197                        continue;
198                }
199
200                break;
201        }
202
203        _sdcard_disable(sdcard);
204
205        return sdcard_rsp;
206}
207
208int sdcard_dev_read(struct sdcard_dev * sdcard, void * buf, unsigned int count)
209{
210    unsigned char args[4];
211    unsigned char sdcard_rsp;
212    register int  i;
213
214    for (i = 0; i < 4; i++)
215        args[i] = (sdcard->access_pointer >> (32 - (i+1)*8)) & 0xFF;
216
217    _sdcard_enable(sdcard);
218
219    sdcard_rsp = _sdcard_send_command(sdcard, 17, SDCARD_CMD, args, 0x00);
220    if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
221    {
222        _sdcard_disable(sdcard);
223        return sdcard_rsp;
224    }
225
226    _sdcard_wait_data_block(sdcard);
227
228    for ( i = 0; i < count; i++ )
229    {
230        *((char *) buf + i) = _sdcard_receive_char(sdcard);
231    }
232
233    /*
234     * Get the remainder of the block bytes and the CRC16 (comes
235     * at the end of the data block)
236     */
237    while( i++ < (sdcard->block_length + 2) ) _sdcard_receive_char(sdcard);
238
239    _sdcard_disable(sdcard);
240
241    /*
242     * Move the access pointer to the next block
243     */
244    sdcard->access_pointer += sdcard->block_length;
245
246    return 0;
247}
248
249unsigned int sdcard_dev_write(struct sdcard_dev *sdcard, void * buf, unsigned int count)
250{
251        return 0;
252}
253
254void sdcard_dev_lseek(struct sdcard_dev * sdcard, unsigned int blk_pos)
255{
256    sdcard->access_pointer = sdcard->block_length * blk_pos;
257}
258
259unsigned int sdcard_dev_get_capacity(struct sdcard_dev * sdcard)
260{
261        return sdcard->capacity;
262}
263
264int sdcard_dev_set_blocklen(struct sdcard_dev * sdcard, unsigned int len)
265{
266    unsigned char args[4];
267    unsigned char sdcard_rsp;
268    register int i;
269
270    for (i = 0; i < 4; i++)
271        args[i] = (len >> (32 - (i+1)*8)) & 0xFF;
272
273    _sdcard_enable(sdcard);
274
275    sdcard_rsp = _sdcard_send_command(sdcard, 16, SDCARD_CMD, args, 0x00);
276    if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
277    {
278        _sdcard_disable(sdcard);
279        return sdcard_rsp;
280    }
281
282    _sdcard_disable(sdcard);
283
284    sdcard->block_length = len;
285
286        return 0;
287}
288
289/*
290 * vim: tabstop=4 : shiftwidth=4 : expandtab : softtabstop=4
291 */
Note: See TracBrowser for help on using the repository browser.