Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с SPI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Alex Truhin
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?
aesok
Код настройки SPI.
Функция DF_SPI_RW - это первая функция вызываемая из main ()?

Анатолий.
Alex Truhin
Код настройки:
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?
Lmx2315
прошу прощения если не на то ссылку даю и если ничем особо новым тут не блесну - вот тут описание SPI для atmega128

http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/15.htm
Цитата
void SPI_MasterInit(void)
{
/* Установка MOSI и SCK на вывод, все остальные на ввод */
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
/* Разрешение SPI в режиме мастера, установка скорости связи fck/16
*/SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}
void SPI_MasterTransmit(char cData)
{
/* Запуск передачи данных */
SPDR = cData;
/* Ожидание завершения передачи данных */
while(!(SPSR & (1<<SPIF)))
;
}
KSANDER
Цитата(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).
Alex Truhin
Цитата(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
GDI
Ногу WP подтяните к питанию у АТ45. Можно просто соплю повесить, там нога питания соседняя, если корпус SO-8.
aesok
Как запрограмирован фьюз M103C?
Как скомпилировалась строка rx = SPDR;? Проверте везде не только в функции DF_SPI_RW, но и во всех местах где она проинлайнилась. не выкинул ли ее компилятор.
Есть ли в других местах программы обращение к регистру SPDR? Поставте в отладчике остановку по обращению к адресу SPDR, возможно в него кто то пишет по указателю.
Состояние бита WCOL в SPSR?

Анатолий.
777777
А не сбрасывает ли кто 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;
}
Сергей Борщ
Цитата(777777 @ Oct 8 2010, 13:03) *
А не сбрасывает ли кто SPE случайно?
Можно еще спросить - не настроена ли на ввод нога SS и не подается ли на нее низкий уровень?
Alex Truhin
Ну по порядку:
Цитата
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. если ввести таймаут (см. выше) то память читается.

aesok
> 1. как память slave может влиять на SPI

никак не должна.

> 2. если ввести таймаут (см. выше) то память читается.

похоже на то что гдето происходит несанкционированое обращение к SPSR и/или к SPDR, скорее всего чтение.

Анатолий.
GDI
Цитата(Alex Truhin @ Oct 8 2010, 14:53) *
WP напрямую на мониторе питания, так что тут проблем нет

Вы посмотрите осциллографом, что у Вас творится на интерфейсе. У меня были похожие проблемы с 321-ми и тоже Мега128, точно так же зависало на чтении статуса (похоже это глюк у 321х, возможно у какой-то партии или у меги128), тогда я выяснил что на не подключенном WP плавает потенциал от 0 до питания и потому проблема проявлялась периодически. В зависимости от потенциала АТ45 просто не отвечала ничего на MISO (или ногу Busy не отпускала, я уже плохо помню), помогло прямое подключение ноги WP на питание.

P.S. Хотя, возможно, я ошибаюсь и у меня просто приходил статус, да он был всегда BUSY... В общем осцилл все равно не помешает.
alexeyv
А можно поинтересоваться что у Вас с пином SS (используется или нет и как настроен - вход или выход) ?
GDI
В сообщении №3 все же написано, про входы и выходы.
V_G
Цитата(alexeyv @ Oct 9 2010, 00:08) *
А можно поинтересоваться что у Вас с пином SS (используется или нет и как настроен - вход или выход) ?

Если вопрос по теме топика, то в мастер-режиме пин SS никак не задействован, его можно настраивать как угодно и манипулировать вручную. У меня на SPI сидят несколько устройств, для каждого вручную дергаю свой чипселект (он же SS)
=GM=
Цитата(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);
}
Alex Truhin
Спасибо всем за рекомендации и советы, теперь только в понедельник посмотрю, отпишу результаты.
Цитата
=GM=: Ещё интересует, почему вы читаете статус памяти, но не дожидаетесь готовности бита BUSY?
Вот кусок из старой библиотеки

BUSY смотрю при переключении страниц, при запросе статуса его смотреть не нужно, это видно и из примеров atmel, и по логике, т.к. busy, согласно документации, можно проверять 2 способами, либо проверять на выводе (если он есть), либо проверять бит статуса.
Сергей Борщ
Цитата(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.
demiurg_spb
Настройте ногу SS на выход, как Вам уже ранее неоднократно намекали.
Это стандартные грабли, на которые очень многие наступают:-)

Сори, увидел, что уже спросили Вас об этом (нога SS) и за Вас же ответили...
alexeyv
Цитата
А можно поинтересоваться что у Вас с пином 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.


Это именно по теме топика и именно это я и хотел порекомендовать проверить!!!!!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.