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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> STM32F207 - проблемы с bitband при доступе к EXTI->PR
Непомнящий Евген...
сообщение Jul 1 2015, 04:33
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Есть код, который использует внешние прерывания. Примерно такой
CODE
template<class T>
constexpr T* bitbandAddr(T *addr, unsigned bit); // возвращает адрес в bitband-области для адреса addr и бита bit

struct ExternalInterrupt {
unsigned no;
// ...
static bool checkIfInterrupt(unsigned no) { return *bitbandAddr(&EXTI->PR, no); }

bool checkIfInterruptAndClear() {
bool r = checkIfInterrupt(no);
if ®
*bitbandAddr(&EXTI->PR, no) = 1;
return r;
}
};

extern "C" void EXTI9_5_IRQHandler() {
/* 1 */
for (unsigned i = 5; i < 10; ++i)
if (ExternalInterrupt::checkIfInterrupt(i))
interrupts.exti[i].fire(); // вызов коллбэка, если он есть
}

void onIntA() { // этот коллбэк связан с interrupts.exti[8]
if (ei[0].checkIfInterruptAndClear()) {
/* 2 */
}
}

void onIntB() { // этот коллбэк связан с interrupts.exti[9]
if (ei[1].checkIfInterruptAndClear()) {
/* 3 */
}
}


Оба прерывания настроены на изменение фронта на входе.

По факту иногда код пропускает изменение фронта. Сделал инвертирование контролек в некоторых местах, оказалось что иногда в /* 1 */ оно попадает, а в /* 2 */ или /* 3 */ - нет.

Переписал функции checkIfInterruptXXX без использования bitband (и больше ничего не трогал) - все стало хорошо. Регистр EXTI->PR типа rc_w1 (чтение, сброс бита записью 1). bitband тут собственно не нужен, поставил в свое время по инерции. Но не ясно, почему с ним работает как-то избирательно.

Никто с подобным не сталкивался?

Сообщение отредактировал IgorKossak - Jul 1 2015, 06:01
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 1 2015, 04:41
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



возможно для битбанга нужно барьеров напихать?
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jul 1 2015, 04:58
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(Golikov A. @ Jul 1 2015, 07:41) *
возможно для битбанга нужно барьеров напихать?


Вы меня подтолкнули к тому, чтобы перечитать cortex m3 prog manual
Цитата
Data accesses to this region are remapped to bit-band region. A write
operation is performed as read-modify-write. Instruction accesses are
not permitted.


Собственно вопрос снят. Если два прерывания произвошли одновременно, то в PR будет установлено 2 бита, и инструкция *bitbandAddr(&EXTI->PR, no) = 1; приведет к чтению всего регистра, модификации бита (который и так 1) и записи всего этого обратно (в результате будут сброшены оба бита) smile3046.gif
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 1 2015, 06:03
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Непомнящий Евгений @ Jul 1 2015, 07:58) *
Собственно вопрос снят.

Неа, это только начало...

Мне всегда казалось, что запись в bit-band обеспечивает атомарность. Неужели это не так?
Как понимать "read-modify-write"? Это по сколько бит? По 1/8/16/32?
Как быть с регистрами, где чтение имеет побочное действие?
А при чтении тоже считывается не один бит?
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jul 1 2015, 06:31
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(adnega @ Jul 1 2015, 09:03) *
Мне всегда казалось, что запись в bit-band обеспечивает атомарность. Неужели это не так?

Мне тоже. Почему то в programming manual об этом ничего не нашел, перечитал Yiu J., The Definitive Guide to the ARM Cortex-M3

One of the most important advantages or properties of a bit-band operation is that it is atomic. ...
With the Cortex-M3 bit-band feature, this kind of race condition can be avoided because the READ-
MODIFY-WRITE is carried out at the hardware level and is atomic (the two transfers cannot be pulled
apart) and interrupts cannot take place between them.

Цитата
Как понимать "read-modify-write"? Это по сколько бит? По 1/8/16/32?

Нашел такое:
Bit band accesses can use byte, halfword, or word transfers. The bit band transfer size matches the transfer size of the instruction making the bit band access.

и такое
For write operations, the written bit data are shifted to the required bit position, and a READ-MODIFY-WRITE is performed.

Цитата
Как быть с регистрами, где чтение имеет побочное действие?
А при чтении тоже считывается не один бит?

For read operations, the word is read and the chosen bit location is shifted to the LSB of the read return data.

Получается, что засада может быть с регистрами вида rc_w0 и rc_w1 (для которых собственно битбанд и не нужен), на что я и напоролся
Go to the top of the page
 
