Перейти к содержанию
    

LPC1756+AT45DB081D

Имеем связку из LPC1756 и AT45DB081D через блок SSP в режиме SPI.

Пытаюсь считать Manufacturer ID (opcode - 0x9f)

По приему в буфеер оказывается значение 0x1E 0x00 0x00 0x00 (должно быть 0x1F 0x25 0x00 0x00).

Посмотрев осцилом на линии на первый взгляд всё порядке : cs опущен, тактирование идет, опкод заносится и от at45 приходит 0x1E( вместо ожидаемого).

Может кто с таким уже сталкивался , в чём может быть причина такого поведения ?

 

Инициализация SSP в SPI Mode 0 (P0.15,16,17,18 -- CLK,!CS,MISO,MOSI )

  DataFlashSSP_CFG.CPHA=SSP_CPHA_FIRST;
DataFlashSSP_CFG.CPOL=SSP_CPOL_LO;
DataFlashSSP_CFG.ClockRate=1000000;
DataFlashSSP_CFG.Mode=SSP_MASTER_MODE;
DataFlashSSP_CFG.FrameFormat=SSP_FRAME_SPI;
DataFlashSSP_CFG.Databit = SSP_DATABIT_8;
SSP_ConfigStructInit(&DataFlashSSP_CFG);
SSP_Init(LPC_SSP0, &DataFlashSSP_CFG);

CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_SSP0, CLKPWR_PCLKSEL_CCLK_DIV_2);

SSP_Cmd(LPC_SSP0, ENABLE);

/* ждем пока освободится*/
while( LPC_SSP0->SR & SSP_SR_BSY ) { ; }

/* очистка FIFO */
while( LPC_SSP0->SR & SSP_SR_RNE ) {
	volatile uint32_t dummy = LPC_SSP0->DR;
	(void)dummy;

 

Чтение Manufacturer ID

 

   CS(LOW):
   delay_us(10);
   LPC_SSP0->DR = 0x9f;
   while (LPC_SSP0->SR & SSP_SR_BSY ) { ; }
   rx_data=LPC_SSP0->DR;

 for (i=0;i<4;i++)
  {
    LPC_SSP0->DR = 0xFF;
    while (LPC_SSP0->SR & SSP_SR_BSY ) { ; }
    buf[i] = LPC_SSP0->DR; 
  }  
  CS(HI);
  delay_ms(1);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы бы написали, что эта чудо-библиотека делает в SSP_ConfigStructInit и SSP_Init.

 

И это... у меня всё работает :-) LPC1768, AT45DB161D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SSP_ConfigStructInit и SSP_Init стандартные функции из nxp lpx17xx cmsis library.

 

SSP_ConfigStructInit - инициализирует поля структуры настроек SSP значениями по умолчанию.

SSP_Init - установка скорости, параметров из DataFlashSSP_CFG, подача питания и тактирования на модуль.

 

P.S 1 ошибка в моем коде - SSP_ConfigStructInit должна находится в начале первого блока с кодом.

P.P.S настройка в режим SPI Mode 3 ничего не дала (

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вот честное слово, лениво продираться через высосанные из пальца дефайны. Имхо, периферия на NXP документирована достаточно хорошо, чтобы не использовать ещё какие-то дополнительные библиотеки.

 

Например, неочевидно мне, что тут пишут в CR1. Надо прочитать Ваш исходник, заголовок драйвера и сам драйвер, и только потом смотреть в даташит.

    tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
    // Write back to CR1
    SSPx->CR1 = tmp;

 

Рабочий код обмена с SPI:

 

#define        SPI_REG(reg)    SSP1->reg

#define        SPI_WAIT_READY()                while (SPI_REG(SR) & SPI_SR_BUSY)


//    Процедура инициализации (возвращает код ошибки)
dword    SPI_Init(void)
{
    // устанавливается в стартапе: SSP1 on, PCLK = CCLK
    //PCONP |= BIT(10);
    //CLKSEL (PCLKSEL0, 1, 20);

    SPI_DISABLE_ALL_CHIP();

    SPI_REG(CPSR)    =    6;
    SPI_REG(CR0)    =    0x0007;
    SPI_REG(IMSC)    =    0x0;
    SPI_REG(DMACR)    =    0x0;
    SPI_REG(CR1)    =    0x2;

    while    (SPI_REG(SR) & SPI_SR_RNE)
        SPI_REG(DR);
    return 0;
}

//    Процедура запуска одного цикла работы
dword    SPI_Run    (dword    aSendByte)
{
    SPI_REG(DR)    =    aSendByte;
    SPI_WAIT_READY();
    return    SPI_REG(DR);
}

 

ChipSelect сконфигурирован как GPIO, остальные ноги - как SSP (в другом модуле, здесь не видно).

После перехода CS low->high рекомендую добавить несколько (я сделал десяток) nop'ов - у контроллера ноги весьма быстрые, память может не "почуствовать" деактивации. Хотя, как я вижу, уже есть delay_ms(1) - это слегка избыточно, но для проверки сойдёт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Функция обмена по SPI была рабочая, проверил на другой плате ( подпаявшись на прямую, достал из загашника ).

Чувствую дело в инициализации работы самой памяти.

 

При старте делаю :

 

delay_us(70); //power-up Vcc
CS(LOW);
delay_ms(20); //delay before write allowed
CS(HI);

 

CS как GPIO, остальные как SSP. Используется внутренняя подтяжка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну работает же у меня! :-) Проверил ещё раз:

