|
Проблема с SPI, зависает при обращении к SPDR |
|
|
|
Oct 7 2010, 10:33
|
Группа: Новичок
Сообщений: 8
Регистрация: 13-04-10
Пользователь №: 56 609

|
Atmega 128 и память AT45DB321, читаю статус памяти, SELECT(); status = DF_SPI_RW(StatusReg); status = DF_SPI_RW(0x00); DESELECT();
static uint8_t DF_SPI_RW( uint8_t tx ) { uint8_t rx; SPDR = tx; while(!(SPSR & 0x80)); rx = SPDR; return rx; } при первом чтении все ОК, но при повторном чтении, на строке status = DF_SPI_RW(0x00); программа зависает, т.е. SPSR не взводиться. Возможно есть проблемы с памятью, но почему не взводится флаг SPSR? Ведь насколько я понимаю, мастер устройству пофиг на реакцию слэйв устройства на SPI?
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 20)
|
Oct 7 2010, 15:17
|
Группа: Новичок
Сообщений: 8
Регистрация: 13-04-10
Пользователь №: 56 609

|
Код настройки: static uint8_t df_GetStatus() { uint8_t status;
SELECT(); status = DF_SPI_RW(StatusReg); status = DF_SPI_RW(0x00); DESELECT();
return status; } .... SPCR = 0; // Отключаем SPI чтобы сконфигурировать направление ножек DESELECT(); DDRB &= ~(DF_MISO_PB + DF_READY); DDRB |= DF_MOSI_PB + DF_SCK_PB + DF_SS_PB; // + DF_RESET_PB /* MOSI, SS, RESET, SCK - выходы */ SPCR = (1<<SPE) | (1<<MSTR) | (1<<CPHA) | (1<<CPOL); // Enable SPI in Master mode, mode 3 SPSR = (1<<SPI2X); Определяю тип памяти: chip_id = df_GetStatus() & 0x3C; Это нормально отрабатывает, а вот дальше через некоторое время вызов df_GetStatus(), виснет на строке while(!(SPSR & 0x80));, причем у меня несколько устройств, практически одинаковых, на некоторых работает, на некоторых нет. Сижу вторые сутки нет ни каких идей. Хотя бы в принципе, отчего может не устанавливаться SPSR? Либо в каких ситуациях он сбрасывается кроме записи в SPDR?
|
|
|
|
|
Oct 8 2010, 07:44
|
Группа: Участник
Сообщений: 14
Регистрация: 28-03-08
Пользователь №: 36 297

|
Цитата(Alex Truhin @ Oct 7 2010, 19:17)  Сижу вторые сутки нет ни каких идей. Хотя бы в принципе, отчего может не устанавливаться SPSR? Либо в каких ситуациях он сбрасывается кроме записи в SPDR? Эта ситуация не может возникнуть в Вашем случае?: Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).
|
|
|
|
|
Oct 8 2010, 08:50
|
Группа: Новичок
Сообщений: 8
Регистрация: 13-04-10
Пользователь №: 56 609

|
Цитата(KSANDER @ Oct 8 2010, 17:44)  Эта ситуация не может возникнуть в Вашем случае?: Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR). Да вроде нет. Запись в SPDR и сразу простой цикл ожидания, компилируется он нормально: while(!(SPSR & 0x80)); c7c: 77 9b sbis 0x0e, 7 ; 14 c7e: fe cf rjmp .-4 ; 0xc7c <_Z12df_FlashReadjjjPh+0x74> так что вроде некому сбросить SPIF Хм. Вот нашел аналогичную тему, и то же нет решения: http://electronix.ru/forum/lofiversion/index.php/t59387.html
|
|
|
|
|
Oct 8 2010, 10:03
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
А не сбрасывает ли кто SPE случайно? Может просто ноль в SPCR пишет? Цитата(Alex Truhin @ Oct 7 2010, 14:33)  static uint8_t DF_SPI_RW( uint8_t tx ) { uint8_t rx; SPDR = tx; while(!(SPSR & 0x80)); rx = SPDR; return rx; } Немного позанудствую: а так не проще? uint8_t DF_SPI_RW( uint8_t tx ) { SPDR = tx; while(!(SPSR & (1<<SPIE))) {} return SPDR; }
|
|
|
|
|
Oct 8 2010, 10:53
|
Группа: Новичок
Сообщений: 8
Регистрация: 13-04-10
Пользователь №: 56 609

