Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: f149 UART1(SPI mode)&DataFlash - грабли
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
O.L.
Пытаюсь отработать процедуры для AT45DB161. UART0 - SerialPort, UART1 SPI 3-wire.

Чтение и запись обоих буферов DataFlash проходит, есть грабельки, но не смертельные.
Прямое чтение страницы MM из DataFlash как и запись MM через оба буфера - вообще без проблем.
Операции стирания страниц, запись содержимого любого из буферов в любую страницу MM, загрузка любой страницы MM в любой буфер - не проходят вообще.
Перебор уровней оптимизации IAR-овского компайлера не влияет, процедуры то простенькие, существенной разницы в ассемблерных листингах нет.
Передрал несколько вариантов инициализации порта, вот так выглядит самый устойчивый.
Код
//    - initialisation spi1 UART module -----------
void spi1_init (void)
{
    U1CTL |= CHAR + SYNC + MM + SWRST;  // 8-bit, SPI, Master
    U1TCTL |= CKPL + SSEL1 + STC;      // Polarity, SMCLK, 3-wire
    U1BR0 = 0x02;          // SPICLK = SMCLK/2 ~ 4MHz
    U1BR1 = 0x00;
    U1MCTL = 0x00;
    ME2 |= USPIE1;          // Module enable
    U1CTL &= ~SWRST;      // Restart USART SPI, SPI enable
//    IE2 |= URXIE1 + UTXIE1;        // RX and TX interrupt enable
}

Опыта работы с DataFlash не так много. Собственно сами процедуры работы перенес с HiTech для pic18-го и DF AT45D011
Вторую неделю бъюсь и здравых мыслей уже нет. Остались только дурацкий колпак и бубен ...
kpv
Цитата(O.L. @ Jun 10 2005, 10:28)
Вторую неделю бъюсь и здравых мыслей уже нет. Остались только дурацкий колпак и бубен ...
*

телепаты тоже в отпуске - что за "не смертельные грабельки и процедуры простенькие"?
O.L.
"Несмертельные" грабли, Это при записи страницы в нулевой байт всегда пишется 0. А простенькие процедуры они завсегда тривиальные, типа такого:
Код
//    - erasing DataFlash -------------------------
void erasing (unsigned int page_cnt)
{
    RLedOn;        // Led red anabled
    _DINT();
    while(!(P5IN & DF_RDY_BUSY));      // waite
    P5OUT &= ~DF_CHIP_SEL;    // enabled DataFlash
    TXBUF1 = PAGE_ERASE;
    while ((IFG2&UTXIFG1)!=UTXIFG1);  // USART1 TX buffer ready?
    TXBUF1 = (char)(page_cnt>>8);
    while ((IFG2&UTXIFG1)!=UTXIFG1);  // USART1 TX buffer ready?
    TXBUF1 = (char)page_cnt;
    while ((IFG2&UTXIFG1)!=UTXIFG1);  // USART1 TX buffer ready?
    TXBUF1 = 0x00;
    while ((IFG2&UTXIFG1)!=UTXIFG1);  // USART1 TX buffer ready?
    P5OUT |= DF_CHIP_SEL;    // disabled DataFlash
    _EINT();

}

и ассемблер у ней соответствующий:
Код
  \   __code void erasing(unsigned int)
  \                     erasing:
  \   000000   B012....             CALL    #??Subroutine3_0
  \                     ??erasing_0:
  \   000004   D2B33000             BIT.B   #0x1, &0x30
  \   000008   FD2B                 JNC     ??erasing_0
  \   00000A   F2C020003100         BIC.B   #0x20, &0x31
  \   000010   F24081007F00         MOV.B   #0x81, &0x7f
  \                     ??erasing_1:
  \   000016   F2B020000300         BIT.B   #0x20, &0x3
  \   00001C   FC2B                 JNC     ??erasing_1
  \   00001E   B012....             CALL    #??Subroutine6_0
  \                     ??erasing_2:
  \   000022   F2B020000300         BIT.B   #0x20, &0x3
  \   000028   FC2B                 JNC     ??erasing_2
  \   00002A   C24C7F00             MOV.B   R12, &0x7f
  \                     ??erasing_3:
  \   00002E   F2B020000300         BIT.B   #0x20, &0x3
  \   000034   FC2B                 JNC     ??erasing_3
  \   000036   ....                 JMP     ??Subroutine0_0

// 6_0
  \                     ??Subroutine6_0:
  \   000000   0F4C                 MOV.W   R12, R15
  \   000002   8F10                 SWPB    R15
  \   000004   C24F7F00             MOV.B   R15, &0x7f
  \   000008   3041                 RET
