Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2378: не работает SPI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
vet
Не поможет ли кто прояснить причину таких вот граблей. Используются ноги: P1.20(SCK0), P1.21(SSEL0, управляется программно), P1.23(MISO0), P1.24(MOSI0). Посылаю в SPI0 байты данных:
Код
#define BIT(n) (1UL<<(n))

void SpiInitHW() {
  //PIO
  PINSEL3_bit.P1_20   = 3; //SCK0
  FIO1CLR             = BIT(20); //low
  FIO1DIR_bit.P1_20   = 1; //output
  PINMODE3_bit.P1_20  = 2; //no pull-up

  PINSEL3_bit.P1_21   = 0; //PIO
  FIO1SET             = BIT(21); //high
  FIO1DIR_bit.P1_21   = 1; //output
  PINMODE3_bit.P1_21  = 2; //no pull-up

  PINSEL3_bit.P1_23   = 3; //MISO0
  FIO1DIR_bit.P1_23   = 0; //input
  PINMODE3_bit.P1_23  = 0; //pull-up (вход выведен на разъём)

  PINSEL3_bit.P1_24   = 3; //MOSI0
  FIO1CLR             = BIT(24); //low
  FIO1DIR_bit.P1_24   = 1; //output
  PINMODE3_bit.P1_24  = 2; //no pull-up

  //SPI
  PCLKSEL0_bit.PCLK_SPI = 1;
  S0SPCCR = 0x80;
  S0SPCR = BIT(5)/*MSTR*/;
}

void SpiSelect()   {FIO1CLR = BIT(21);}
void SpiDeselect() {FIO1SET = BIT(21);}

INT8U SpiTransfer(INT8U data) {
  S0SPDR = data;
  while (!S0SPSR_bit.SPIF);
  return S0SPDR;
}

//.................

  for (;;) {
    WAIT(signalSend); //ждем сигнала на передачу байта
    SpiSelect();
    SpiTransfer(mSend);
    SpiDeselect();
  }


SSEL держит низкий уровень в течение байтового интервала, как задумано; на SCK и MOSI - молчание.
Что здесь не так?
zltigo
Цитата(vet @ Oct 13 2008, 14:51) *
Что здесь не так?

Не читал, но... - Power, тактировка, выборка...
Для сравнения подобное:
Код
    PCONP = (PCONP & (~PCONP_RESERV))|PCONP_PCSSP1; // Turn On EMC SSP1

    // Configure Pin Connect Block
    PINSEL0_bit.P0_7 = 0x2;           // SCK1
    PINSEL0_bit.P0_8 = 0x2;         // MISO1
    PINSEL0_bit.P0_9 = 0x2;         // MOSI1
    PINSEL0_bit.P_AT45_SSEL = 0x0;  // SSEL1 - Software Control


       FIO0SET =  (P0B_AT45_SSEL|P0B_AT45_RES|P0B_AT45_WP);     // Set Hi (Disabled)
      FIO0DIR |= (P0B_AT45_SSEL|P0B_AT45_RES|P0B_AT45_WP);    // Set ports to output

    // Warning! PClk = CClk  or 1/2 or 1/4
    SSP1CPSR = 2;        // Prescaler/2 = maximum speed
    SSP1CR0 = SSPCR0_DSS(8)|SSPCR0_SCR(1);
      
    for( int i = 0; i < SSP_FIFOSIZE; i++ )
        SSP1DR;            // Clear the RxFIFO

    // Device Enabled and selected as master
    SSP1CR1 = SSPCR1_SSE;
DimaM
я тоже только что фунции для spi писал.
вот мои кусочки которые работают

инициализация для LPC2368
Код
    PINSEL0 |= 0xC00A8000;        // CLK; MOSI1, MISO1, CLK1
    PINSEL1 |= 0x0000003C;        // MISO, MOSI;
    FIO0DIR |= (1<<CS_FPGA);        // CS_FPGA
    FIO0SET |= (1<<CS_FPGA);        // CS_FPGA
    FIO0DIR |= (1<<CS_FLASH1);        // CS_FLASH1
    FIO0SET |= (1<<CS_FLASH1);        // CS_FLASH1
    S0SPCCR = 8;    // max freq clock = 6MHz
    S0SPCR = SPI0_MSTR;
    SSP1CR0 = 0x00000007;    // max freq, clk- low defalt, second edge, spi, 8bit  
    SSP1CR1 = 0x00000002;    // SSP Enable, master
    SSP1CPSR = 4;            // max freq