+Quote Post
LightElf
сообщение Jul 1 2015, 06:54
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205



QUOTE (adnega @ Jul 1 2015, 09:03) *
Мне всегда казалось, что запись в bit-band обеспечивает атомарность. Неужели это не так?

Атомарность обеспечивается на уровне процессора (операция не может быть прервана), для периферии никто ничего не обещает.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 1 2015, 06:55
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ну да скорее всего...

вместо записи 1 бита вы всегда писали все биты замапленые на этот регион. Причем прерывание могло происходить не в момент записи а в момент обработки, а та строка которая должна была снять 1 бит всегда снимала их все, потому что чтение из этого региона скорее всего было константой не зависимо от состояния.... или что-то типа того.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 3 2015, 04:14
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Непомнящий Евгений @ Jul 1 2015, 09:31) *
Получается, что засада может быть с регистрами вида rc_w0 и rc_w1 (для которых собственно битбанд и не нужен), на что я и напоролся

Я в одно время очень сильно подсел на битовый доступ именно к периферии.
Потом в новых ST из bit-band убрали GPIO - интерес к поутих.
Сейчас использую M0, там нет битового доступа вообще.

Вроде, msc-51 и AVR битовые операции делали без r-m-w?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 3 2015, 05:16
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



а регистра поставить бит, снять бит для портов нету?
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 3 2015, 05:35
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Golikov A. @ Jul 3 2015, 08:16) *
а регистра поставить бит, снять бит для портов нету?

Конечно есть. И ODR, и BSRR. Но битовый доступ гораздо удобнее.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 3 2015, 08:21
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Чем удобнее? Макросом через дефайн не решается?
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 3 2015, 08:29
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Golikov A. @ Jul 3 2015, 11:21) *
Чем удобнее? Макросом через дефайн не решается?

Я понимаю, что есть более одного правильного решения.
Я в структурах хранил адрес бита, чтоб потом делать так:
Код
*pwm_pin = 1;

Можно хранить номер порта и номер пина и делать так:
Код
void set_pin(const WORD pin, const BYTE value)
{
    switch(pin & 0xF0)
    {
        case GPIOA_PORT: GPIOA->BSRR = (1 << (pin & 15)) << ((value)? 0 : 16); break;
        case GPIOB_PORT: GPIOB->BSRR = (1 << (pin & 15)) << ((value)? 0 : 16); break;
        case GPIOC_PORT: GPIOC->BSRR = (1 << (pin & 15)) << ((value)? 0 : 16); break;
        case GPIOD_PORT: GPIOD->BSRR = (1 << (pin & 15)) << ((value)? 0 : 16); break;
        case GPIOE_PORT: GPIOE->BSRR = (1 << (pin & 15)) << ((value)? 0 : 16); break;
        case GPIOF_PORT: GPIOF->BSRR = (1 << (pin & 15)) << ((value)? 0 : 16); break;
    }
}

set_pin(PWM_PIN, 1);

Или вы как-то по другому предлагаете?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 3 2015, 10:06
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Обычно дефайнами, так как пины обычно дергаю руками
#define MY_PIN_1 (LPC_GPIO0 -> SET = (1ul << n))
#define MY_PIN_0 (LPC_GPIO0 -> CLR = (1ul << n))

В смысле явным образом в функциях задаю когда какой пин поднять - опустить....

Мне трудно представить зачем хранить в структурах номер пина, который надо дергать. Потому что кроме рывков надо же этот пин еще настроить, и снаружи какая-то обвеска должна быть, то есть фактически это в 99% константа. Потому если есть какой-то ногодрыг в 1% случаем с возможностью смены пинов, то он в итоге у меня будет завернут в функцию, а внутри все будет явным образом сделано.

Потому я и просил пример, где оно может быть удобнее
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jul 3 2015, 10:29
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(Golikov A. @ Jul 3 2015, 13:06) *
Потому я и просил пример, где оно может быть удобнее


В каком-то обобщенном коде. К примеру у меня есть обертка над УАРТ-ом, с поддержкой 485 (и сигнала DE). Ножка, на которой DE, задается как раз константой. Инфраструктура позволяет настроить ножку по такой константе, установить ее значение и т.п.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 3 2015, 10:45
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ну в этом случае вам одного адреса не хватит, ведь для настройки порта надо знать конкретно какой порт и какая в нем нога. Хотя конечно можно хранить адреса битбанда для всех параметров...
но в целом понятно, надо признать какое-то удобство в этом имеется.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 1st July 2025 - 12:31
Рейтинг@Mail.ru


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