// 3_0
  \                     ??Subroutine3_0:
  \   000000   E2C22100             BIC.B   #0x4, &0x21
  \   000004   32C2                 DINT
  \   000006   0343                 NOP
  \   000008   3041                 RET
// 0_0
  \                     ??Subroutine0_0:
  \   00001C   C2437F00             MOV.B   #0x0, &0x7f
  \                     ??write_page_flash_4:
  \   000020   F2B020000300         BIT.B   #0x20, &0x3
  \   000026   FC2B                 JNC     ??write_page_flash_4
// 8_0
  \                     ??Subroutine8_0:
  \   000000   F2D020003100         BIS.B   #0x20, &0x31
  \   000006   32D2                 EINT
  \   000008   3041                 RET


Все как надо, только не работает ...
kpv
первое, что бросается в глаза
UTXIFGx, indicates that data has moved from
UxTXBUF to the TX shift register and UxTXBUF is ready for new data. It does
not indicate RX/TX completion.
соответственно последний байт практически не передается до конца
kpv
при таком варианте, по опросу, попробуй использовать TXEPT
UxTXBUF and TX shift register are empty
rezident
У меня такая процедура инициализации SPI.

Код
void _init_spi0(void)
{ IE1 &=~ (URXIE0 + UTXIE0);                      // запретить прерывания для SPI0
 _DIS_SPI0;                                      // запретить функции выводов SPI0
 _RESET_FLASH_CS;                                // сбросить активн.сост. CS DataFlash
 _RESET_RTC_CS;                               // сбросить активн.сост. CS RTC
 _RESET_CNTR_CS;                              // сбросить активн.сост. CS CNTR
 U0CTL = SWRST;                                  // уст.бит прогр. сброса модуля UART0
 U0CTL |= CHAR+SYNC+MM;                          // уст.режим UART0:8бит,SPI,ведущий,3-х провод.
 U0TCTL = CKPL+SSEL0+SSEL1+STC;             // Mode3, U0CLK=SMCLK, 3-ware
 U0BR1 = 0x00;                           // уст.старший байт предделителя BITCLK
 U0BR0 = 0x07;                                   // уст.младший байт предделителя BITCLK
 U0MCTL = 0;                                     // установка регистра модуляции
 ME1 |= USPIE0;                                  // разрешаем работу модуля SPI0
 U0CTL &=~ SWRST;                                // очистим бит программного сброса
 _EN_SPI0_3;                                     // разрешим функции pin 3-пров. SPI
 spi0.bufSize = 0;                               // установим нулевой размер буфера
 spi0.cntr = 0;                                  // сбросим счетчик байт буфера SPI0
 spi0.req = 0;                                   // сбросим регистр запросов к SPI0
 spi0.status = 0;                                // сбросим статус готовности SPI0
 spi0.num = 0;                                   // инициализация номера канала SPI0
 IE1 |= URXIE0+UTXIE0;                           // разрешить прерывания для UART0
}


Правда хочу уточнить, что у меня три устройства подключены к SPI, с равным приоритетом доступа. И с SPI я работаю по прерываниям.
O.L.
Грамотная инициализация, спасибо. Сейчас буду корректоровать свою.
Я в начале то же попробовал поиграть значениями в регистрах битрейт делителя, но flash работает только при установленных значениях
U1BR0 = 0x02;
U1BR1 = 0x00;

У меня кварц 7 372 800, но при U1BR1 = 0x00, а U1BR0 = 0x03, U1BR0 = 0x04 и т.д. регистр статуса микросхемы просто не читается.

Я вобщем то же хочу работать по прерываниям, но с "налету" не получилось, вот и начал разбираться детально. Тем более, что под HiTech-ем все так и работало.
O.L.
Цитата(kpv @ Jun 10 2005, 16:05)
при таком варианте, по опросу, попробуй использовать TXEPT
UxTXBUF and TX shift register are empty
*


Слабоват я пока в знании матчасти,
а в том, что вы написали, определенно есть смысл. Переписал все, erasing теперь работает, но в буфер ни в первый, ни во второй данные записываться перестали ... В общем дело двинулось, и это уже неплохо.
kpv
Цитата(O.L. @ Jun 10 2005, 13:00)
Слабоват я пока в знании матчасти

на русском почитайте - лучше, может быть, усвоится www.gaw.ru у меня на сайте старенький перевод лежит.

Цитата(O.L. @ Jun 10 2005, 13:00)
но в буфер ни в первый, ни во второй данные записываться перестали

код в студию, ассемблерный не надоть...
kpv
Цитата(O.L. @ Jun 10 2005, 12:53)
У меня кварц 7 372 800, но при U1BR1 = 0x00, а U1BR0 = 0x03, U1BR0 = 0x04 и т.д. регистр статуса микросхемы просто не читается.

