Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Скорость махания ногами lpc1343
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
alexey_z83
Здравствуйте,
начал осваивать кортексы, взял пример моргания светодиодом, заодно решил проверить максимальную скорость махания ногами, получилось, что при частоте 72мГц максимальная скорость коммутации ~ 0,5мГц.
Использовал стандартную функцию:

GPIO_SetValue(0, 7);
GPIO_ClearValue(0, 7);

из примера IARARM 5.50 для lpc1343 SystemTick.

Как я понял управление осуществляется через:

Код
typedef struct
{
  union {
    __IO uint32_t MASKED_ACCESS[4096];
    struct {
         uint32_t RESERVED0[4095];
    __IO uint32_t DATA;
    };
  };
       uint32_t RESERVED1[4096];
  __IO uint32_t DIR;
  __IO uint32_t IS;
  __IO uint32_t IBE;
  __IO uint32_t IEV;
  __IO uint32_t IE;
  __IO uint32_t RIS;
  __IO uint32_t MIS;
  __IO uint32_t IC;
} LPC_GPIO_TypeDef;

void GPIO_SetValue(uint8_t portNum, uint32_t bitValue)
{
    LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);

    if (pGPIO != NULL) {
        pGPIO->DATA |= (0x1<<bitValue);

    }
}

void GPIO_ClearValue(uint8_t portNum, uint32_t bitValue)
{
    LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);

    if (pGPIO != NULL) {
        pGPIO->DATA &= ~(0x1<<bitValue);
    }
}



что при выполнении вылилось в 53такта на смену состояния, что соответствует ~0,5мГц.

Собственно вопрос:
можно ли достичь большей скорости используя эти библиотеки и можно ли напрямую использовать регистр GPIOnDATA для управления состоянием вывода поскольку в хедере этих регистров не нашел.
codier
А не проще напрямую регистрами порта? С LPC13хх не работал, на LPC17xx делал так:

Код
#include "cmsis/lpc17xx.h"
#include "cmsis/system_LPC17xx.h"

int main(void)
{
    SystemInit();

    // 1 - output
    LPC_GPIO1->FIODIR = 1 << 27;

    while(1)
    {
        LPC_GPIO1->FIOSET = 1 << 27;
        for(volatile int i = 0; i < 1000000; i++);
        LPC_GPIO1->FIOCLR = 1 << 27;
        for(volatile int i = 0; i < 1000000; i++);
    }
}


На 100МHz проца 10MHz на ножках в таком режиме получить можно, вопрос только зачем? sm.gif

Всякие условыне операторы лучше не использовать как в приведённых выше функциях, т.к. могут быть накладные расходы с конвеером.
alexey_z83
Цитата
А не проще напрямую регистрами порта?


а разве это не он регистр GPIOnDATA?

Цитата
На 100МHz проца 10MHz на ножках в таком режиме получить можно, вопрос только зачем?


программный spi (нету у устройств своего cs, а у контроллера один spi)

P.S. вы с задержками не ошиблись?
alexey_z83
Спасибо, разобрался, вроде, 4 такта (~ 9мГц при 72мГц) на смену состояния получилось.

Скажите кто имел дело с lpc1343, это максимум для него?
GetSmart
скорее всего может ещё в 2 раза быстрее. только нужно всё оптимизировать и развернуть цикл.
alexey_z83
Спасибо за подсказку, GetSmart, оптимизация творит чудеса sm.gif .
Благодарю всех за ответы на глупые вопросы.
codier
Цитата(alexey_z83 @ Jan 16 2011, 12:59) *
P.S. вы с задержками не ошиблись?


Ясен пень что без циков :-))
HARMHARM
Цитата(alexey_z83 @ Jan 16 2011, 11:59) *
программный spi (нету у устройств своего cs, а у контроллера один spi)

А что значит у устройств нету своего CS?
Необязательно использовать CS от SSP, можно просто ножкой дергать. Запросто несколько устройств можно подключить, и быстрее будет работать чем софтварный spi.
alexey_z83
Цитата
А что значит у устройств нету своего CS?