посылка значений
Код
    unsigned int i; unsigned int b;
    FIO0CLR |= (1<<CS_FPGA);
    S0SPDR = adr;
    while ( !(S0SPSR & SPIF) );
    i = S0SPDR;        // Flush the RxFIFO
    S0SPDR = data;
    while ( !(S0SPSR & SPIF) );
    b = (data >> 8);
    S0SPDR = b;
    while ( !(S0SPSR & SPIF) );
    FIO0SET |= (1<<CS_FPGA);
    return i;

или
Код
void Flash1_ReadType(void)
{
    volatile unsigned int i;
    FIO0CLR |= (1<<CS_FLASH1);
    SSP1DR = 0x9F;
    SSP1DR = 0;
    SSP1DR = 0;
    SSP1DR = 0;
//    while ( !(SSP1SR & SSPSR_BSY) );   // SSPSR_TFE SSPSR_RNE
    i = SSP1DR;
    Flash1_ManID = SSP1DR;
    Flash1_MemType = SSP1DR;
    Flash1_MemSize = SSP1DR;
    FIO0SET |= (1<<CS_FLASH1);
}

но что я не понимаю - почему последняя функция выполняется 3.6 us? я вроде и частоту процессора настроил 72 МГц и spi 18МГц.

за сколько должна выполнятся команда MOV ?
wangan
Не использовал но есть код который делал товарищ на работе но лучше глянуть примеры и попробуйте частоту поменьше поставить 60МГц и меньше. Чето помню с этим у него были грабли завязаны на SPI.
У иара здесь:
c:\Program Files\IAR Systems\Embedded Workbench 5.20 Evaluation\ARM\examples\NXP\LPC23xx\IAR-LPC-2378-SK\simple\SSP\
Qwertty
Цитата(DimaM @ Oct 14 2008, 14:42) *
Код
    FIO0CLR |= (1<<CS_FPGA);

Странная конструкция. Может вместо"|=" использовать просто "="? И в других аналогичных случаях тоже...
DimaM
Цитата(Qwertty @ Oct 15 2008, 10:41) *
Странная конструкция. Может вместо"|=" использовать просто "="? И в других аналогичных случаях тоже...

конечно, это я ерунду написал, потому что с ARM недавно работаю. Но SPI и SSP в этих примерах рабочии.
но еще я до сих пор не могу понять сколько время на выполнение команды считать.
vet
Выводы по теме: пин SSEL предназначен для использования только в slave режиме SPI. Любые манипуляции с ним в master режиме - программные ли, аппаратные ли - приведут к переходу SPI в slave режим. Если нужен мастер - разводим вход выбора ведомого уст-ва на другой вывод LPC.
Поправьте, если я неверно понял.
zltigo
Цитата(vet @ Oct 15 2008, 11:56) *
Поправьте, если я неверно понял.

Абсолютно. В относительно свежих чипах все в порядке управляем и аппаратно, и софтово. В старых - в старых да, был документированный баг по не использоваемю SSEL.
MikePic
Цитата(DimaM @ Oct 14 2008, 14:42) *
но что я не понимаю - почему последняя функция выполняется 3.6 us? я вроде и частоту процессора настроил 72 МГц и spi 18МГц.


Всё описанное ниже справедливо для IAR-а.

Перед процедурой лучше поставить оптимизацию по скорости:
Код
#pragma optimize= s 9
__arm

Причина, возможно, ещё в переменных Flash1_. Где они расположены? Во внешней памяти? Даже если во внутренней, всё-равно простым mov-ом там не обойдётся. Смотрите листинг asm-овский. Попробуйте для эксперимента внутри процедуры создать временную переменную (массив) и читать в него, а потом замерить скорость. Если SPI 8-битный, то в этом случае на приём/передачу уйдёт ~1.3мкс, всё остальное - обработка и дёрганье FIO. Мне на SSI LPC2214/01 удалось получить производительность 2,27мкс/слово (17бит при 14,7456МГц интерфейс, *4 - частота проца), при этом была куча проверок, условий, поддержка протокола, принимаемые и передаваемые данные размещались в эластичном FIFO, который был во внешней SRAM, FIFO LPC не использовал.
DimaM
Цитата(MikePic @ Oct 16 2008, 10:34) *
Причина, возможно, ещё в переменных Flash1_. Где они расположены? Во внешней памяти? Даже если во внутренней, всё-равно простым mov-ом там не обойдётся. Смотрите листинг asm-овский. Попробуйте для эксперимента внутри процедуры создать временную переменную (массив) и читать в него, а потом замерить скорость. Если SPI 8-битный, то в этом случае на приём/передачу уйдёт ~1.3мкс, всё остальное - обработка и дёрганье FIO. Мне на SSI LPC2214/01 удалось получить производительность 2,27мкс/слово (17бит при 14,7456МГц интерфейс, *4 - частота проца), при этом была куча проверок, условий, поддержка протокола, принимаемые и передаваемые данные размещались в эластичном FIFO, который был во внешней SRAM, FIFO LPC не использовал.