всё сходится - spi работает на большой скорости и пока, по опросу, бит освобождения UxTXBUF проверяется, есть большая вероятность, что за это время и передача закончится, в случае низких скоростей, получается так, что не успевает на 100%
O.L.
Цитата(kpv @ Jun 10 2005, 17:06)
Цитата(O.L. @ Jun 10 2005, 13:00)
Слабоват я пока в знании матчасти

на русском почитайте - лучше, может быть, усвоится www.gaw.ru у меня на сайте старенький перевод лежит.

Цитата(O.L. @ Jun 10 2005, 13:00)
но в буфер ни в первый, ни во второй данные записываться перестали

код в студию, ассемблерный не надоть...
*



да совственно все без затей
по Serial получаем порцию данных 512+служебка засовываем все это в буфер DataFlash
Код
//    - write max page size 528byte to buffer DataFlash -
void write_to_buffer (unsigned char * sprt, unsigned char a_buff)
{
unsigned int buffer_cnt = 0;
    RLedOn;            // Led red anabled
    _DINT();
    while(!(P5IN & DF_RDY_BUSY));      // waite blok cleared
    P5OUT &= ~DF_CHIP_SEL;        // enabled DataFlash
    if (a_buff == BUFFER_1)        // if active Buffer1
 TXBUF1 = BUFFER_1_WRITE;
    else
 TXBUF1 = BUFFER_2_WRITE;
    while ((IFG2&UTXIFG1)!=UTXIFG1);
    TXBUF1 = 0x00;          // don't care 8 bits
    while ((IFG2&UTXIFG1)!=UTXIFG1);  // USART1 TX buffer empty?
    TXBUF1 = (char)(buffer_cnt>>8);      // first two byte buffer addr
    while ((IFG2&UTXIFG1)!=UTXIFG1);  // USART1 TX buffer empty?
    TXBUF1 = (char)buffer_cnt;    // buffer addr(max. 2^8 = 256 pages)
    while ((U1TCTL&TXEPT)!= TXEPT);      // USART1 TX buffer is empty?
    
    while(++buffer_cnt < (MAX_LEN+1))
    {
 TXBUF1 = *sprt++;
 while ((U1TCTL&TXEPT)!= TXEPT);  // USART1 TX buffer is empty?
    }
    P5OUT |= DF_CHIP_SEL;        // disabled DataFlash
    _EINT();
}
kpv
а как, собственно, определяется, что запись не прошла?
лишний текст убирай (мой или на то, что отвечаешь)
kpv
все, как было, можно было и оставить, только перед самым концом, когда #cs поднимаешь, добавить это
Код
while ((U1TCTL&TXEPT)!= TXEPT);

а лучше, конечно, работать через прерывание smile.gif
O.L.
Всяко по прерываниям лучше, я ж не спорю. Доберусь и до них, с буферами только разберусь smile.gif.
Но похоже, где то в программе я сам с переключениями буферов лажанулся. Запись в память через буфер работает, мне его очисти потом не удается.
Смысл DataFlas-ки в проекте такой. Нулевая страница для бэкапа, на экстренный случай. Последняя - примитивная файловая таблица. А все остальное пространство под хранение нескольких файлов. Какие то записываются один раз, какие то динамические. Вобщем флаги, пнризнаки, семафорчики ...
сейчас чайку попью и алгоритм из разрухи начну восстанавливать. Часиков шесть у меня еще есть smile.gif
Спасибо за помощь.
rezident
Я на прерывания посадил простой транспортный протокольчик. Структура spi0 имеет регистр статуса, регистр запросов, счетчик байт, переменную размера буфера, указатель на элемент буфера и номер канала. В прерываниях UARTx тупой обмен по SPI: байт из буфера передал - байт принял, положил в буфер, инкремент счетчика/указателя. И так до окончания буфера. А сам буфер готовит и обрабатывает программа более высокого уровня.
//Nikson
Поднимаю старую тему.

Есть F149 и две SPI-DataFlash - AT25F2048 и AT45DB161B. Инициализацию SPI (UART1) сделал на основе примеров из этой темы. Никакой связи с памятью наладить не удалось - выяснилось что на выводе контроллера P5.3 нет тактового сигнала UCLK. Вместо него или высокий уровень если установлен бит CKPL, или низкий если бит не установлен (по крайней мере вывод рабочий). Почему так - понять не могу.

