|
|
  |
LPC1111, тормоза SPI |
|
|
|
Dec 1 2011, 15:50
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Копаюсь с модулем SSP0 на контроллере LPC1111. Частота камня - 48 МГц, частота SPI - 12 МГц, задержки между байтами 1,17 мкс.
Частота камня - 36 МГц, частота SPI - 18 МГц, задержки между байтами 1,23 мкс.
код простейший, никаких прерываний: Код uint8_t SendByteSPI( uint8_t data) { LPC_SSP0->DR = data; while( LPC_SSP0->SR & BIT(4) ) // SPI0 busy ; return LPC_SSP0->DR; }
#define SPI_WriteByte(data) SendByteSPI(data) #define SPI_ReadByte() SendByteSPI(0x00)
uint8_t Mem_ReadByte( uint32_t aunMemAddr ) { uint8_t ucByteReadMem; ACTIVE_SPI(); SPI_WriteByte( 0x03 ); // Read Data Bytes SPI_WriteByte( (uint8_t)(aunMemAddr >> 16 ) ); SPI_WriteByte( (uint8_t)(aunMemAddr >> 8 ) ); SPI_WriteByte( (uint8_t)(aunMemAddr ) ); ucByteReadMem = SPI_ReadByte(); DEACTIVE_SPI(); return ucByteReadMem; } Сталкивался кто-нибудь?..
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Dec 1 2011, 16:15
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Почему же, заглядывал. Надо было сразу написать, что там ничего интересного не найдено. Код SendByteSPI PROC ;;;47 uint8_t SendByteSPI( uint8_t data) 000000 4903 LDR r1,|L2.16| ;;;48 { ;;;49 LPC_SSP0->DR = data; 000002 6088 STR r0,[r1,#8] |L2.4| ;;;52 while( LPC_SSP0->SR & BIT(4) ) 000004 68c8 LDR r0,[r1,#0xc] 000006 06c0 LSLS r0,r0,#27 000008 d4fc BMI |L2.4| ;;;53 ; ;;;59 return LPC_SSP0->DR; 00000a 6888 LDR r0,[r1,#8] 00000c b2c0 UXTB r0,r0 ;;;60 } 00000e 4770 BX lr ENDP |L2.16| DCD 0x40040000 Код Mem_ReadByte PROC ;;;171 // ;;;172 uint8_t Mem_ReadByte( uint32_t aunMemAddr ) 000000 b5f8 PUSH {r3-r7,lr} ;;;173 { ;;;174 uint8_t ucByteReadMem; ;;;175 ;;;176 ACTIVE_SPI(); 000002 2405 MOVS r4,#5 000004 4e0d LDR r6,|L6.60| 000006 0724 LSLS r4,r4,#28 000008 4605 MOV r5,r0 ;173 00000a 6126 STR r6,[r4,#0x10] 00000c 6126 STR r6,[r4,#0x10] 00000e 2700 MOVS r7,#0 000010 6127 STR r7,[r4,#0x10] ;;;177 ;;;178 SPI_WriteByte( 0x03 ); // Read Data Bytes 000012 2003 MOVS r0,#3 000014 f7fffffe BL SendByteSPI ;;;179 SPI_WriteByte( (uint8_t)(aunMemAddr >> 16 ) ); 000018 0228 LSLS r0,r5,#8 00001a 0e00 LSRS r0,r0,#24 00001c f7fffffe BL SendByteSPI ;;;180 SPI_WriteByte( (uint8_t)(aunMemAddr >> 8 ) ); 000020 0428 LSLS r0,r5,#16 000022 0e00 LSRS r0,r0,#24 000024 f7fffffe BL SendByteSPI ;;;181 SPI_WriteByte( (uint8_t)(aunMemAddr ) ); 000028 b2e8 UXTB r0,r5 00002a f7fffffe BL SendByteSPI ;;;182 ucByteReadMem = SPI_ReadByte(); 00002e 2000 MOVS r0,#0 000030 f7fffffe BL SendByteSPI ;;;183 ;;;184 DEACTIVE_SPI(); 000034 6127 STR r7,[r4,#0x10] 000036 6126 STR r6,[r4,#0x10] ;;;185 ;;;186 return ucByteReadMem; ;;;187 } 000038 bdf8 POP {r3-r7,pc} ;;;188 ENDP
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Dec 2 2011, 08:36
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Код while( LPC_SSP0->SR & BIT(4) ) // SPI0 busy я бы заменил на Код while( (LPC_SSP0->SR & BIT(2)) == 0 ) // SPI0 busy Т.е. ждал бы прихода байта, а не IDLE состояния.
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Dec 2 2011, 13:45
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Уже второй день сижу, экспериментирую... Ну да ладно, пятница  Закономерности выявить не удалось. При частоте ядра 48 и 36 МГц разница незначительная, а при снижении до 24 МГц задержка возрастает до 1,8 мкс. Цитата(Rst7 @ Dec 1 2011, 20:47)  uint8_t замените на uint_fast8_t да заинлайньте SendByteSPI. Сделал так, получил 0,9 мкс задержки. Цитата(Dron_Gus @ Dec 2 2011, 12:36)  Т.е. ждал бы прихода байта, а не IDLE состояния. И ещё одна десятая микросекунды в выигрыше. Почему, мне не ясно... При выкидывании проверки вообще получаем промежуток между клоками 80 наносекунд. Только, разумеется, ничего не работает ;-) Цитата(Сергей Борщ @ Dec 2 2011, 13:31)  А я бы проверял TNF и эту проверку на готовность к передаче поставил перед записью в DR. Идею не понял. А читаемые данные как достать? Там же FIFO, всё перепутается...
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Dec 2 2011, 14:03
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
QUOTE При выкидывании проверки вообще получаем промежуток между клоками 80 наносекунд. Только, разумеется, ничего не работает ;-) Ну и отлично. Пихаете 4 байта без проверок, и выгребаете все из RX, пока RNE=1 - последний байт будет Вашим. CODE uint_fast8_t Mem_ReadByte( uint_fast32_t aunMemAddr ) { uint8_fast8_t ucByteReadMem; ACTIVE_SPI(); LPC_SSP0->DR = 0x03; LPC_SSP0->DR = aunMemAddr >> 16; LPC_SSP0->DR = aunMemAddr >> 8; LPC_SSP0->DR = aunMemAddr; LPC_SSP0->DR = 0; //Это для выгребания последнего байта. while(LPC_SSP0->SR & (1<<2)) ucByteReadMem=LPC_SSP0->DR; DEACTIVE_SPI(); return ucByteReadMem; } Типа такого.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Dec 2 2011, 16:28
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Не взлетит  Запихать в FIFO 5 байт получается быстрее, чем он их передаёт. Соответственно, переходим к циклу выгребания, и возвращаем какой-то неверный байт. Но за идею спасибо, в итоге закончилось следующим: Код uint8_t Mem_ReadByte( uint32_t aunMemAddr ) { ACTIVE_SPI(); LPC_SSP0->DR = 0x03; LPC_SSP0->DR = aunMemAddr >> 16; LPC_SSP0->DR = aunMemAddr >> 8; LPC_SSP0->DR = aunMemAddr; LPC_SSP0->DR = 0; while (LPC_SSP0->SR & BIT(4)); DEACTIVE_SPI(); LPC_SSP0->DR; LPC_SSP0->DR; LPC_SSP0->DR; LPC_SSP0->DR; return LPC_SSP0->DR; } При попытке свернуть чтение в цикл получаем неплохие тормоза...
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Dec 2 2011, 17:18
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Неверно выразился. Сначала была комбинация из Код while (LPC_SSP0->SR & BIT(4)); while(LPC_SSP0->SR & (1<<2)) ucByteReadMem=LPC_SSP0->DR; А потом я второй цикл развернул, стало заметно быстрее. В итоге: было 7 мкс, стало 4,5. С одной стороны - неплохо. А с другой - я два дня страдал фигнёй, ускорив первичную инициализацию аж на 30 миллисекунд. Всё остальное время обмен небольшой, пользователь потерпит.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|