то, что у устройств есть только входы clk и sdi, даже выхода sdo нет, потому и не могу повесить на одну линию.
HARMHARM
А не проще ли коммутировать sck на кристалле? У LPC1343 два вывода SCK, нога 22 и нога 29. Даже еще один есть, нога 31. Это для LQFP.
alexey_z83
Да вы правы, до 3 устройств можно подключить, я только начал разбираться поэтому не все тонкости знаю.
HARMHARM
Спрашивайте, посоветуем, тут все мирные sm.gif
esaulenka
Если исходный вопрос ещё актуален:
- регистр GPIOxDATA в стандартном заголовке теперь значится как GPIOx->DATA
- гораздо быстрее (и идеологически правильней, граблей меньше) работать через GPIOx->MASKED_ACCESS[y]. Измерений не проводил, но должно получиться ускорение в два раза.

PS универсальные хедеры - это всё-таки хорошо. IAR я давно не видел, но в кейле определения этих регистров точно такие же.
rezident
Цитата(alexey_z83 @ Jan 18 2011, 08:44) *
то, что у устройств есть только входы clk и sdi, даже выхода sdo нет, потому и не могу повесить на одну линию.
Так не бывает! Как же в вашем устройстве тогда фреймовая синхронизация осуществляется? По паузе в передаче?
alexey_z83
Цитата
Так не бывает! ...


Возьмем к примеру:

http://www.st.com/internet/com/TECHNICAL_R.../CD00149163.pdf стр.9

каким образом фрэймы отделяем?

Я конечно понемаю, что cs надежнее, но нет его и в результате импульсной помехи есть вероятность "перескочить через бит".
HARMHARM
Это не совсем SPI, а просто сдвиговый регистр. А вместо CS у вас входная защелка LH/DM1, только логика работы немного отличается.
alexey_z83
И опять вы правы, HARMHARM, хоть вход и не cs, но выполняет аналогичную функцию, а то, что не совсем spi так гдеж его найдешь настоящий sm.gif . В общем - Спасибо.
pofikus
так дрыгать ногами можно быстрее....


static __INLINE void GPIOSetValue( uint32_t portNum, uint32_t bitPosi, uint32_t bitVal )
{
LPC_GPIO[portNum]->MASKED_ACCESS[(1<<bitPosi)] = (bitVal<<bitPosi);
}
GetSmart
Бфстрее двух тактов на изменение пина не бывает.
alexey_z83
А у меня, вроде, за один такт получилось (хотя в реальной программе это мало пригодится), но только для pin8-pin11 порта, а для pin0-pin7 два такта (так и не понял почему компилятор так разложил?).

Максимальная оптимизация по скорости IAR 5.50

Код
          LPC_GPIO0->DATA = 0x800;
          LPC_GPIO0->DATA = 0;
          LPC_GPIO0->DATA = 0x800;
          LPC_GPIO0->DATA = 0;  
          LPC_GPIO0->DATA = 0x800;
          LPC_GPIO0->DATA = 0;
          LPC_GPIO0->DATA = 0x800;
          LPC_GPIO0->DATA = 0;  



        0x424: 0xf44f 0x6100  MOV.W     r1, #2048              ; 0x800
        0x428: 0x2200         MOVS      r2, #0
          LPC_GPIO0->DATA = 0x800;
??main_1:
        0x42a: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;
        0x42c: 0x6002         STR       r2, [r0]
          LPC_GPIO0->DATA = 0x800;
        0x42e: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;  
        0x430: 0x6002         STR       r2, [r0]
          LPC_GPIO0->DATA = 0x800;
        0x432: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;
        0x434: 0x6002         STR       r2, [r0]
          LPC_GPIO0->DATA = 0x800;
        0x436: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;          
        0x438: 0x6002         STR       r2, [r0]
        0x43a: 0xe7f6         B.N       ??main_1               ; 0x42a
        0x43c: 0x0000         MOVS      r0, r0
        0x43e: 0x0000         MOVS      r0, r0