Из программы удалил всё, что не касается SPI. Осталось вот что:
Код
int main()
{

  WDTCTL = WDTPW + WDTHOLD;
  IE1   |= OFIE + WDTIE;
  IFG1  |= OFIFG;
  
  __enable_interrupt();
  
  AT25SEL &= ~AT25LN;
  AT25DIR |= AT25LN;
  AT25CS_HI;
  
  AT45SEL &= ~AT45LN;
  AT45DIR |=  AT45LN;
  AT45CS_HI;
  
   IE2 &= ~(UTXIE1 + URXIE1);
   U1CTL = SWRST;
   U1CTL |= CHAR + SYNC + MM;
   U1TCTL = CKPL + SSEL1 + STC;
   U1BR1  = 0x00;
   U1BR0  = 0x04;
   U1MCTL = 0x00;
   ME2 |= USPIE1;
   U1CTL &= ~SWRST;
   //IE2 |= UTXIE1 + URXIE1;

   P5SEL |= 0x0E;
   P5DIR |= 0x0A;

   P1DIR = 0x10; //проверка наличия SMCLK
   P1SEL = 0x10;  


  while(1)
  {

  }

  return 0;
}

и тактирование (кварц 7,32 МГц и 32КГц)
Код
#pragma vector = NMI_VECTOR
__interrupt void OSCfault_ISR(void)
{
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
BCSCTL1 = DIVA_0 + RSEL2 + RSEL1 + RSEL0;
DCOCTL = DCO1 + DCO2;
while ((IFG1 & OFIFG) != 0) IFG1 &=~OFIFG;
BCSCTL2 = SELM_2 + DIVM_0 + DIVS_0 + SELS;
}


На ноге 16 SMCLK есть. Пробовал разные варианты U1BR1 и U1BR0, пробовал тактирование от ACLK - результат тот же.

Конфигурация выводов после выполнения программы:
P5SEL=0b00001110
P5DIR=0b00011011
P5OUT=0b00010001
(т.е. вывод 5.3 - периферийный модуль, на вывод, обе памяти в состоянии сброса)

вроде бы всё правильно.... и не работает. нужен свежий взгляд.

Подскажите в каком направлении копать, пожалуйста. (может ли дело быть в схемотехнике? может, какая обвязка нужна - у меня всё соединено напрямую).
rezident
//Nikson, два момента.
1. Вы бы не поленились еще хидер с дефайнами к исходнику приложить. А то как можно найти чужую ошибку, когда такой блок видишь?
Цитата
AT25SEL &= ~AT25LN;
AT25DIR |= AT25LN;
AT25CS_HI;

AT45SEL &= ~AT45LN;
AT45DIR |= AT45LN;
AT45CS_HI;

2. SPI это синхронный интерфейс для обмена данными. Чтобы что-то принять, нужно что-то передать. Где у вас в исходнике команда записи в UxTXBUF? Или вы предполагаете, что UCLK для SPI сам по себе постоянно генерится?
В общем RTFM.

P.S. ИМХО не совсем хорошо залезать в чужую тему со своими проблемами. Заведите свою собственную. Так более корректно будет.
//Nikson
rezident,
Да, точно. Эти 2 куска управляют только сигналами ChipSelect для двух микросхем памяти. На SPI влияния не оказывают, поэтому из поля зрения упустил.

Что касается UCLK и U1TXBUF... У меня-то именно передача и не работала. Поиск неисправности в первую очередь начал с проверки тактового сигнала. Обнаружилось, что его нет - вот я и бросился активно его искать, максимально урезав код, убрал всё что хоть как-то могло повлиять (в том числе и запись данных в буфер передатчика)- до этого момента был уверен, что он должен генерироваться постоянно пока включён модуль, независимо от состояния приёма/передачи в данный момент. Ну не знаю, почему я это так придумал sad.gif ....К сожалению, теперь выходит что не UCLK дело и надо рыть глубже. По крайней мере не буду топтаться на одном месте. Спасибо.

ЗЫ. Хорошо, замечание по поводу тем принято. Приношу свои извинения.
Просто иногда на форумах проповедуется идеология "все схожие вопросы в одной теме". Сделано для того, чтобы человек при решении проблемы поиском наткнулся на одну тему, прочитал её от начала до конца и разобрался. А не рылся в залежах тем-близнецов. ИМХО какая-то логика в этом есть, но в чужой монастырь со своим уставом не ходят smile.gif
rezident
Цитата(//Nikson @ Apr 12 2006, 03:12) *
ИМХО какая-то логика в этом есть, но в чужой монастырь со своим уставом не ходят smile.gif [/i]

Я не указывал вам, а лишь высказал свое мнение. Не я местный "устав" составлял, но я ему подчиняюсь. "Бурундук - птичка" что тут поделаешь? smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.