на 0xD7 возвращается 0xAC

на 0x9F возвращается 0x1F,0x26 (у меня объем памяти другой)

 

Единственное, что Вы не указали - реализация CS(HI) / CS(LOW). Может, тут ошибка?

 

Также, в теории, возможна дохлая микросхема. Проверяли на другой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверял, тоже самое.

Различие в уровнях может вызывать такое поведение ( на отладочной плате пины с 3,3 В , а питание платки с dataflash 3 В) ?

#define LOW 0
#define HI  1

void CS (uint8_t type)
{
   if (type)
     {
        GPIO_SetValue(0, (1 << 16)); // Set Value on PIN  - port num , pin  
     }
   else
     {
        GPIO_ClearValue(0, (1 << 16));
     }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, ну не нравятся мне эти супер-библиотеки!

Вся эта супер-портабельная фигня заменяется ОДНОЙ строкой.

void GPIO_SetValue(uint8_t portNum, uint32_t bitValue)
{
LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);

if (pGPIO != NULL) {
	pGPIO->FIOSET = bitValue;
}
}

static LPC_GPIO_TypeDef *GPIO_GetPointer(uint8_t portNum)
{
LPC_GPIO_TypeDef *pGPIO = NULL;

switch (portNum) {
case 0:
	pGPIO = LPC_GPIO0;
	break;
case 1:
	pGPIO = LPC_GPIO1;
	break;
case 2:
	pGPIO = LPC_GPIO2;
	break;
case 3:
	pGPIO = LPC_GPIO3;
	break;
case 4:
	pGPIO = LPC_GPIO4;
	break;
default:
	break;
}

return pGPIO;
}

LPC_GPIO0->FIOSET = (1UL<<16);

 

По делу:

Описание того, что флеш и контроллер находятся на разных платах, я упустил...

Осталось только проверить, что земли одинаковые, и хорошо связанные.

 

О! И что ещё вспомнил!! Я ведь тоже м/с на "соплях" подвешивал! В даташите на эту флеш указано макс. время фронтов клока. Оно там не просто так указано, при превышении этого значения начинаются разные странные вещи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня точно такая же проблема, но контроллер STM32 а флешку пробовал at45db161 и at45db642. Спаяно 4 платы, одна работает без проблем. На трех на команду 9F читается 0x1E 0x00 0x00 0x00 именно такое значение выдает и флешка, видно осциллом.

На плате имеются длинные дорожки к другой SPI микросхеме, та микросхема читается без каких либо проблем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Простите, а разве нельзя просто частоту уменьшить если у вас паразитные емкости из-за плохого монтажа ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Частоту итак понижал до 250 КГц. Проблема похоже решена. Воткнул последовательно сигнальным линиям резисторы 100 Ом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Простите, а разве нельзя просто частоту уменьшить если у вас паразитные емкости из-за плохого монтажа ?

Повторюсь. У этих микросхем есть параметр SCR rise (fall) time, равный 0.1 V/ns min. Для 3 вольт питания это означает максимальное время фронта 30 наносекунд.

 

По опыту, при превышении этих параметров будет работать именно так, как описано - читается всякая фигня, вне зависимости от самой частоты клока. При этом форма сигнала довольно хорошая...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поясню тоже на будущее для других. Возможно кому-то поможет.

У меня тоже устройство состоит из двух лпат.

На первой стоит STM32 и в паре сантиметров от нее AT45DB642. На другой плате ADE7878. Обе микросхемы висят на одной шине SPI.

Суммарное расстояние до ADE порядка 30см. Межплатный разъем примерно по середине.

У разъема стоят резисторы 100 Ом последовательно и кондеры 1000пф на землю. С емкостью я похоже переборщил.

ADE отлично работает на длинной линии с таким резистором и емкостью.

Попробовал снять кондеры, ADE по-прежнему работает. с SPI флеш ничего не изменилось.

Запаял последовательно SPI флеш резисторы 100 Ом, кондеры по прежнему сняты. Все заработало.

Но ведь эти резисторы опять же увеличили длительность фронта.

Кондеры я ставил с целью избавится от отражений которые могли вызывать появление ложных фронтов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кондеры я ставил с целью избавится от отражений которые могли вызывать появление ложных фронтов.
Резисторы тоже. Завалили фронт, уменьшили спектр.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...