Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: EFSL стабильна?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
freux
Адаптировал EFSL версии 0.3.4 на ATMega32L на STK-500 под SD. Отладочные строки убрал во flash, все файловые переменные - глобальные, размер стека - 0х180, потребление памяти 1 879 bytes of DATA memory, размер кода несущественен - во flash укладывается.
Examplы - копирование файла, вывод содержимого файла в UART проходят без проблем. Усложнил main - добавил командный процессор - и стал выводить содержимое файлов один за другим. И тут возникли зависания. Отладчика нет. Обложил печатью, и выяснил, что зависания происходят в функции посылки команды - sd_Command. Посмотрел исходники FlashFile v2.10 от Progressive Resources LLC, подправил sd_Command() и sd_readSector() на манер, как это сделано у prllc.
Результат тот же, - несколько раз файл считывается и выводится, затем, при чтении сектора того же файла зависает в sd_Command(). На печать вывожу так же #сектора при вызове sd_readSector() - сектора все те же, что и читались успешно.
Очевидно зависание в while(!(SPSR & (1<<SPIF)));
У Трамперта в "AVR-RISC микроконтроллерах" сказано, что в режиме "мастер" текущая передача может быть прервана подачей 1 в линию SS. Счетчик разрядов и внутрення логика Slave сбрасываются.
Оператор while(!(SPSR & (1<<SPIF))) в sd_Command() я добавил флагом, который взводится таймером через некоторое время после посылки команды так, чтобы исключить зависания. Если флаг взведен, поднимаю линию SS. Однако SD попав в это состояние больше не воспринимает команды - зависание исключено, но и секторы карты больше не читаются.
Теперь подумываю о прерывании питания на карту и ее повторной инициализации в случае продолжительного ожидания в SPI.
F osc = 3.68, F spi пробовал /2, /4 и /8 - безразлично.
Никто не испытывал подобных проблем?
Что посоветуете?
defunct
Цитата(freux @ Feb 16 2009, 23:40) *
размер стека - 0х180, потребление памяти 1 879 bytes of DATA memory, размер кода несущественен - во flash укладывается.

Чем собираете? Если IAR'ом - отдайте под стек все что есть (так как сейчас - у Вас даже на буфер одного сектора нехватает).
Если WinAVR'ом, тогда как посчитали объем стека?

Цитата
Теперь подумываю о прерывании питания на карту и ее повторной инициализации в случае продолжительного ожидания в SPI.
F osc = 3.68, F spi пробовал /2, /4 и /8 - безразлично.

Для FS столь низкая тактовая? Может проц захлебывается данными от SD и обработкой UART'a?...
Если нет подходящего кварца, на внутреннем осцилляторе с OSCCAL = 0xFF получите частоту близкую к 13Mhz.

Цитата
Никто не испытывал подобных проблем?

Всяко бывало. Причиной всему чаще всего - ошибка в программе.

Цитата
Что посоветуете?

Первое - рассчитать или промониторить количество свободных MIPS'ов проца.
И приведите код функций с этой строчкой:
Цитата
Очевидно зависание в while(!(SPSR & (1<<SPIF)));
demiurg_spb
Чтоб небыло проблем с SS настройте ее на вывод или включите pullup обязательно.
Таймеры и т.д. это уже извращения ИМХО.
freux
Цитата(defunct @ Feb 17 2009, 01:43) *
Чем собираете? Если IAR'ом - отдайте под стек все что есть (так как сейчас - у Вас даже на буфер одного сектора нехватает).
Если WinAVR'ом, тогда как посчитали объем стека?

Собираю в IAR 3.20. Как уже говорил, все ёмкие файловые переменные EFSL_Filesystem, File, EFSL_Storage, в том числе содержащий кэш сектора да и другие, как -то буфер, куда читается содержимое сектора поместил в глобальные переменные. В листинге глубина main CSTACK=16, понятно, что полную глубину надо просуммировать, на вскидку получится не более 200. Да я и пробовал варианты, когда эти переменные были в стеке, естественно стек был почти максимальным.

Цитата(defunct @ Feb 17 2009, 01:43) *
Для FS столь низкая тактовая? Может проц захлебывается данными от SD и обработкой UART'a?...
Если нет подходящего кварца, на внутреннем осцилляторе с OSCCAL = 0xFF получите частоту близкую к 13Mhz.

