Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 – вопросы – проблемы - решения.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
AHTOXA
Цитата(demiurg_spb @ Apr 8 2011, 15:50) *
Т.е. так вполне сносно будет?

На так давно ReAl провёл целое исследование на эту тему. Я позволю себе процитировать фрагмент его письма:
Цитата
-------- CPL ------------------------------------------------------
---- через ODR ^=
521 0012 DA68 ldr r2, [r3, #12]
522 0014 82F00202 eor r2, r2, #2
523 0018 DA60 str r2, [r3, #12]
-- 8 байтов, 9 циклов, 125 ns -- всё как у On/Off через ODR |=, что и
должно было быть

---- через Latched() ? Off() : On()
Полные глупости при компиляции, компилируется в условные переходы,
нестабильный и плохой результат.

---- через GPIOx->BSRR = Latched() ? mask << 16 : mask;

551 001a DA68 ldr r2, [r3, #12]
556 001c 12F0020F tst r2, #2
557 0020 0CBF ite eq
558 0022 0222 moveq r2, #2
559 0024 4FF40032 movne r2, #131072
561 0028 1A61 str r2, [r3, #16]
-- 14 байтов, 12 циклов (около 167 ns импульс)
Опять выходит немного больше, чем по рассчёту -- как и для ODR |= / &= / ^=


---- через bit-band
525 0010 5A68 ldr r2, [r3, #4]
526 0012 D243 mvns r2, r2
527 0014 5A60 str r2, [r3, #4]
-- 6 байтов, те же самые 12 циклов, что и выше.
По коду короче даже ODR ^=
По времени дольше, зато атомарно.

---- через GPIOx->BSRR = Latched() ? mask << 16 : mask;

Но Latched() сделано через bit-band
619 004a 5268 ldr r2, [r2, #4]
624 004c 002A cmp r2, #0
625 004e 0CBF ite eq
626 0050 0222 moveq r2, #2
627 0052 4FF40032 movne r2, #131072
629 0056 1A61 str r2, [r3, #16]
Немного короче и бстрее, чем с Latched() через считывание ODR и маскирование.
Тут использовать особого смысла нет, так как почти не быстрее
bit-band, но длиннее.
Но сам Latched() стоит сделать через bit-band. Разница между
556 001c 12F0020F tst r2, #2
и
624 004c 002A cmp r2, #0
мелочь, а приятно. А где-то просто эта единичка/нолик сразу в bool
пойдёт для возврата из функции.


По результатам этих исследований победил вариант с BB sm.gif
ViKo
Цитата(demiurg_spb @ Apr 8 2011, 12:50) *
Т.е. так вполне сносно будет?

Думаю, да. А для чтения-модификации бита можете и ODR регистр использовать.
Мне не было необходимости делать именно инверсию бита. Просто задаю то состояние, что нужно.

Цитата(AHTOXA @ Apr 8 2011, 13:25) *
На так давно ReAl провёл целое исследование на эту тему. Я позволю себе процитировать фрагмент его письма:
По результатам этих исследований победил вариант с BB sm.gif

Трудно сравнивать объективно, потому что слова для записи и адреса еще нужно подготовить.
Вот листинг того кода, что я показал.
Код
;;;370    void LED_Blink(void) {
000386  482e              LDR      r0,|L1.1088|
;;;371      while (1) {
;;;372        GPIOB->BSRR = 0x0002;
000388  f04f0102          MOV      r1,#2
                  |L1.908|
00038c  f8c01c10          STR      r1,[r0,#0xc10]
;;;373    //    __nop(), __nop(), __nop(); // from Flash 12 clock states
;;;374    //  __nop(), __nop();   // from RAM 14 clock states
;;;375        GPIOB->BRR = 0x0002;
000390  f8c01c14          STR      r1,[r0,#0xc14]
000394  e7fa              B        |L1.908|
;;;376      }
;;;377    }

Пара регистров BSRR, BRR тем и хороша, что одним и тем же словом можно установить или сбросить бит. Как в этом коде - оно хранится в R1. И адрес структуры один - в R0. А смещение внутри команды задается.
Я пробовал и с bit-band, у меня получилось хуже.
AHTOXA
Цитата(ViKo @ Apr 8 2011, 16:32) *
Трудно сравнивать объективно, потому что слова для записи и адреса еще нужно подготовить.

Что может быть объективнее тактов и байтов? sm.gif
А адрес надо готовить в любом случае, что с BB, что с B(S)RR.
ViKo
Цитата(AHTOXA @ Apr 8 2011, 14:38) *
Что может быть объективнее тактов и байтов? sm.gif

Пусть бы ReAl показал результат не для
---- через GPIOx->BSRR = Latched() ? mask << 16 : mask;
а
if (Latched()) GPIOx->BSRR = mask;
else GPIOx->BRR = mask;
Впрочем, для инверсии бита, наверное, вывод ReAl верный.
Зато через регистр BSRR можно зараз сбросить-установить кучу битов.

Покажу результат своих только что проделанных экспериментов. Считайте сами, не забудьте константы в конце кода.
Код
                  Bit_change1 PROC
;;;68    
;;;69     void Bit_change1(bool set)
000004  b118              CBZ      r0,|L1.14|
;;;70     {
;;;71       if (set) GPIOB->BSRR = 0x0002;
000006  2102              MOVS     r1,#2
000008  4a0f              LDR      r2,|L1.72|
00000a  6011              STR      r1,[r2,#0]
00000c  e002              B        |L1.20|
                  |L1.14|
;;;72       else     GPIOB->BRR  = 0x0002;
00000e  2102              MOVS     r1,#2
000010  4a0e              LDR      r2,|L1.76|
000012  6011              STR      r1,[r2,#0]
                  |L1.20|
;;;73     }
000014  4770              BX       lr
;;;74    
                          ENDP

                  Bit_change2 PROC
;;;75     void Bit_change2(bool set)
000016  b108              CBZ      r0,|L1.28|
;;;76     {
;;;77       GPIOB->BSRR = 0x0002<<(set ? 0 : 16);
000018  2200              MOVS     r2,#0
00001a  e000              B        |L1.30|
                  |L1.28|
00001c  2210              MOVS     r2,#0x10
                  |L1.30|
00001e  2102              MOVS     r1,#2
000020  4091              LSLS     r1,r1,r2
000022  4a09              LDR      r2,|L1.72|
000024  6011              STR      r1,[r2,#0]
;;;78     }
000026  4770              BX       lr
;;;79    
                          ENDP

                  Bit_change3 PROC
;;;80     void Bit_change3(bool set)
000028  b108              CBZ      r0,|L1.46|
;;;81     {
;;;82       GPIOB->BSRR = set ? 0x0002 : 0x0002<<16;
00002a  2102              MOVS     r1,#2
00002c  e001              B        |L1.50|
                  |L1.46|
00002e  f44f3100          MOV      r1,#0x20000
                  |L1.50|
000032  4a05              LDR      r2,|L1.72|
000034  6011              STR      r1,[r2,#0]
;;;83     }
000036  4770              BX       lr
;;;84    
                          ENDP

                  Bit_change4 PROC
;;;91    
;;;92     void Bit_change4()
000038  4905              LDR      r1,|L1.80|
;;;93     {
;;;94     #define ALIAS_PTR(VarPtr,BitNum) \
;;;95       *((__IO uint32_t *) (((uint32_t) &(VarPtr) & 0xf0000000) | 0x02000000 \
;;;96       + (((uint32_t) &(VarPtr) & 0xfffff) <<5) | (BitNum <<2)))
;;;97    
;;;98       uint32_t bit = ALIAS_PTR(GPIOB->ODR,1);
00003a  6808              LDR      r0,[r1,#0]
;;;99       bit = !bit;
00003c  b908              CBNZ     r0,|L1.66|
00003e  2101              MOVS     r1,#1
000040  e000              B        |L1.68|
                  |L1.66|
000042  2100              MOVS     r1,#0
                  |L1.68|
000044  4608              MOV      r0,r1
;;;100    }
000046  4770              BX       lr
;;;101    
                          ENDP

                  |L1.72|
                          DCD      0x40010c10
                  |L1.76|
                          DCD      0x40010c14
                  |L1.80|
                          DCD      0x42218184
AHTOXA
Цитата(ViKo @ Apr 8 2011, 18:59) *
Впрочем, для инверсии бита, наверное, вывод ReAl верный.

Дык, вопрос-то как раз и был про инверсию бита.
Цитата(ViKo @ Apr 8 2011, 18:59) *
Покажу результат своих только что проделанных экспериментов. Считайте сами, не забудьте константы в конце кода.

Вот благодетель! Не пожалел времени и сил, накропал гениальной рукой десяток тривиальных гениальных строк, и поделился со всеми! Нате, считайте!
Спасибо, что-то не хочется. В чём заключались ваши "эксперименты", если ничего не посчитано? В выяснении возможности скопипастить кусок дизассемблерного текста в форум? cranky.gif
ViKo
Цитата(AHTOXA @ Apr 8 2011, 17:52) *
Вот благодетель! Не пожалел времени и сил, накропал гениальной рукой десяток тривиальных гениальных строк, и поделился со всеми! Нате, считайте!
Спасибо, что-то не хочется. В чём заключались ваши "эксперименты", если ничего не посчитано? В выяснении возможности скопипастить кусок дизассемблерного текста в форум? cranky.gif

Вообще-то, я не вам предлагал считать. Тот код, что я показал, содержит все строки исходного кода. Кому интересно, может скомпилировать и изучить самостоятельно. ALIAS_PTR(), например, кому-нибудь может пригодиться.
А что, байты посчитать тяжелая задача?
P.S. А грубить зачем?
P.P.S. А про инверсию бита я уже сказал - обхожусь без инверсии, задаю то, что мне нужно через BSRR и BRR.
AHTOXA
Цитата(ViKo @ Apr 9 2011, 00:53) *
P.S. А грубить зачем?

Ну что вы, какая грубость? Так, лёгкий сарказм.
Дело в том, что я привёл вариант, скажем так, выстраданный, выбранный после многих тестов (ещё раз респект ReAl-у). И по размеру кода, и по тактам. А вы, походя, совершенно безо всяких тестов, его осудили. (Те кусочки дизассемблера - они не в счёт, ибо во-первых, несерьёзны, во-вторых, без замеров тактов, ну и в-третьих, были сделаны уже после исходных утверждений).
ReAl
Цитата(ViKo @ Apr 8 2011, 15:59) *
Пусть бы ReAl показал результат не для
---- через GPIOx->BSRR = Latched() ? mask << 16 : mask;
а
if (Latched()) GPIOx->BSRR = mask;
else GPIOx->BRR = mask;
Я похож на человека, который такое не проверит?
ODR ^= просто было написано первым, так как «идеологически просто». Но за неатомарность было забанено. Затем первым из других вариантов было проверено как раз предлагаемое, читаем внимательно:
Цитата
---- через Latched() ? Off() : On()
Полные глупости при компиляции, компилируется в условные переходы,
нестабильный и плохой результат.
Только после этого начался поиск других вариантов.
On и Off как раз и сделаны через BSRR = и BRR =. Причём совершенно параноидальная попытка вкопипастить прямой код, а не «вызов» готовых On/Off -- ничего не меняет.
В таком варианте оно иногда генерирует вполне приличные два str в разные смещения под ite, иногда жуткую муть с условными переходами и возвратами потом назад.
Сильно зависит от того, чем размыты операции. Между ними вставлялись и обращения к ОЗУ, и обращения к другим пинам -- пока этого не было сделано, вариант был кандидатом номер 1. А так -- может, со временем будет иметь право на жизнь.
ViKo
Цитата(AHTOXA @ Apr 9 2011, 08:37) *
Ну что вы, какая грубость? Так, лёгкий сарказм.
Дело в том, что я привёл вариант, скажем так, выстраданный, выбранный после многих тестов (ещё раз респект ReAl-у). И по размеру кода, и по тактам. А вы, походя, совершенно безо всяких тестов, его осудили. (Те кусочки дизассемблера - они не в счёт, ибо во-первых, несерьёзны, во-вторых, без замеров тактов, ну и в-третьих, были сделаны уже после исходных утверждений).

И сильно "стадали"? Рожали в муках, наверное? (вот это - легкий сарказм).
Дело в том, что я тоже поначалу загорелся этим bit-band, но попробовав, пришел к выводу, что для управления битами порта это не нужно, благодаря куче специально предназначенных регистров. И эту работу я провел не походя, и не вчера. Во всех случаях, кроме инверсии бита, работа через bit-band не дает ничего. А инверсия мне не нужна (может, именно поэтому и не нужна).
Хотите, "пострадаем" и "выберем после многих тестов" еще раз, вместе? Начнем со сброса бита?

Цитата(ReAl @ Apr 9 2011, 10:30) *
Сильно зависит от того, чем размыты операции.

Я же и говорю, что трудно посчитать объективно.
demiurg_spb
Да вроде всё понятно уже. Чего страдать-тоsm.gif.
Инверсия бита действительно не очень частое явление, но тем не менее эта функция must have, как говориться.
И bit-band в этом случае может быть весьма кстати.
Спасибо всем за поддержку дискуссии!
ReAl
Цитата(ViKo @ Apr 9 2011, 12:36) *
Я же и говорю, что трудно посчитать объективно.
Я говорю, что
обращение к BSRR или BRR в зависимости от текущего состояния ноги компилируется в код, вид которого (ITE или «обычный if» с условным и безусловным пеерходами) сильно зависит от остального кода.
Т.е. если в коде будет
PIN1.On();
PIN2.Cpl();
PIN3.Off();
PIN2.Cpl();
PIN4.On();
то может даже оказаться, что эти два Cpl() по варианту «пишем в BSRR или BRR» скомпилируются по разному (собственно, это и было замечено осциллографом). Тут не то, что объективно, тут никак посчитать нельзя.

обращение к BSRR с маской, зависящей от текущего состояния ноги компилируется в код, не зависящий от остального кода. Да, загрузка указателей может плавать по коду относительно других команд, но непосредственно проверка и изменение состояния всегда одинаковы.

Т.е. вариант «пишем в BSRR или BRR» однозначно хуже при текущем состоянии оптимизатора.
И в саоём «лучшем» варианте компиляции он выигрывает у принятого совсем немножко.


Цитата(ViKo @ Apr 9 2011, 12:36) *
Во всех случаях, кроме инверсии бита, работа через bit-band не дает ничего. А инверсия мне не нужна (может, именно поэтому и не нужна).
А разве в предложенном исходнике для изменения состояния выходов bit-band применяется где-то кроме инверсии?
Или «bit-band не нужен вообще, потому что он нужен только в том, что не нужно Вам лично» ?
ViKo
Цитата(ReAl @ Apr 9 2011, 13:31) *
А разве в предложенном исходнике для изменения состояния выходов bit-band применяется где-то кроме инверсии?
Или «bit-band не нужен вообще, потому что он нужен только в том, что не нужно Вам лично» ?

Отвечу вопросом на вопрос - а разве я такое где-то сказал?
Я сказал, что при манипуляции битами портов от bit-band пользы мало. Даже если и выиграешь пару байтов, по сравнению с общим количеством кода это пустое.
Хотя, я тоже стремлюсь использовать "совершенный" код. И применяю, например, такие конструкции:
Код
typedef struct {
  int  HelpEna : 1; // Индикация помощи
  int  Lang : 2; // Язык
  int  Vect : 1; // Точки / Вектора
  int  Wide : 1; // WorkArea Wide
  int  Scale : 2; // Work Scale Form
  int  dummy : 1;
} DPY_t __attribute__((bitband));

Работа с такими переменными компилируется в команды с использованием bit-band.
Bit-band манипуляции полезны, в первую очередь, своей атомарностью. Но при работе с портами ее (атомарность) можно получить и иными способами. А такты-байтики считать - не главное. IMHO.

P.S. В моем сообщении №99 нужно переставить местами bit-band alias и bit-band. Bit-band - это область в 1MB, а bit-band alias - это то, что имеет размер 32MB, и отражается на bit-band. Поправить сообщение уже не могу.

P.P.S. А есть ли у кого мысли, как этот bit-band реализован физически? Теряюсь в смутных догадках...
AHTOXA
Цитата(ViKo @ Apr 9 2011, 15:36) *
И сильно "стадали"? Рожали в муках, наверное? (вот это - легкий сарказм).

Это уже не сарказм, это юродствование.
Цитата(ViKo @ Apr 9 2011, 15:36) *
Дело в том, что я тоже поначалу загорелся этим bit-band, но попробовав, пришел к выводу, что для управления битами порта это не нужно, благодаря куче специально предназначенных регистров.

Дело в том, что вы это повторяете уже пятый раз. И все пять раз - мимо кассы. Ибо вопрос был конкретно про инверсию бита, и именно для этого случая (и только для него) в предложенном исходнике применён bit-band. Но на это вам наплевать, вам бы поумничать.
Цитата(ViKo @ Apr 9 2011, 15:36) *
И эту работу я провел не походя, и не вчера.

Не верю, уж извините.
Цитата(ViKo @ Apr 9 2011, 15:36) *
Хотите, "пострадаем" и "выберем после многих тестов" еще раз, вместе?

С вами? Увольте.
ViKo
Код
#include "stm32f10x.h"

#define ALIAS_PTR(VarPtr,BitNum) \
  *((__IO uint32_t *) (((uint32_t) &(VarPtr) & 0xf0000000) | 0x02000000 \
  + (((uint32_t) &(VarPtr) & 0xfffff)<<5) | (BitNum<<2)))

void Bit_toggle(void);

int32_t main(void)
{
  while (1) {
    Bit_toggle();
  }
}

void Bit_toggle()
{
//  GPIOC->ODR ^= 1UL<<8;
//  ALIAS_PTR(GPIOC->ODR,8) ^= 1;
//  ALIAS_PTR(GPIOC->ODR,8) = ~ALIAS_PTR(GPIOC->ODR,8);
}

Предлагаю всем желающим скомпилировать показанный код, раскомментировав одну из трех строк, и самостоятельно убедиться, что все три варианта дают одинаковое количество байтов, и одинаковое количество тактов.
А именно, для Keil 4.12 при оптимизации default программа занимает 18 байтов, плюс 4 байта константа адреса. Основной цикл while выполняется за 16 тактов в симуляторе. Вот листинг для одного из вариантов. Для других картина аналогичная.
Код
; generated by ARM C/C++ Compiler, 4.1 [Build 481]
; commandline ArmCC [--debug -c --asm --interleave -o.\objects\bit_toggle.o --depend=.\objects\bit_toggle.d --cpu=Cortex-M3 --apcs=interwork -O3 -IC:\Programs\Keil\ARM\INC -IC:\Programs\Keil\ARM\INC\ST\STM32F10x -DSTM32F10X_HD --omf_browse=.\objects\bit_toggle.crf Source\Bit_toggle.c]
                          THUMB
                          AREA ||.text||, CODE, READONLY, ALIGN=2
                  Bit_toggle PROC
;;;25    
;;;26     void Bit_toggle()
000000  4804              LDR      r0,|L1.20|
;;;27     {
;;;28       GPIOC->ODR ^= 1UL<<8;
000002  68c1              LDR      r1,[r0,#0xc]
000004  f4817180          EOR      r1,r1,#0x100
000008  60c1              STR      r1,[r0,#0xc]
;;;29     //  ALIAS_PTR(GPIOC->ODR,8) ^= 1;
;;;30     //  ALIAS_PTR(GPIOC->ODR,8) = ~ALIAS_PTR(GPIOC->ODR,8);
;;;31     }
00000a  4770              BX       lr
                          ENDP
                  main PROC
                  |L1.12|
;;;18    
;;;19     int32_t main(void)
00000c  f7fffffe          BL       Bit_toggle
;;;20     {
;;;21       while (1) {
;;;22         Bit_toggle();
000010  e7fc              B        |L1.12|
;;;23       }
;;;24     }
;;;25    
                          ENDP
000012  0000              DCW      0x0000
                  |L1.20|
                          DCD      0x40011000
                  __ARM_use_no_argv EQU 0
ReAl
Нет у меня кейла.
Но есть вопрос:
Как может одинаковое число байтов получаться для команд (это я беру цитаты из своих компиляций в GCC, но это не должно біть принципиально):
Прямой доступ к ODR, операция ^=
Код
521 0012 DA68     ldr r2, [r3, #12]
522 0014 82F00202 eor r2, r2, #2; ну никуда не деться от константы, с которой XOR-ить, в Вашем листинге аналогично
523 0018 DA60     str r2, [r3, #12]

Доступ через бит-банд, запись инверсии прочитанного
Код
525 0010 5A68 ldr r2, [r3, #4]
526 0012 D243 mvns r2, r2 ; константа не нужна, просто инвертируется весь регистр
527 0014 5A60 str r2, [r3, #4]


По одинаковости времени STR в «обычный» порт и в его bit-band область (скрытое RMW обращение) -- это симулятор какой-то турбированный. Реальный кристалл с осциллографом показывает разные результаты.
ViKo
Цитата(ReAl @ Apr 9 2011, 23:15) *
Как может одинаковое число байтов получаться для команд...
Доступ через бит-банд, запись инверсии прочитанного

Вот как компилирует Keil. Почему так, не знаю. Но уже замечал, что в IAR получается компактнее.
Код
;;;30       ALIAS_PTR(GPIOC->ODR,8) = ~ALIAS_PTR(GPIOC->ODR,8);
000002  6801              LDR      r1,[r0,#0]
000004  ea6f0101          MVN      r1,r1
000008  6001              STR      r1,[r0,#0]

Цитата
По одинаковости времени STR в «обычный» порт и в его bit-band область (скрытое RMW обращение) -- это симулятор какой-то турбированный. Реальный кристалл с осциллографом показывает разные результаты.

Если, как видите, команды для обычной пересылки и пересылки в bit-band, практически, одни и те же (а по тактам полностью одинаковые, EOR и MVN выполняются за одну команду), то с чего бы второй вариант был быстрее? Осциллограф показывает работу кода из flash. Попробуйте запустить из ОЗУ. Я делал, но точные цифры сейчас вряд ли найду.

P.S. У вас MVNS - с обновлением флагов, у меня MVN - без обновления. Кто здесь "правильнее" подошел, Keil или GCC, не могу сказать. С одной стороны, лишний раз флаги "портить" не желательно, вдруг они потом используются. С другой, с "порчей" флагов компактнее. В любом случае, это особенности компиляторов, а не достоинства bit-band.
Я, все же, останусь при своей точке зрения. Bit-band для манипуляции битами порта использовать не буду.
ReAl
Цитата(ViKo @ Apr 10 2011, 10:24) *
Если, как видите, команды для обычной пересылки и пересылки в bit-band, практически, одни и те же (а по тактам полностью одинаковые), то с чего бы второй вариант был быстрее?
Кто «второй»? Который с бит-банд? Так я везде говорю, что он медленнее, зато атомарный.

Полагаю, раз Ваш симулятор показывает одинаковое время для записи в какой-то адрес (не важно, это порт или ОЗУ) и в его bit-band-alias область (хотя это просто запись и RMW), то для следующих фрагментов кода:
Код
    str r1,[r0, #16];  показывает даже не на bit-band, в обычную область IO,
    str r1,[r0, #20];  но _не_ на память, а в APB2

Код
    str r1,[r0, #16]
    nop
    str r1,[r0, #20]
он покажет разное время?

Знаете, на старом добром AVR команда STS ADDR выглядит одинаково для записи во внутреннее ОЗУ и во внешнее. А время отличается, ещё и разное может быть для разных адресов внешнего ОЗУ, в зависимости от установки битов SRW* в XMCRA*.
А у кортекса всё ещё сложнее.

p.s. во всех рассмотренных примерах был stm32f103, ядро/AHB и APB2 работали на одинаковой частоте 72 Мгц, если APB2 присадить, то еще веселее должно быть с подсчётом времён.
ViKo
Цитата(ReAl @ Apr 10 2011, 10:59) *
Кто «второй»? Который с бит-банд? Так я везде говорю, что он медленнее, зато атомарный.

я забыл, перепутал
Цитата
Полагаю, раз Ваш симулятор показывает одинаковое время для записи в какой-то адрес и в его bit-band-alias область (хотя это просто запись и RMW)...

Для манипуляций с битами ODR - и там, и там используется RMW, читаем-меняем-записываем.
Аналогично для регистров BSRR и BRR - и там, и там используется просто запись.
Разница между обычным доступом и bit-band только в том, что обращаемся к целому слову или к одному биту. Вот она и "атомарность".
На 100% достоверность не претендую. Однако симулятор показывает... Надо знать само устройство этого bit-band.
Цитата
p.s. во всех рассмотренных примерах был stm32f103, ядро/AHB и APB2 работали на одинаковой частоте 72 Мгц

Аналогично.

Цитата(ReAl @ Apr 10 2011, 10:59) *
он покажет разное время?

добавил __nop(); получил на такт длительнее цикл, 17 тактов. А разве должно было быть иначе?
P.S. Чтобы разобраться до конца, попробую запустить свои варианты из flash, из RAM и посмотрю осциллографом. Доложу, когда сделаю.
ReAl
Цитата(ViKo @ Apr 10 2011, 12:28) *
Разница между обычным доступом и bit-band только в том, что обращаемся к целому слову или к одному биту. Вот она и "атомарность".
На 100% достоверность не претендую. Однако симулятор показывает... Надо знать само устройство этого bit-band.
Ну я же да линк на сай ARM.
Там чётко написано одной строкой, что «System bus interface» _запись_ в bit-band выполняет как атомароне(_чтение_-модификация-_запись_), скрыто от програмиста. Делать аппаратный побитовый доступ к мегабайтному адресному пространству -- дороговато.

Кстати, так же работает SBI в старых AVR-ках, в результате чего при обращении по SBI/CBI к некоторым регистрам в них отлично сбрасыватся соседние биты флагов, котрые сбрасываются записью единички.

Цитата(ViKo @ Apr 10 2011, 12:28) *
добавил __nop(); получил на такт длительнее цикл, 17 тактов. А разве должно было быть иначе?
Да. Время не меняется.
STR с точки зрения ядра выполняется может и один такт, запись ушла в AHB и досвидания. Там она по окну адресов перебрасывается на APB2, но ядро продолжает выполнять команды. Если следующей командой опять STR в ту же APB2 (вот в APB1 я не пробовал писать, интересно, что будет), то ядро начинает ждать готовности заброса данных в шину. Таким образом, в цепочке STR в APB2 каждый STR занимает два такта, такт сбоственно STR в IO и такт ожидания готовности для следующего STR.
Но если после STR стоит однотактовая команда, то она себе выполняется, а следующий STR уже никого не ждёт.

Привет симулятору ядра, пусть не болеет.
ViKo
Цитата(ReAl @ Apr 10 2011, 13:36) *
Там чётко написано одной строкой, что «System bus interface» _запись_ в bit-band выполняет как атомароне(_чтение_-модификация-_запись_), скрыто от програмиста. Делать аппаратный побитовый доступ к мегабайтному адресному пространству -- дороговато.
Да. Время не меняется.
Привет симулятору ядра, пусть не болеет.

Практика - критерий истины. Проверил на STM32VLDISCOVERY, на частоте 24MHz, код выполнялся из flash с 0 циклов ожидания (естественно).
Все три мои варианта (назовем P ^= 1UL<<8; BB ^= 0x1; BB = ~BB) работают одинаково.

Цикл выполняется за 15 тактов, а период полученной частоты, понятно, в 2 раза больше. Итого 24MHz/30 = 800kHz. Удивительно, что получилось именно 15, а не 16 тактов! Чудо.

Для проверки добавил код, разрешающий вывод через MCO 8MHz от кварцевого генератора HSE. Убедился, что 8MHz есть. Период же исследуемого сигнала стал 32 такта (16+16). Как и ожидалось изначально.

Добавил _nop();, ставил и перед изменением регистра, и после ставил. Период сигнала стал 34 такта (17+17). Как видите, NOP работает. Примечательно, что размер кода при этом увеличился на 4 байта, а не на 2. В-общем, работа компилятора - потемки.

Похоже, никаких лишних тактов обращение к bit-band alias не требует.
Несомненно, используется некий аппаратный способ.

Команда NOP может работать, как надо. Кроме шины AHB еще есть буфер предвыборки flash, который путает всю временную картину. Он состоит из 2-х 64-битовых регистров. Как туда лягут команды цикла - тайна, покрытая мраком.

Ради интереса попробовал работу с портом через BSRR, BRR. Вот такой код выдает на ножке 4MHz со скважностью 50%, 3 такта - 0, 3 такта - 1. Может быть, при другом раскладе кода будет иначе.
Код
  while (1) {
    GPIOC->BRR  = 0x00000100;
    __nop();  __nop();
    GPIOC->BSRR = 0x00000100;
  }

Сравните с 800kHz через инверсию. Понятно, вещи разные. Но для меня, как не было нужды инвертировать бит, так и не появилось желания. Одно удобно - при инвертировании скважность частоты будет точно 50%.
Вот такой вам ответ от DISCOVERY и Осциллографа с Симулятором. sm.gif
ReAl
Ну я всё гонял на F103-ем и на 72 МГц. Но не думаю, что тут предвыборка что-то сильно накосячила, команды-то все короткие (много влазит в буфер) и многие не однотактовые.
Чтобы уйти от циклов/вызовов/возвратов, делал линейный код с разным количеством повторов операций и стартовой отмашкой на другую ножку. Причм этой байды тоже несколько повтров ставил подряд -- все давали одинаковые импульсы. Точнее, как-то вдруг вылезли разные, так заметил, что одна и та же комбинация с if(on) BSRR = mask; else BRR = mask; компилируется по разному в разных местах.
И так чтобы ну совсем -- там не NOP стоял, а MVNS, почему-то именно его вставил :-)
Но и удлиннение работы STR в bit-band по сравению с простым доступом к региону, и удлиннение импульса на число_MVNS_между_STR_минус_1 тактов (т.е. отсутствие удлиннения при одном) поворялись уверенно.
Надо эту тему где-то себе на видное место положить, сейчас не до того, чтобы повторять замеры.
Если кто напомнит в конце апреля в личку, буду благодарен :-)
ViKo
Добавлю еще, что инвертировать бит везде, кроме рабочих регистров процессора ARM или Cortex - это не атомарная операция. Независимо от способа, "напрямую" или через bit-band. Потому, что сначала этот бит нужно прочитать, в виде целого слова, или как отдельный бит через bit-band alias. Нужно выполнить те самые неоднократно показанные три команды. Но после чтения может случиться что угодно до того, как измененный бит будет записан обратно.

Атомарными
будут только сброс или установка бита через bit-band. Потому, что это одна команда. А чтение-модификация-запись слова, содержащего нужный бит, делается аппаратно.
Также атомарными будут команды сброса или установки порта ввода-вывода через BSRR и BRR. Потому что в этом случае не происходит чтение-модификация-запись.

Цитата(ReAl @ Apr 10 2011, 20:20) *
Но не думаю, что тут предвыборка что-то сильно накосячила, команды-то все короткие (много влазит в буфер) и многие не однотактовые.

Не так уж и много. Если команда 4-байтовая, вот она половину одного регистра и забрала. Т.е., всего в два регистра влазит от 4-х до 8-ми команд. Вот последний показанный мой код влезет в два регистра. А как остальное, не знаю.
ReAl
Под атомарностью имелось ввиду отсутствие интерференции с работой в других местх с другими битами того же слова.
В этом смысле *ADDR ^= MASK с основным адресом не атомарен. Если будет прерывание, модифицирующее другую ногуэтого же порта - кака.
А с *ADDR_ALIAS = ~*ADDR_ALIAS такой проблемы не будет.
В этом же смысле атомарно и if ( ODR & mask ) BRR = mask; else BSRR = mask; и BSRR = (ODR & mask) ? mask << 16 : mask;

______
Чё ж так спать хочется... Ещё и двух ночи нет...
ViKo
В результате, для инвертирования бита через бит-бэнд,
по сравнению с обычным xor регистра ODR:
- Настоящей атомарности нет,
- Размер кода такой же,
- Время выполнения такое же.

ReAl
В результате, если к разным битам одного и того же порта идут инвертирования ножки из основного кода и из прерывания, то для xor с ODR в основном потоке надо добавить запрещающую/восстанавливающую прерывания обёртку. И в размер кода, и в его время.

Для инвертирования через bit-band не нужно, несмотря на «ненастоящую» атомарность.
У ODR ^= и такой нет.

Я понимаю, что использование Cpl() само по себе будет редким, а уж чтобы и в прерывании, и в основном коде, так и ещё реже. Но это не мешает подумать по возможных последствих (и положить на весы способы их обхода). Так как чем круче джип, тем дальше идти за трактором чем менее вероятен баг, тем дольше его искать при возникновении.
ViKo
Цитата(ReAl @ Apr 11 2011, 09:52) *
В результате, если к разным битам одного и того же порта идут инвертирования ножки из основного кода и из прерывания, то для xor с ODR в основном потоке надо добавить запрещающую/восстанавливающую прерывания обёртку. И в размер кода, и в его время.
Для инвертирования через bit-band не нужно, несмотря на «ненастоящую» атомарность.
У ODR ^= и такой нет.

С этим согласен.
Есть еще команды исключительного доступа. С ними пока серьезно не разбирался. Думаю, они помогли бы в описанном случае.
Ну, и те самые регистры - сбросить бит порта, установить бит порта. С истинной атомарностью. И голова не болит.
uvreg
Помогите с бутлоадером STM32F105.
Бутлоадер очень странно себя ведет. Судя по описанию протокола, для входа в режим команд нужно сбросить проц и подать на USART1 0x7F, после чего он должен ответить байтом 0x79. Однако, у меня сразу после сброса процессор выдает в порт 0x00 примерно три раза в секунду и на подачу 0x7F не реагирует. Flash loader demonstrator (v2.2.0) не опознает его, то есть получая эти ноли пишет, что чип не опознан и все.
Я взял терминалку, поставил выдачу 0x7F в цикле и сделал сброс процессора, после этого он вошел в режим команд бутлоадера. Далее, подавая команды вручную получаю нормальные ответы, но ведь вручную программу не зальешь.
Errata говорит, что в чипах с датой выпуска до 937 bootloader вообще не работает; у меня как раз 937 - должно работать. Как видно он и работает, но более чем странно.
Было предположение, что выбирается другая периферия для бутлоадера (есть еще USB, CAN и USART2), в даташите, сказано, что нельзя оставлять неподключенными соответствующие ноги. У меня неподключены. Посадил указанные ноги на землю, ничего не поменялось.
Кто зашивал по USART? Программировать по USB, JTAG или SWD возможности нет.
dac
кто-нибудь знает, как в Keil симулировать STM32F107RC? со 103 проблем нет. для 107 вылетает ошибка
*** error 65: access violation at 0x0000000C : no 'read' permission.
пробовал через MAP добавить доступ к этому диапазону адресов, но это бесполезно - он пытается исполнять программу с нулевого адреса, вместо 0x8000000. а в нуле соответственно программы нету.
при всех тех же настройках проекта и исходниках, проект скомпилированный для 103 нормально дебажится в симуляторе.

PS эмуляция через ST-Link работает нормально.
akimych
Цитата
кто-нибудь знает, как в Keil симулировать STM32F107RC? со 103 проблем нет. для 107 вылетает ошибка

Потому что симулятор кейла не умеет симулировать 107ой, а 103ий умеет. Для 107го только симулятор ядра.
Можно выбарть 103ий в настройках и симулировать, как 103ий.
ISK2010
У кого-нибудь пробивалась нога NRST? А у меня походу пробилась. Всего-то сменил батарейку) Напряжение батарейки измерялось ацп на 15ой ножке МК, а NRST - 14я. Сменил батарейку - не запускается. Пытаюсь конектится - без толку. Оказывается, что нога NRST в нуле теперь всегда. на выключенном девайсе там меж ногой и землей ~300 Ом. Т.е. внутри полевичек, который подтягивает к земле ногу, пробился(((. А перепаивать так не хотелось... Короче насильно резистором 10 Ом подтянул NRST к +3В. И, вуаля, все заработало. Только там теперь ток аж 15мА течет, и при отладке никакой ULINK или JLINK не сможет прорезетить МК, остается вручную помогать.

Но вот думаю, может не пробил, а кто-то в МК формирует резет. Но тогда ведь должны были быть импульсы и при выключении уж явно больше 300 Ом?

Aaron
Собираемся переходить на stm32f107 дружно, - будем покупать отладочные платы stm3210c-eval, а к ним ещё и программаторы-отладчики.
Прокомментируйте, пожалуйста, вопросы:
- с помощью st-link можно отлаживать мк только в keil, iar, плюс Ride и ST toolset (набор от STM). В eclipse можно только прошивать (используя консольную утилиту для st-link)?
- есть ли у openocd уже поддержка st-link? быстрый поиск говорит, что вопрос поднимался, но решения пока нет.
- если стоит задача обучения работе с мк с нуля (студенты и выпускники) - то какую среду разработки им лучше советовать (в контексте работы с данными контроллерами)?
- имеет смысл брать не узкоспециализированные st-link, а mt-link? преимущество mt-link только в его универсальности? Или st-link'и дают какие-то вкусные плюшки?
- на сайте Терраэлектроники продаются их собственные TE-ARM-LINK - "устройство является функциональным аналогом J-LINK (Segger, IAR)". они дешевле, чем mt-link. кто-нибудь с ними уже работал? думаю, может их закупить вместо mt-link (я так понимаю, ночинка-то у них идентичная wink.gif ).
ViKo
Цитата(ISK2010 @ Apr 14 2011, 12:57) *
Короче насильно резистором 10 Ом подтянул NRST к +3В. И, вуаля, все заработало. Только там теперь ток аж 15мА течет, и при отладке никакой ULINK или JLINK не сможет прорезетить МК, остается вручную помогать.

А вы 100 Ом прицепите вместо 10.
ISK2010
Цитата(ViKo @ Apr 14 2011, 14:35) *
А вы 100 Ом прицепите вместо 10.

Спасибо! Я уж думал поставить туда 120 Ом и дополнительно пару транзисторов, дабы не нагружать ULINKа 30мАмперами. Но прочивал ваше сообщение, и поставил просто 120 Ом))) Работает все как у новенького)

Вот только теперь вопрос. Какой максимальный втекающий ток по reset у ULINK?

И еще. Вы с таким уже сталкивались?


prm
Цитата(Aaron @ Apr 14 2011, 15:34) *
- есть ли у openocd уже поддержка st-link? быстрый поиск говорит, что вопрос поднимался, но решения пока нет.


Есть проект http://www.versaloon.com, почитав его форум можно найти информацию, как и чем перепрошить ST-Link, чтобы появилась поддержка openocd. Сам не делал, но судя по форуму, у людей все получилось.
ISK2010
Плата STM3210C. Почему на ней не разряжается батарейка при выключенном питании?!? Я повторил схемку, у меня разряжается. И так должно быть, ведь там на gpio в МК диоды стоят, а через диод и измерительный резистор 10кОм батарейка замыкается на Vdd. Итог - 250мкА. Ну никак не могу понять, почему на доске STM3210C нет этого тока.

P.S. Не повторил бы бездумно схему, не разрядилась бы батарейка, не стал бы её менять, не убил бы статикой ногу NRST... (см.выше)

ViKo
Цитата(ISK2010 @ Apr 14 2011, 13:54) *
Вот только теперь вопрос. Какой максимальный втекающий ток по reset у ULINK?
И еще. Вы с таким уже сталкивались?

Не знаю. Не сталкивался. Предложил, руководствуясь законом Ома. sm.gif
dac
QUOTE (akimych @ Apr 14 2011, 07:57) *
Потому что симулятор кейла не умеет симулировать 107ой, а 103ий умеет. Для 107го только симулятор ядра.
Можно выбарть 103ий в настройках и симулировать, как 103ий.

keil не умеет для 107 симулировать ВСЮ периферию. а уж uart точно должен уметь, т.к. идентичен 103. проблема как раз не в симуляции периферии, а в симуляции ядра. симулятор запускает с 0 адреса вместо 0х8000000
akimych
А с чего он вдруг должен стартовать с 0х800000? Если он знать не знает, что там еще есть кроме ядра, а флеш частью ядра не является.
Дело в том как устроен симулятор кейла. Не умеет он симулировать по отдельности. Типа вот тут у нас уарты одинаковые - это я могу, а вот тут что-то другое не могу. Просто симулятор не знает
чипа stm32f107 вообще. Потому и ведет себя подобным образом, симулирует только ядро, стартует с 0 и т.д.
Если очень хочется, можно заставить симулятор ядра стартовать с 0х800000, да только какой смысл, если можно запустить симулятор как f103 и получить тоже самое + часть периферии, которая у f107 такая же.
dac
QUOTE (akimych @ Apr 17 2011, 22:02) *
А с чего он вдруг должен стартовать с 0х800000? Если он знать не знает, что там еще есть кроме ядра, а флеш частью ядра не является.
Дело в том как устроен симулятор кейла. Не умеет он симулировать по отдельности. Типа вот тут у нас уарты одинаковые - это я могу, а вот тут что-то другое не могу. Просто симулятор не знает
чипа stm32f107 вообще. Потому и ведет себя подобным образом, симулирует только ядро, стартует с 0 и т.д.
Если очень хочется, можно заставить симулятор ядра стартовать с 0х800000, да только какой смысл, если можно запустить симулятор как f103 и получить тоже самое + часть периферии, которая у f107 такая же.

понятно. жаль конечно, всегда в железе отлаживал уже на заключительном этапе, либо придется симулировать для 103, а в железе уже 107 sad.gif и это хваленый кейл 1111493779.gif интересно когда поддержку 107 в симуляторе планируют?
akimych
Сомневаюсюь, что вообще планируют. F217 уже вроде как добавили, а он позже появился. Так же как и F100 уже давно могли бы добавить, там же различий почти нет с F101.
Забавно, что кейл почему-то думает, что у них симулятор поддерживает частично F107. На сайте написано и в настройках симулятора именно F107 выставляется, если его выбрать. С F100 честно пишут, что не поддерживается и в настройках симулятора сразу прописывается симулятор ядра.
ViKo
В дополнение к разговору о битах, выкладываю свои макрофункции конфигурирования портов STM32 - модификации конфигурации одиночного бита, и записи конфигурации младшего или старшего байта порта целиком.
По-моему, простенько (и красиво)...
Код
/* Port bit configuration table */
typedef enum {
  IN_ANALG, GPO_PP10, GPO_PP02, GPO_PP50,  // Input Analog, GP Output Push-pull 10-2-50MHz
  IN_FLOAT, GPO_OD10, GPO_OD02, GPO_OD50,  // Input Float, GP Output Open-drain 10-2-50MHz
  IN_PD_PU, AFO_PP10, AFO_PP02, AFO_PP50,  // Input Pull-down/Pull-up, Alt Func Push-pull
  CFG_None, AFO_OD10, AFO_OD02, AFO_OD50   // none(illegal), Alt Func Open-drain 10-2-50MHz
} CFG_MODE;

/*!
*******************************************************************************
* @brief Port Low/High byte configuration
* @details Конфигурация байтов порта целиком
* @param PORT - имя порта (A..G)
* @param CM15..CM00 - конфигурация битов 15..0
* @return нет
* @note Используется перечисляемый тип CFG_MODE
* @note Для IN_PD_PU нужный pull-down, pull-up задается в ODR
*******************************************************************************/
#define GPIO_PORTL_CFG(PORT,CM07,CM06,CM05,CM04,CM03,CM02,CM01,CM00) \
GPIO##PORT->CRL = (CM07<<28|CM06<<24|CM05<<20|CM04<<16|CM03<<12|CM02<<8|CM01<<4|CM00)

#define GPIO_PORTH_CFG(PORT,CM15,CM14,CM13,CM12,CM11,CM10,CM09,CM08) \
GPIO##PORT->CRH = (CM15<<28|CM14<<24|CM13<<20|CM12<<16|CM11<<12|CM10<<8|CM09<<4|CM08)

/*!
*******************************************************************************
* @brief Bit of Low/High byte Port configuration
* @details Конфигурация одиночного бита порта
* @param PORT - имя порта (A..G)
* @param BIT - номер бита (0..15)
* @param CM - конфигурация бита
* @return нет
* @note Используется перечисляемый тип CFG_MODE
* @note Для IN_PD_PU нужный pull-down, pull-up задается в ODR
*******************************************************************************/
#define GPIO_LBIT_CFG(PORT,BIT,CM) \
GPIO##PORT->CRL = GPIO##PORT->CRL & (~(0xf<<BIT*4)) | (CM<<BIT*4)

#define GPIO_HBIT_CFG(PORT,BIT,CM) \
GPIO##PORT->CRH = GPIO##PORT->CRH & (~(0xf<<(BIT-8)*4)) | (CM<<(BIT-8)*4)


Добавлю пример использования
Код
  GPIO_LBIT_CFG(A,0,IN_FLOAT);
  GPIO_HBIT_CFG(A,8,AFO_PP50);
  GPIO_PORTL_CFG(B,IN_PD_PU,IN_PD_PU,IN_PD_PU,IN_PD_PU,IN_PD_PU,IN_PD_PU,IN_PD_PU,IN_PD_PU);
  GPIO_PORTH_CFG(B,GPO_PP10,GPO_PP10,GPO_PP10,GPO_PP10,GPO_PP10,GPO_PP10,GPO_PP10,GPO_PP10);
ARV
у меня вопрос тупой до безобразия... решил пойти в ногу с прогрессом и освоить ARM наконец-таки. для чего приобрел STM32vldiscovery, как наиболее дешевую платку. Скачал и установил Yagarto, плагин для Eclipse и наэтом подзастрял.
во-первых, смотрю в демо-проекты, скачанные с сайта ST, и не могу найти некоторых хидеров. куда они их позасунули? какова вообще структура библиотечных файлов поддержки камней STM32 "от производителя"? может, не стоит ими пользоваться? опыт WinAVR как-то не очень помогает - там все камушки описывались хидерами, лежащими в одной папке, поставляемой с WinAVR, генератор проекта позволял выбрать нужный кристалл - и аллес, на этом подготовка кончалась, оставалось только вспомнить, какая периферия доступна и пользоваться ею. пока что такой аналогии в STM32 не прослеживаю... научите, пожалуйста!

во-вторых, если у кого есть опыт работы со всем упомянутым счастьем именно в Eclipse, посоветуйте, что и как там настроить для комфортной работы? Может, есть толковые ссылки по этой теме, плагины какие-то особые? Скачал ARM Eclipse plugin - но, может, это не самое лучшее, что есть?

в общем, что-то я в тумане почище ежика... дайте толчок - дальше попробую сам... не смотря на то. что GCC считается кросс-компилятором, для всех таргетов свои фишки, голова пухнет sad.gif
AHTOXA
Цитата(ARV @ Apr 21 2011, 00:03) *
в общем, что-то я в тумане почище ежика... дайте толчок - дальше попробую сам... не смотря на то. что GCC считается кросс-компилятором, для всех таргетов свои фишки, голова пухнет sad.gif

А ибо нефиг пользовать специализированные плагиныsm.gif
Если взять просто эклипс, и делать makefile-based проекты, то работа со всеми поддерживаемыми GCC таргетами практически идентична.

Что касаемо примеров от ST, то обычно там лежит их библиотека, по крайней мере во всех, что я видел - лежала.
Я лично её не использую, не нравится. Могу порекомендовать примеры от scmRTOS, четвёртый там точно под VL.

---
ЗЫ. Ещё вот тут постил пример, он вроде на сях и с ст-шной библиотекой.
ARV
Цитата(AHTOXA @ Apr 20 2011, 22:51) *
А ибо нефиг пользовать специализированные плагины sm.gif
Если взять просто эклипс, и делать makefile-based проекты, то работа со всеми поддерживаемыми GCC таргетами практически идентична.

Что касаемо примеров от ST, то обычно там лежит их библиотека, по крайней мере во всех, что я видел - лежала.
Я лично её не использую, не нравится. Могу порекомендовать примеры от scmRTOS, четвёртый там точно под VL.

---
ЗЫ. Ещё вот тут постил пример, он вроде на сях и с ст-шной библиотекой.


во-первых, в примерах ST нет makefile. а сделать его самостоятельно, не имея прочных понятий в новой архитектуре и не будучи знакомым с новым компилятором, я не смогу.


во-вторых, если не ST-шная библиотека - то какая альтернатива? где вся ST-шная периферия описана хорошо? не самому же все эти бесчисленные GPIO и т.п. описывать?! не понимаю...

ну а ссылки - погляжу, спасибо, может, что прояснится...

AHTOXA
Цитата(ARV @ Apr 21 2011, 01:34) *
во-первых, в примерах ST нет makefile. а сделать его самостоятельно, не имея прочных понятий в новой архитектуре и не будучи знакомым с новым компилятором, я не смогу.

Ну так возьмите готовыйsm.gif В тех примерах, на которые я сослался, для добавления файла к проекту достаточно расположить его в каталоге src. А вообще - makefile и архитектура - вещи практически ортогональные.
Цитата(ARV @ Apr 21 2011, 01:34) *
во-вторых, если не ST-шная библиотека - то какая альтернатива? где вся ST-шная периферия описана хорошо? не самому же все эти бесчисленные GPIO и т.п. описывать?! не понимаю...

Альтернатива - ручками, через регистры. Доку про них всё равно придётся читать, что с библиотекой, что без.
А все регистры описаны в паре специальных файлов - stm32f10x.h и core_cm3.h. Они не являются частью FwLib, а входят в CMSIS.
Axel
Контроллер STM32F103RD. Не могу заставить ADC1 тактироваться от Timer2. Вариантов перепробовал ...очень много. В чем может быть фишка?
KARLSON
Без кода инициализации, что у Вас сейчас, вряд ли поможем.
Axel
Цитата(KARLSON @ Apr 21 2011, 21:40) *
Без кода инициализации, что у Вас сейчас, вряд ли поможем.


Вот один из вариантов:
CODE
void ADC1_Init()
{
ADC1->CR1 = ADC_CR1_DISCEN | ADC_CR1_EOCIE;
ADC1->CR2 = ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTTRIG;

ADC1->SQR1 = 0x00;
ADC1->SQR2 = 0x00;
ADC1->SQR3 = ADC_SQR3_SQ1_0;
ADC1->SMPR2 = ADC_SMPR2_SMP1_2; //0x08;

ADC1->CR2 |= ADC_CR2_ADON;
ADC1->CR2 |= ADC_CR2_RSTCAL;
while(ADC1->CR2 & ADC_CR2_RSTCAL);
ADC1->CR2 |= ADC_CR2_CAL;
while(ADC1->CR2 & ADC_CR2_CAL);
ADC1->SR = 0;
}

void TIM2_Init()
{
TIM2->CR1 = TIM_CR1_ARPE;
TIM2->SMCR = 0;
TIM2->ARR = 49;
TIM2->PSC = 0x47;
// TIM2->CCR2 = 50;

// TIM2->CCMR1 = TIM_CCMR1_OC2PE | TIM_CCMR1_OC2CE;
TIM2->CCMR1 = TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE;
// TIM2->CCMR1 = TIM_CCMR1_OC2CE;
TIM2->EGR = TIM_EGR_CC2G;
TIM2->DIER = TIM_DIER_CC2IE;
TIM2->CCER = TIM_CCER_CC2E;
}


Хедер прикрепил.
Нажмите для просмотра прикрепленного файла
Alechin
Не могу заставить процессор запускаться с программой из флеши. Писал-писал, отлаживался в IARе через ST-Link. А тут решил включить плату отдельно - не хочет запускать программу! ST-Link Utility показывает, что файл прошит. Но стартует программу только если нажать "Core Reset" В чем может быть причина?
Danis
Цитата(Alechin @ Apr 22 2011, 13:27) *
Не могу заставить процессор запускаться с программой из флеши. Писал-писал, отлаживался в IARе через ST-Link. А тут решил включить плату отдельно - не хочет запускать программу! ST-Link Utility показывает, что файл прошит. Но стартует программу только если нажать "Core Reset" В чем может быть причина?


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