реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> LPC1111, тормоза SPI
esaulenka
сообщение Dec 1 2011, 15:50
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 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;
}


Сталкивался кто-нибудь?..


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 1 2011, 16:04
Сообщение #2


Йа моск ;)
******

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



Заглянуть в продуцируемый компилятором код не позволяет религия?


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 1 2011, 16:15
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 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


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 1 2011, 16:47
Сообщение #4


Йа моск ;)
******

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



QUOTE
Надо было сразу написать, что там ничего интересного не найдено.


Поганенько, конечно. uint8_t замените на uint_fast8_t да заинлайньте SendByteSPI. Но что-то мне кажется, что полста тактов оверхеда там не наберется. Чуть позже гляну в ман на проца, может чего подскажу еще.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 2 2011, 08:36
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 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 состояния.


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 2 2011, 09:31
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Dron_Gus @ Dec 2 2011, 11:36) *
я бы заменил
А я бы проверял TNF и эту проверку на готовность к передаче поставил перед записью в DR.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 2 2011, 10:45
Сообщение #7


Профессионал
*****

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



Цитата(Сергей Борщ @ Dec 2 2011, 13:31) *
А я бы проверял TNF и эту проверку на готовность к передаче поставил перед записью в DR.

Если слать побайтно и ждать приема ответного байта, то можно обойтимь одной проверкой.


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 2 2011, 13:45
Сообщение #8


Профессионал
*****

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



Уже второй день сижу, экспериментирую... Ну да ладно, пятница sm.gif

Закономерности выявить не удалось.
При частоте ядра 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, всё перепутается...


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 2 2011, 14:03
Сообщение #9


Йа моск ;)
******

Группа: Модераторы
Сообщений: 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;
}


Типа такого.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 2 2011, 16:28
Сообщение #10


Профессионал
*****

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



Не взлетит sad.gif
Запихать в 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;
}


При попытке свернуть чтение в цикл получаем неплохие тормоза...


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 2 2011, 16:46
Сообщение #11


Йа моск ;)
******

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



QUOTE
При попытке свернуть чтение в цикл получаем неплохие тормоза...


А зачем в цикл сворачивать?


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 2 2011, 17:18
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 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 миллисекунд. Всё остальное время обмен небольшой, пользователь потерпит.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 10:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.03368 секунд с 7
ELECTRONIX ©2004-2016