Чтоб не ставить конверторы уровня для SD, я взял L разновидность с Fosc max =8MHz, а STK500 больше 3.68 МГц разгонять не рекомендуют, якобы разводка ПП слишком универсальна - может быть не стабильна. UART много не нагружаю, - вместо отладочных строк вывожу байтовый код, что-то вроде: SendTraceByteToUART(0x34);

Цитата(defunct @ Feb 17 2009, 01:43) *
Всяко бывало. Причиной всему чаще всего - ошибка в программе.

Гм.., но питание SD не прерываете? т.е. как я понял, прервать питание на карте и затем снова ее инициализировать - это единственный способ сброса SD карты? В Отличие от DataFlash памяти, где есть Reset?

Цитата(defunct @ Feb 17 2009, 01:43) *
Первое - рассчитать или промониторить количество свободных MIPS'ов проца.
И приведите код функций с этой строчкой:

Стало быть, одной из возможных причин может быть слишком малая скорость взаимодействия с карточкой? Target устройством будет Mega64, пока не отладил все составные части программы не хотелось бы приступать к разводке платы. Из оставшихся модулей это файловая система и алгоритм upgrade, естественно тоже с карточки. Не считаете ли Вы, перенос на Mega64, подъем до 8 МГц может решить проблему?
CODE

euint8 atmega_spi_send(atmegaSpiInterface *iface, euint8 data)
{
euint8 incoming=0;

// PORTB &= ~(iface->pinSelect);

SPDR = data;
while(!(SPSR & (1<<SPIF)))
incoming = SPDR;

// PORTB |= iface->pinSelect;

return(incoming);
}

Пробовал условие цикла заменить на while((!(SPSR & (1<<SPIF))) && (!flagSPIInt))
flagSPIInt взводится в прерывании (пробовал разные продолжительности: CK/256 -> 17.6 mS)
Далее в функции чтения сектора, что-то вроде
CODE

