|
LPC2378: не работает SPI |
|
|
|
Oct 13 2008, 12:51
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Не поможет ли кто прояснить причину таких вот граблей. Используются ноги: 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 - молчание. Что здесь не так?
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
 |
Ответов
(1 - 11)
|
Oct 13 2008, 13:05
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(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;
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 14 2008, 10:42
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615

|
я тоже только что фунции для 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 ?
|
|
|
|
|
Oct 15 2008, 06:41
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(DimaM @ Oct 14 2008, 14:42)  Код FIO0CLR |= (1<<CS_FPGA); Странная конструкция. Может вместо"|=" использовать просто "="? И в других аналогичных случаях тоже...
|
|
|
|
|
Oct 15 2008, 09:38
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615

|
Цитата(Qwertty @ Oct 15 2008, 10:41)  Странная конструкция. Может вместо"|=" использовать просто "="? И в других аналогичных случаях тоже... конечно, это я ерунду написал, потому что с ARM недавно работаю. Но SPI и SSP в этих примерах рабочии. но еще я до сих пор не могу понять сколько время на выполнение команды считать.
Сообщение отредактировал DimaM - Oct 15 2008, 09:39
|
|
|
|
|
Oct 16 2008, 06:34
|
Участник

Группа: Новичок
Сообщений: 57
Регистрация: 7-11-06
Пользователь №: 22 054

|
Цитата(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 не использовал.
|
|
|
|
|
Oct 16 2008, 07:33
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615

|
Цитата(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 мкс. Мне кажется это недостаточно быстро.
|
|
|
|
|
Oct 16 2008, 09:41
|
Участник

Группа: Новичок
Сообщений: 57
Регистрация: 7-11-06
Пользователь №: 22 054

|
Цитата(DimaM @ Oct 16 2008, 11:33)  то есть ассемблерных команд не много, а исполняется 3,55 мкс, а сама передача 4 байт занимает 2 мкс. Мне кажется это недостаточно быстро. Чем и как измеряете время? Осциллографом по CS-ноге? А какую частоту клоков показывает осцилл (период)? Может проц/интерфейс не на той частоте сконфигурированы?
|
|
|
|
|
Oct 16 2008, 11:10
|
Частый гость
 
Группа: Участник
Сообщений: 103
Регистрация: 17-12-06
Из: село
Пользователь №: 23 615

|
Цитата(MikePic @ Oct 16 2008, 13:41)  Чем и как измеряете время? Осциллографом по CS-ноге? А какую частоту клоков показывает осцилл (период)? Может проц/интерфейс не на той частоте сконфигурированы? время измерял осцилографом на ноге CS. Частоту SPI тоже. Частота процессора правильная. А посмотрел инициализацию и нашел что у меня MAM не был включен. Сейчас все нормально, 2 мкс.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|