From 20ad32bb18c002b3fe860a909c6ed06ed3ce29cb Mon Sep 17 00:00:00 2001
From: Arnout Vandecappelle <arnout@mind.be>
Date: Mon, 21 Jun 2010 18:15:38 +0200
Subject: [PATCH] c/src/libchip/i2c/spi-sd-card.c: do read polling in bigger chunks and
allow higher-priority tasks to take over.
---
src/c/src/libchip/i2c/spi-sd-card.c | 61 +++++++++++++++++++++--------------
1 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/src/c/src/libchip/i2c/spi-sd-card.c b/src/c/src/libchip/i2c/spi-sd-card.c
index effdeb8..3fb9a70 100644
a
|
b
|
static int sd_card_wait( sd_card_driver_entry *e) |
374 | 374 | FIXME should actually look at R2W_FACTOR for non-HC cards. */ |
375 | 375 | int retries = e->n_ac_max * 25 / 10; |
376 | 376 | /* n_ac_max/100 is supposed to be the average waiting time. To |
377 | | approximate this, we start with waiting n_ac_max/250 and |
| 377 | approximate this, we start with waiting n_ac_max/150 and |
378 | 378 | gradually increase the waiting time. */ |
379 | 379 | int wait_time_bytes = (retries + 149) / 150; |
380 | 380 | while (e->busy) { |
… |
… |
static int sd_card_read( sd_card_driver_entry *e, uint8_t start_token, uint8_t * |
530 | 530 | { |
531 | 531 | int rv = 0; |
532 | 532 | |
533 | | /* Access time idle tokens */ |
534 | | uint32_t n_ac = 1; |
535 | | |
536 | 533 | /* Discard command response */ |
537 | 534 | int r = e->response_index + 1; |
538 | 535 | |
539 | | /* Minimum token number before data start */ |
540 | | int next_response_size = 2; |
541 | | |
542 | 536 | /* Standard response size */ |
543 | 537 | int response_size = SD_CARD_COMMAND_SIZE; |
544 | 538 | |
| 539 | /* Where the response is stored */ |
| 540 | uint8_t *response = e->response; |
| 541 | |
545 | 542 | /* Data input index */ |
546 | 543 | int i = 0; |
547 | 544 | |
548 | 545 | /* CRC check of data */ |
549 | 546 | uint16_t crc16; |
550 | 547 | |
| 548 | /* Maximum number of tokens to read. */ |
| 549 | int retries = e->n_ac_max; |
| 550 | |
| 551 | /* How much to sleep when retrying. First time, don't sleep yet |
| 552 | since there is a high likelihood that the access time is just |
| 553 | a few bytes. */ |
| 554 | int wait_time_bytes = 0; |
| 555 | |
551 | 556 | SD_CARD_INVALIDATE_RESPONSE_INDEX( e); |
552 | 557 | |
553 | 558 | while (true) { |
554 | 559 | RTEMS_DEBUG_PRINT( "Search from %u to %u\n", r, response_size - 1); |
555 | 560 | |
556 | 561 | /* Search the data start token in in current response buffer */ |
| 562 | retries -= (response_size - r); |
557 | 563 | while (r < response_size) { |
558 | | RTEMS_DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]); |
559 | | if (n_ac > e->n_ac_max) { |
560 | | RTEMS_SYSLOG_ERROR( "Timeout\n"); |
561 | | return -RTEMS_IO_ERROR; |
562 | | } else if (e->response [r] == start_token) { |
| 564 | RTEMS_DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, response [r]); |
| 565 | if (response [r] == start_token) { |
563 | 566 | /* Discard data start token */ |
564 | 567 | ++r; |
565 | 568 | goto sd_card_read_start; |
566 | | } else if (SD_CARD_IS_DATA_ERROR( e->response [r])) { |
567 | | RTEMS_SYSLOG_ERROR( "Data error token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]); |
| 569 | } else if (SD_CARD_IS_DATA_ERROR( response [r])) { |
| 570 | RTEMS_SYSLOG_ERROR( "Data error token [%02i]: 0x%02" PRIx8 "\n", r, response [r]); |
568 | 571 | return -RTEMS_IO_ERROR; |
569 | | } else if (e->response [r] != SD_CARD_IDLE_TOKEN) { |
570 | | RTEMS_SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]); |
| 572 | } else if (response [r] != SD_CARD_IDLE_TOKEN) { |
| 573 | RTEMS_SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, response [r]); |
571 | 574 | return -RTEMS_IO_ERROR; |
572 | 575 | } |
573 | | ++n_ac; |
574 | 576 | ++r; |
575 | 577 | } |
576 | 578 | |
577 | | /* Query more */ |
578 | | rv = sd_card_query( e, e->response, next_response_size); |
579 | | RTEMS_CHECK_RV( rv, "Query data start token"); |
| 579 | if (retries <= 0) { |
| 580 | RTEMS_SYSLOG_ERROR( "Timeout\n"); |
| 581 | return -RTEMS_IO_ERROR; |
| 582 | } |
580 | 583 | |
581 | | /* Set standard query size */ |
582 | | response_size = next_response_size; |
583 | | next_response_size = SD_CARD_COMMAND_SIZE; |
| 584 | if (e->schedule_if_busy) |
| 585 | rtems_task_wake_after( RTEMS_YIELD_PROCESSOR); |
| 586 | |
| 587 | /* Query more. We typically have to wait between 10 and 100 |
| 588 | bytes. To reduce overhead, read the response in chunks of |
| 589 | 50 bytes - this doesn't introduce too much copy overhead |
| 590 | but does allow SPI DMA transfers to work efficiently. */ |
| 591 | response = in; |
| 592 | response_size = 50; |
| 593 | if (response_size > n) |
| 594 | response_size = n; |
| 595 | rv = sd_card_query( e, response, response_size); |
| 596 | RTEMS_CHECK_RV( rv, "Query data start token"); |
584 | 597 | |
585 | 598 | /* Reset start position */ |
586 | 599 | r = 0; |
… |
… |
sd_card_read_start: |
590 | 603 | |
591 | 604 | /* Read data */ |
592 | 605 | while (r < response_size && i < n) { |
593 | | in [i++] = e->response [r++]; |
| 606 | in [i++] = response [r++]; |
594 | 607 | } |
595 | 608 | |
596 | 609 | /* Read more data? */ |