??DataTable2:
        0x440: 0x10000458     DC32      SysTickCnt





          LPC_GPIO0->DATA = 0x80;
          LPC_GPIO0->DATA = 0;
          LPC_GPIO0->DATA = 0x80;
          LPC_GPIO0->DATA = 0;  
          LPC_GPIO0->DATA = 0x80;
          LPC_GPIO0->DATA = 0;
          LPC_GPIO0->DATA = 0x80;
          LPC_GPIO0->DATA = 0;



        0x422: 0x480c         LDR.N     r0, ??DataTable2_3 [0x454]; GPIO0DATA
          LPC_GPIO0->DATA = 0x80;
??main_1:
        0x424: 0x2180         MOVS      r1, #128               ; 0x80
        0x426: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;
        0x428: 0x2100         MOVS      r1, #0
        0x42a: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0x80;
        0x42c: 0x2180         MOVS      r1, #128               ; 0x80
        0x42e: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;  
        0x430: 0x2100         MOVS      r1, #0
        0x432: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0x80;
        0x434: 0x2180         MOVS      r1, #128               ; 0x80
        0x436: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;
        0x438: 0x2100         MOVS      r1, #0
        0x43a: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0x80;
        0x43c: 0x2180         MOVS      r1, #128               ; 0x80
        0x43e: 0x6001         STR       r1, [r0]
          LPC_GPIO0->DATA = 0;
zltigo
QUOTE (alexey_z83 @ Jan 19 2011, 21:09) *
А у меня, вроде, за один такт получилось

Вы еще путаете команды с тактами? Пора перестать.
alexey_z83
CYCLECOUNTER — в симуляторе разве не кол-во тактов показывает? Если так то команда STR (как и смена состояния вывода) выполняется за один такт.
zltigo
QUOTE (alexey_z83 @ Jan 19 2011, 21:57) *
CYCLECOUNTER — в симуляторе разве не кол-во тактов показывает?

sm.gif А не приходилось-ли Вам когда-нибудь слышать о скоростях работы памяти? Периферийных шинах? И waitstate? А полагаете-ли Вы, что Ваш игрушечный симулятор истребителя F16 похож на реальный F16?


alexey_z83
Как расценивать ваш ответ?
zltigo
QUOTE (alexey_z83 @ Jan 19 2011, 22:01) *
Как расценивать ваш ответ?

Как вопросы с которых надо начинать искать ответы на вопрос "почему не один такт".
alexey_z83
Хорошо, завтра посмотрю осциллографом, я так понял если частота будет 36mHz, т. е. тактовая(72)/2 тогда ...симулятор истребителя F16 похож на реальный F16 sm.gif .
GetSmart
Команда STR займёт как минимум 2 такта. Поэтому сааамый оптимизированный алгоритм ручного ногодрыга не заставит дрыгать лапкой выше 18 мгц при 72 мгц тактовой.
alexey_z83
Помогите с ответами на вопросы:

1). В документе DDI0337H_cortex_m3_r2p0_trm.pdf от ARM
напротив команды STR стоит два такта и ссылка на:

Neighboring load and store single instructions can pipeline their address and data phases.
This enables these instructions to complete in a single execution cycle.

Как я понял в некоторых случаях команда может быть выполнена за один такт?

2). В юзермануале в разделе Flash memory access говориться, что при частоте выше 40mHz требуется 2 такта на доступ.

От величины этой задержки будет зависеть время выполнения команды(в тактах)?, просто в ARM7 NXP есть модуль MAM который компенсировал такты ожидания читая 128 бит за раз, а сколько lpc13xx за раз с flash памяти читает не нашел.

Просто хотел разобраться сколько конкретная команда для конкретного контролера выполняется.
vallav
Цитата(alexey_z83 @ Jan 20 2011, 17:52) *
1). В документе DDI0337H_cortex_m3_r2p0_trm.pdf от ARM
напротив команды STR стоит два такта и ссылка на:

Neighboring load and store single instructions can pipeline their address and data phases.
This enables these instructions to complete in a single execution cycle.


А в DDIO337G ( это предыдущая версия ) чуть по другому:
b. Generally, load-store instructions take two cycles for the first access and one cycle for each additional access. Stores with
immediate offsets take one cycle.