У меня keil, который должен оптимизировать не хуже. Переменные в оперативной памяти, SPI 8-бит, частота процессора, как мне кажется 72 МГц, SPI 18 МГц.
Код
    volatile unsigned int i;
    FIO0CLR = (1<<CS_FLASH1);
    SSP1DR = 0x9F;
    SSP1DR = 0;
    SSP1DR = 0;
    SSP1DR = 0;
    while ( !(SSP1SR & SSPSR_BSY) );
    i = SSP1DR;
    Flash1_ManID = SSP1DR;
    Flash1_MemType = SSP1DR;
    Flash1_MemSize = SSP1DR;
    FIO0SET = (1<<CS_FLASH1);

ассемблер получится следующий
Код
    16:         FIO0CLR = (1<<CS_FLASH1);
0x00000F78  E3A03101  MOV       R3,#__RTA_fpDbgIn(0x40000000)
0x00000F7C  E3A02040  MOV       R2,#0x00000040
0x00000F80  E2433901  SUB       R3,R3,#0x00004000
0x00000F84  E583201C  STR       R2,[R3,#0x001C]
    17:         SSP1DR = 0x9F;
0x00000F88  E3A00803  MOV       R0,#0x00030000
0x00000F8C  E3A0109F  MOV       R1,#0x0000009F
0x00000F90  E280020E  ADD       R0,R0,#WDMOD(0xE0000000)
0x00000F94  E5801008  STR       R1,[R0,#0x0008]
    18:         SSP1DR = 0;  
0x00000F98  E3A01000  MOV       R1,#Flash1_DevID(0x00000000)
0x00000F9C  E5801008  STR       R1,[R0,#0x0008]
    19:         SSP1DR = 0;  
0x00000FA0  E5801008  STR       R1,[R0,#0x0008]
    20:         SSP1DR = 0;  
0x00000FA4  E5801008  STR       R1,[R0,#0x0008]
    21:         while ( !(SSP1SR & SSPSR_BSY) );
0x00000FA8  E590100C  LDR       R1,[R0,#0x000C]
0x00000FAC  E3110010  TST       R1,#0x00000010
0x00000FB0  0AFFFFFC  BEQ       0x00000FA8
    22:         i = SSP1DR;
0x00000FB4  E5901008  LDR       R1,[R0,#0x0008]
    23:         Flash1_ManID = SSP1DR;
0x00000FB8  E590C008  LDR       R12,[R0,#0x0008]
0x00000FBC  E59F1384  LDR       R1,[PC,#0x0384]
    24:         Flash1_MemType = SSP1DR;
0x00000FC0  E581C000  STR       R12,[R1]
0x00000FC4  E590C008  LDR       R12,[R0,#0x0008]
    25:         Flash1_MemSize = SSP1DR;
0x00000FC8  E581C004  STR       R12,[R1,#0x0004]
0x00000FCC  E5900008  LDR       R0,[R0,#0x0008]
    26:         FIO0SET = (1<<CS_FLASH1);
0x00000FD0  E5810008  STR       R0,[R1,#0x0008]
0x00000FD4  E5832018  STR       R2,[R3,#0x0018]

то есть ассемблерных команд не много, а исполняется 3,55 мкс, а сама передача 4 байт занимает 2 мкс. Мне кажется это недостаточно быстро.
MikePic
Цитата(DimaM @ Oct 16 2008, 11:33) *
то есть ассемблерных команд не много, а исполняется 3,55 мкс, а сама передача 4 байт занимает 2 мкс. Мне кажется это недостаточно быстро.

Чем и как измеряете время? Осциллографом по CS-ноге? А какую частоту клоков показывает осцилл (период)? Может проц/интерфейс не на той частоте сконфигурированы?
DimaM
Цитата(MikePic @ Oct 16 2008, 13:41) *
Чем и как измеряете время? Осциллографом по CS-ноге? А какую частоту клоков показывает осцилл (период)? Может проц/интерфейс не на той частоте сконфигурированы?

время измерял осцилографом на ноге CS. Частоту SPI тоже. Частота процессора правильная. А посмотрел инициализацию и нашел что у меня MAM не был включен. Сейчас все нормально, 2 мкс.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.