|
Ну по порядку: Цитата GDI: Ногу WP подтяните к питанию у АТ45. Можно просто соплю повесить, там нога питания соседняя, если корпус SO-8. WP напрямую на мониторе питания, так что тут проблем нет Цитата aesok: Как запрограмирован фьюз M103C? Не запрограммирован, т.е. нормальный режим atmega 128 Цитата Как скомпилировалась строка rx = SPDR;? SPDR = tx; 876: 8f b9 out 0x0f, r24 ; 15 878: 80 e0 ldi r24, 0x00 ; 0 Цитата Проверте везде не только в функции DF_SPI_RW, но и во всех местах где она проинлайнилась. не выкинул ли ее компилятор. Есть ли в других местах программы обращение к регистру SPDR? В нерабочем/тестируемом куске именно такой код, т.е. не выкинул все ОК. Цитата Поставте в отладчике остановку по обращению к адресу SPDR, возможно в него кто то пишет по указателю. Не распаян у меня JTAG, пока посмотреть не могу. Цитата Состояние бита WCOL в SPSR? Посмотрю, может завтра (у нас уже вечер). Цитата 777777: А не сбрасывает ли кто SPE случайно? Может просто ноль в SPCR пишет? Нет. Сделал таймаут ожидания: SPDR = tx; uint8_t Cnt = 0; while(((SPSR & 0x80) == 0) and (Cnt++ < 0xFE)); rx = SPDR; Функция начала нормально читать данные. Но скорость ограниченна таймаутом. Цитата 777777: Немного позанудствую: а так не проще? Проще но при инлайне выкидывается чтение, а оно нужно. Вообще тестирую на нескольких устройствах (пишу прошивку тестирования железа), на некоторых работает абсолютно нормально, на некоторых подвисает, похоже как раз на этих устройствах проблемы с памятью. Непонятно 2 момента: 1. как память slave может влиять на SPI 2. если ввести таймаут (см. выше) то память читается.
|
|
|
|
|
Oct 8 2010, 11:10
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Цитата(Alex Truhin @ Oct 8 2010, 14:53)  WP напрямую на мониторе питания, так что тут проблем нет Вы посмотрите осциллографом, что у Вас творится на интерфейсе. У меня были похожие проблемы с 321-ми и тоже Мега128, точно так же зависало на чтении статуса (похоже это глюк у 321х, возможно у какой-то партии или у меги128), тогда я выяснил что на не подключенном WP плавает потенциал от 0 до питания и потому проблема проявлялась периодически. В зависимости от потенциала АТ45 просто не отвечала ничего на MISO (или ногу Busy не отпускала, я уже плохо помню), помогло прямое подключение ноги WP на питание. P.S. Хотя, возможно, я ошибаюсь и у меня просто приходил статус, да он был всегда BUSY... В общем осцилл все равно не помешает.
--------------------
|
|
|
|
|
Oct 8 2010, 15:31
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Alex Truhin @ Oct 7 2010, 09:33)  uint8_t rx; SPDR = tx; while(!(SPSR & 0x80)); rx = SPDR; при первом чтении все ОК, но при повторном чтении, на строке status = DF_SPI_RW(0x00); программа зависает, т.е. SPSR не взводиться Явно есть проблема с периферией МК, нельзя ли оторвать SCLK и MOSI от чипа памяти и повторить тест? Ещё интересует, почему вы читаете статус памяти, но не дожидаетесь готовности бита BUSY? Вот кусок из старой библиотеки Код //================================================ // Ожидание готовности DataFlash, // проверяем BUSY в регистре статуса //------------------------------------------------ //аргументы: нет //возвращает:значение регистра статуса //================================================ xByte at45WaitReady(st_at45_Data *pntr) { xByte res=0; SET_CS_DATAFLASH; //установим CS для DataFlash txrxByteSpi(at45_StatusRegRead1, pntr->num); //передаем номер команды while (!(res&AT45BUSY)) //ждем пока не установится { res=txrxByteSpi(0, pntr->num); //бит READY/nBUSY в регистре } //статуса DataFlash RESET_CS_DATAFLASH; //сбросим CS для DataFlash return(res); }
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 8 2010, 17:16
|
Группа: Новичок
Сообщений: 8
Регистрация: 13-04-10
Пользователь №: 56 609

|
Спасибо всем за рекомендации и советы, теперь только в понедельник посмотрю, отпишу результаты. Цитата =GM=: Ещё интересует, почему вы читаете статус памяти, но не дожидаетесь готовности бита BUSY? Вот кусок из старой библиотеки BUSY смотрю при переключении страниц, при запросе статуса его смотреть не нужно, это видно и из примеров atmel, и по логике, т.к. busy, согласно документации, можно проверять 2 способами, либо проверять на выводе (если он есть), либо проверять бит статуса.
|
|
|
|
|
Oct 8 2010, 21:20
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(V_G @ Oct 8 2010, 17:47)  Если вопрос по теме топика, то в мастер-режиме пин SS никак не задействован, его можно настраивать как угодно и манипулировать вручную. Это не по теме топика (у автора он настроен на вывод), но для полноты картины: в мастер-режиме, будучи настроенным на ввод эта ножка используется: Цитата If SS is configured as an input, it must be held high to ensure Master SPI operation. If the SS pin is driven low by peripheral circuitry when the SPI is configured as a master with the SS pin defined as an input, the SPI system interprets this as another master selecting the SPI as a slave and starting to send data to it. To avoid bus contention, the SPI system takes the following actions: 1. The MSTR bit in SPCR is cleared and the SPI system becomes a slave. As a result of the SPI becoming a slave, the MOSI and SCK pins become inputs. 2. The SPIF flag in SPSR is set, and if the SPI interrupt is enabled, and the I-bit in SREG is set, the interrupt routine will be executed.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 11 2010, 03:48
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата А можно поинтересоваться что у Вас с пином SS (используется или нет и как настроен - вход или выход) ? Цитата Это не по теме топика (у автора он настроен на вывод), Цитата If SS is configured as an input, it must be held high to ensure Master SPI operation. If the SS pin is driven low by peripheral circuitry when the SPI is configured as a master with the SS pin defined as an input, the SPI system interprets this as another master selecting the SPI as a slave and starting to send data to it. Это именно по теме топика и именно это я и хотел порекомендовать проверить!!!!!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|