Так что, увы, проверять надо.
И будет эта штука сильно процессрозависящей.
Kostia87
У меня получалось частоту переключения разогнать до 2Мгц на 72Мгц. используй этот код
.equ STACK_TOP, 0x10002000

.text
.global _start
.thumb
.syntax unified
_start:
.word STACK_TOP,start
.type start,function

.org 0x124
start:
ldr.w r0,=0x50008000 @ адресс GPIO0DIR
ldr.w r1,=0x00000000
ldr.w r2,=0xFFFFFFFFF
str.w r2,[r0] @ порт 0 все порты на выход
ldr.w r0,=0x50003FFC @ адресс GPIO0DATA
aaaa:
str.w r1,[r0] @ порт в 0
dsb.w @ синхронизация
str.w r2,[r0] @ порт в 1
dsb.w
bx aaaa

Весь код написан в thumb2 инструкциях для увеличения бысродействия. Инструкция синхронизации dsb нужна для того что бы значение успело записать в память, так как запись происходит не непосредственно в память а через буфер шины. Если ее не вставить на осцилографе вместо меандра будут палки.

Цитата(Kostia87 @ Mar 18 2011, 11:30) *
У меня получалось частоту переключения разогнать до 2Мгц на 72Мгц. используй этот код
.equ STACK_TOP, 0x10002000

.text
.global _start
.thumb
.syntax unified
_start:
.word STACK_TOP,start
.type start,function

.org 0x124
start:
ldr.w r0,=0x50008000 @ адресс GPIO0DIR
ldr.w r1,=0x00000000
ldr.w r2,=0xFFFFFFFFF
str.w r2,[r0] @ порт 0 все порты на выход
ldr.w r0,=0x50003FFC @ адресс GPIO0DATA
aaaa:
str.w r1,[r0] @ порт в 0
dsb.w @ синхронизация
str.w r2,[r0] @ порт в 1
dsb.w
b.w aaaa
Изменил код переход нужен b.w , а не bx



весь код с инициализацией ФАПЧ следующий.

.equ STACK_TOP, 0x10002000

.text
.global _start
.thumb
.syntax unified
_start:
.word STACK_TOP,start
.type start,function

.org 0x124
start:
bl SYS_TACT_INIT

ldr.w r0,=0x50008000 @ адресс GPIO0DIR
ldr.w r1,=0x00000000
ldr.w r2,=0xFFFFFFFFF
str.w r2,[r0] @ порт 0 все порты на выход
ldr.w r0,=0x50003FFC @ адресс GPIO0DATA
aaaa:
str.w r1,[r0] @ порт в 0
dsb.w @ синхронизация
str.w r2,[r0] @ порт в 1
dsb.w
b.w aaaa
SYS_TACT_INIT:
push {lr}
ldr.w r1,=0x00000001
ldr.w r2,=0x00000000

ldr.w r0,=PDRUNCFG
str.w r3,[r0]
bic.w r3,#0xA0
ldr.w r3,[r0]

ldr.w r0,=SYSPLLCLKSEL
str.w r1,[r0]
dsb
ldr.w r0,=SYSPLLUEN
str.w r2,[r0]
dsb
str.w r1,[r0]

bl SYS_PLL_72MHZ

ldr.w r0,=MAINCLKSEL
ldr.w r3,=0x00000003
str.w r3,[r0]
dsb
ldr.w r0,=MAINCLKUEN
str.w r2,[r0]
dsb
str.w r1,[r0]

ldr.w r0,=SYSAHBCLKCTRL
ldr.w r1,[r0]
ldr.w r2,=0x00001000
orr.w r1,r2
str.w r1,[r0]
dsb
pop {pc}

SYS_PLL_72MHZ:
push {r0-r2}
ldr.w r0,=SYSPLLCTRL
ldr.w r1,=0x00000005
str.w r1,[r0]
dsb
ldr.w r0,=SYSPLLSTAT
SYS_2:
ldr.w r1,[r0]
ldr.w r2,=0x00000001
ands.w r2,r1
bne.w SYS_2
pop {r0-r2}
bx lr


Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.