for(uLoop=0; uLoop<4; uLoop++)
{
sd_clear_buff(ssp);
if (sd_Command(ssp,CMDREAD, (euint16) (place >> 16), (euint16) place) != 0)
{
ssp->spi_CS_OFF(ssp->spiHwInterface);
SendTraceByteToUART(0x2F);
continue;
}
SendTraceByteToUART(0x31);

cardresp=sd_Resp8b(ssp); /* Card response */
if (flagSPIInt)
{
ssp->spi_CS_OFF(ssp->spiHwInterface);
SendTraceByteToUART(0x2F);
continue;
}


sd_clear_buff() выглядит следующим образом
CODE

void sd_clear_buff(SdSpiProtocol *ssp)
{
sd_resetSPITimer();
ssp->spi_CS_OFF(ssp->spiHwInterface);
ssp->spiSendByte(ssp->spiHwInterface,0xff);
ssp->spiSendByte(ssp->spiHwInterface,0xff);
}

Это позаимствовал у FlashFile от prllc


Цитата(demiurg_spb @ Feb 17 2009, 12:13) *
Чтоб небыло проблем с SS настройте ее на вывод или включите pullup обязательно.

Про pullup хорошая идея, внутренний сгодится?

Цитата(demiurg_spb @ Feb 17 2009, 12:13) *
Таймеры и т.д. это уже извращения ИМХО.

Когда есть конструкции вида: while(!(SPSR & (1<<SPIF)))
есть вероятность повиснуть там навсегда, и, тогда либо неуправляемый сброс от сторожевой собаки, либо своя управляемая обработка.
Ну это как если бы вынул сидюк из CDROM во время чтения, а Windows завис и потребовалась перезагрузка! biggrin.gif

Цитата(freux @ Feb 17 2009, 13:21) *
Про pullup хорошая идея, внутренний сгодится?

Ерунду сморозил: SS линия настроена на выход, внутреннего pullupа быть не может:
CODE

...
/* Set as master, clock and chip select output */
DDR_SPI = (1<<DD_MOSI) | (1<<DD_SCK) | 1;
...

PB0 - SlaveSelect
defunct
Цитата(freux @ Feb 17 2009, 12:48) *
Чтоб не ставить конверторы уровня для SD, я взял L разновидность с Fosc max =8MHz, а STK500 больше 3.68 МГц разгонять не рекомендуют, якобы разводка ПП слишком универсальна - может быть не стабильна.

Насчет разводки - справедливо для кварца (площадка по центру платы). А на внутреннем осцилляторе (Int RC Osc он внутри чипа) можно ставить все что угодно, разводка никак не повлияет.

Насчет L-ки, как для разового теста (а Вам больше и не надо) можно попробовать включить ее выше 8Mhz... Должна запуститься без проблем. В любом случае ничего не теряете, т.к. после сброса OSCCAL обновляется заводским калибровочным значением и генератор будет работать на штатной частоте.

Цитата
Гм.., но питание SD не прерываете? т.е. как я понял, прервать питание на карте и затем снова ее инициализировать - это единственный способ сброса SD карты? В Отличие от DataFlash памяти, где есть Reset?

Нет, такого делать не доводилось. В случае с DF - тоже не приходилось Reset дергать...

Цитата
Стало быть, одной из возможных причин может быть слишком малая скорость взаимодействия с карточкой? Target устройством будет Mega64, пока не отладил все составные части программы не хотелось бы приступать к разводке платы. Из оставшихся модулей это файловая система и алгоритм upgrade, естественно тоже с карточки. Не считаете ли Вы, перенос на Mega64, подъем до 8 МГц может решить проблему?
Шанс есть, но он невелик. Частоту поднять и попробовать в Ваших силах прямо на STK.


По коду похоже что есть ошибка:
Код
//    PORTB &= ~(iface->pinSelect);
    SPDR = data;
    while(!(SPSR & (1<<SPIF)))   <---- ТУТ нехватает ";"

    incoming = SPDR;
//    PORTB |= iface->pinSelect;


Еще остаются вопросы с SS и ChipSelect'ом.
(spi_CS_OFF() и spi_CS_ON()) по приведенному коду видно где отключается CS, а где включается - нет.

Цитата
Про pullup хорошая идея, внутренний сгодится?

Более правильная идея (если SPI не предполагается использовать в роли слейва) - пользовать этот самый пин SS как ChipSelect SD!

Цитата
Когда есть конструкции вида: while(!(SPSR & (1<<SPIF)))
есть вероятность повиснуть там навсегда, и, тогда либо неуправляемый сброс от сторожевой собаки, либо своя управляемая обработка.

Вероятность появится только если для этого есть какие-то предпосылки. Когда все гладко - нет причин подвисания на этой строке!
demiurg_spb
Цитата(defunct @ Feb 17 2009, 15:10) *
Вероятность появится только если для этого есть какие-то предпосылки. Когда все гладко - нет причин подвисания на этой строке!
Я тоже так считаю и всегда делаю это допущение - проблем нет и не было никогда...
А SS использовать как CS, так это же классикаsmile.gif
freux
Цитата(defunct @ Feb 17 2009, 15:10) *
Частоту поднять и попробовать в Ваших силах прямо на STK.

Попробую в ближайшем подходе!

Цитата(defunct @ Feb 17 2009, 15:10) *
По коду похоже что есть ошибка:
Код
//    PORTB &= ~(iface->pinSelect);
    SPDR = data;
    while(!(SPSR & (1<<SPIF)))   <---- ТУТ нехватает ";"

    incoming = SPDR;
//    PORTB |= iface->pinSelect;


Еще остаются вопросы с SS и ChipSelect'ом.
(spi_CS_OFF() и spi_CS_ON()) по приведенному коду видно где отключается CS, а где включается - нет.

Убедился, действительно, исходники efsl включают incoming = SPDR; в цикл, а вот FlashFile от prllc - нет, у них цикл пустой, только проверка флага. Спасибо, что обратили на это внимание! a14.gif

Карта выбирается в начале sd_Command()
Код
esint8 sd_Command(SdSpiProtocol *ssp,euint8 cmd, euint16 paramx, euint16 paramy)
{
        ssp->spi_CS_ON(ssp->spiHwInterface);
        
    ssp->spiSendByte(ssp->spiHwInterface,0x40 | cmd);
    if (flagSPIInt)
        return (-1);
    ssp->spiSendByte(ssp->spiHwInterface,(euint8) (paramx >> 8));/* MSB of x */
    if (flagSPIInt)
        return (-1);
    ssp->spiSendByte(ssp->spiHwInterface,(euint8) (paramx));      /* LSB of x */
    if (flagSPIInt)
        return (-1);
    ssp->spiSendByte(ssp->spiHwInterface,(euint8) (paramy >> 8));/* MSB of y */
    if (flagSPIInt)
        return (-1);
    ssp->spiSendByte(ssp->spiHwInterface,(euint8) (paramy));      /* LSB of y */
    if (flagSPIInt)
        return (-1);

    if (cmd == 0)
    /* Checksum (should be only valid for first command (0) */
      ssp->spiSendByte(ssp->spiHwInterface,0x95);
        else
    /* Eat response, we don't care for now */
      ssp->spiSendByte(ssp->spiHwInterface,0xff);
    if (flagSPIInt)
        return (-1);
        
        return (0);
}

Также привожу модифицированную функцию чтения сектора (может еще что-нибудь найдете):
Код
esint8 sd_readSector(SdSpiProtocol *ssp,euint32 address, euint8* buf)
{
    euint8 cardresp;
    euint8 firstblock;
    euint8 c, uLoop;
    euint16 fb_timeout=0xffff;
    euint32 i;
    euint32 place;
    const euint16 len=512; /* FIXME */
SendTraceByteToUART(0x30);
SendLongToUART(address);

    /*DBG((TXT("sd_readSector::Trying to read sector %u and store it at %p.\n"),address,&buf[0]));*/
    place=512*address;
    for(uLoop=0; uLoop<4; uLoop++)
    {
        sd_clear_buff(ssp);
        if (sd_Command(ssp,CMDREAD, (euint16) (place >> 16), (euint16) place) != 0)
        {
                ssp->spi_CS_OFF(ssp->spiHwInterface);
SendTraceByteToUART(0x2F);
                continue;
        }
SendTraceByteToUART(0x31);
    
        cardresp=sd_Resp8b(ssp); /* Card response */
        if (flagSPIInt)
            {
                ssp->spi_CS_OFF(ssp->spiHwInterface);
SendTraceByteToUART(0x2F);
                continue;
        }

SendTraceByteToUART(0x32);

        for(i=0; ((i<1000)&&(cardresp!=0xFE)); i++)
        {
              sd_resetSPITimer();
              cardresp=sd_Resp8b(ssp);
              if (flagSPIInt)
                  {
                      ssp->spi_CS_OFF(ssp->spiHwInterface);
                      break;
              }
            }
SendTraceByteToUART(0x33);

            if (cardresp==0xFE)
            {    
            for(i=0;i<512;i++){
                sd_resetSPITimer();
            c = ssp->spiSendByte(ssp->spiHwInterface,0xff);
                    if (flagSPIInt)
                    {
                          ssp->spi_CS_OFF(ssp->spiHwInterface);
                          break;
                }
            if(i<len)
            buf[i] = c;
            }
SendTraceByteToUART(0x34);
                if (flagSPIInt)
                    continue;

    /* Checksum (2 byte) - ignore for now */
            ssp->spiSendByte(ssp->spiHwInterface,0xff);
            ssp->spiSendByte(ssp->spiHwInterface,0xff);
            ssp->spiSendByte(ssp->spiHwInterface,0xff);
SendTraceByteToUART(0x35);
                ssp->spi_CS_OFF(ssp->spiHwInterface);
                return(0);
            }   // if (cardresp==0xFE)
        }   // for uLoop<4
    sd_Resp8bError(ssp,cardresp);
        ssp->spi_CS_OFF(ssp->spiHwInterface);
    return(-1);
}

Цитата(defunct @ Feb 17 2009, 15:10) *
Более правильная идея (если SPI не предполагается использовать в роли слейва) - пользовать этот самый пин SS как ChipSelect SD!

SPI Master, но есть еще один Slave - это DataFlash, и вот там SS пином выступает PB4

Цитата(defunct @ Feb 17 2009, 15:10) *
Вероятность появится только если для этого есть какие-то предпосылки. Когда все гладко - нет причин подвисания на этой строке!

А предпосылки - это вынимание пользователем карточки во время записи, дефективная карточка, сам пользователь дефективный.. biggrin.gif
GDI
Сделайте этот цикл конечным, вставьте счетчик, чтоб он, к примеру, только 1000 раз опрашивал готовность SPI, а после выхода проверку на этот же счетчик, если вышли по таймауту, то какие то действия сделать, карту переинитить или еще что нибудь.
defunct
Цитата(freux @ Feb 17 2009, 15:35) *
А предпосылки - это вынимание пользователем карточки во время записи, дефективная карточка, сам пользователь дефективный.. biggrin.gif

Отключение слейва (вынимание карточки) на мастер не должно влиять! Просто прочитается мусор. ;>
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.