|
|
  |
давайте делится удобными дефайнами для stm32f10x |
|
|
|
Feb 6 2013, 03:09
|
Местный
  
Группа: Участник
Сообщений: 222
Регистрация: 14-12-12
Из: новосибирск
Пользователь №: 74 845

|
например я вот такие сделал : CODE #define enable_clock(port) RCC->APB2ENR|=RCC_APB2ENR_IOP##port##EN // включение тактирования порта
#define set_pin(port,bit) GPIO##port## -> ODR |= GPIO_ODR_ODR##bit // установить на порте 1 #define clear_pin(port,bit) GPIO##port## -> ODR &= ~ GPIO_ODR_ODR##bit // установить на порте 0 #define test_pin(port,bit) GPIO##port## -> ODR &= GPIO_ODR_ODR##bit // возвращает истинное состояние на выводе ножки порта
//vvvvvvvvvvv Задаём направление и максимальную частоту работы портов MODE[bit1,bit0] vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv #define set_in(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //00: Input mode (reset state) - порт работает на вход, устанавливается по умолчанию после ресета #define set_out_10MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //01: Output mode, max speed 10 MHz. #define set_out_2MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //10: Output mode, max speed 2 MHz. #define set_out_50MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //11: Output mode, max speed 50 MHz. //если биты портов 0-7 то half=L //если биты портов 8-15 = то half=H // в регистре GPIOX_CR(L/H) меняет биты MODEx (режимы работы x ножки порта X) // Пример использования: // set_in(D,L,7); // устанавливает порт D.7 как вход // set_out_10MHz(D,L,7); //устанавливает порт D.7 как выход с максимальной частотой 10 Мгц. // set_out_2MHz(D,L,7); // set_out_50MHz(D,L,7); //^^^^^^^^^^^^ Задаём направление и максимальную частоту работы портов ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Сообщение отредактировал IgorKossak - Feb 7 2013, 18:53
Причина редактирования: форматирование
|
|
|
|
|
Feb 6 2013, 04:12
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
хм.... И что-ж тут удобного???  Во-первых - неудобно, во-вторых - баги в каждом макросе. Вот вам для примера мои аналогичные макросы, для управления пинами GPIO (NXP). Найдите отличия и поймите где баги: Код #define Pval2(port, pin) (GPIO[port].PIN >> (pin) & 1) #define Pclr2(port, pin) (GPIO[port].CLR = 1U << (pin)) #define Pset2(port, pin) (GPIO[port].SET = 1U << (pin)) #define Pval(port_pin) Pval2(port_pin) #define Pclr(port_pin) Pclr2(port_pin) #define Pset(port_pin) Pset2(port_pin) #define PORT2(port, pin) port #define PIN2(port, pin) pin #define PORT(port_pin) PORT2(port_pin) #define PIN(port_pin) PIN2(port_pin)
#define PIN_RF_RST 2, 3 //порт, пин #define PIN_KEY1 1, 0 #define PIN_WDI 1, 9
//использование: Pset(PIN_RF_RST); //установить в '1' Pclr(PIN_WDI); //установить в '0' if (Pval(PIN_KEY1)) { ... }
struct { u8 port, pin; } static const t[] = {{PORT(PIN_WDI), PIN(PIN_WDI)}, ...};
Pset2(t[0].port, t[0].pin);
|
|
|
|
|
Feb 6 2013, 05:19
|

Местный
  
Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631

|
Ну, раз для STM32F1, т.е. для контроллера с ядром Cortex M3, то полезны макросы для побитовой работы с регистрами: CODE /*Побитовая адресация:*/ #define PERIPH_BB_ADDRESS(PeriphAddress,RegisterOffset,NumBit) (((u32)((u32)PeriphAddress+RegisterOffset)- 0x40000000)*32+(NumBit)*4+0x42000000)
#define RELAY5 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOA,0x0C,2))) /*output PA2*/ #define RELAY6 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOB,0x0C,2))) /*output PB2*/ #define LEDS_LED1 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOE,0x0C,5))) /*output PE5*/ #define LEDS_LED2 (Pin)(*((Pin*) PERIPH_BB_ADDRESS(GPIOE,0x0C,4))) /*output PE4*/
/*И по месту просто использовать так:*/ LEDS_LED1 = 1; RELAY6 =0; Но при использовании оптимизации лучше использовать следующее: CODE #define RS485_ADDRESS_FE PERIPH_BB_ADDRESS(RS485_USART,USART_SR,1) /*адрес флага FE*/ #define RS485_ADDRESS_NE PERIPH_BB_ADDRESS(RS485_USART,USART_SR,2) /*адрес флага NE*/
extern vu32 RS485_FE __attribute__((at(RS485_ADDRESS_FE))); extern vu32 RS485_NE __attribute__((at(RS485_ADDRESS_NE)));
/*И по месту:*/ if( RS485_FE ) abc = bcd+cda;
Сообщение отредактировал IgorKossak - Feb 7 2013, 18:50
Причина редактирования: форматирование
|
|
|
|
|
Feb 7 2013, 14:11
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(jcxz @ Feb 7 2013, 16:34)  У меня вызовы макросов типа установить/обнулить/проинвертировать/... пин GPIO одинаковы для разных процессоров, что часто позволяет переносить исходники с одного CPU на другой другого производителя с минимальными модификациями (или вообще без оных). Вы коснулись хорошей темы, а именно наилучшего API для контроллеров. Его, ессно, не существует, но есть вещи, которые хорошо себя зарекомендовали и на разных платформах. Например вызов инициализации UART в виде Код uint_fast8_t async_config( const uint_fast8_t number, //номер порта const uint_fast32_t baud, // скорость const uint_fast8_t bits, // число бит const char parity, //'E'-even, 'O'-odd, 'N'-none const uint_fast8_t stops // 1, 2 для полутора - нет ); Но uart - это просто. Потом, с SPI более менее получается - там где нет аппаратной поддержки, например, DMA, - включается эмуляция оного. А вот с таймерами - уже засада. Или с АЦП. А дергать пинами - у меня лично такого уровня просто нет. У меня в board.h есть например "включить реле", а set-reset какой-то сферический пин - нету.
|
|
|
|
|
Feb 8 2013, 02:27
|
Местный
  
Группа: Участник
Сообщений: 222
Регистрация: 14-12-12
Из: новосибирск
Пользователь №: 74 845

|
CODE #define uchar unsigned char // VVVVVVVVVVVVVVVVVVVVV Работа с портами VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV #define enable_clock(port) RCC->APB2ENR|=RCC_APB2ENR_IOP##port##EN // включение тактирования порта #define pin_on(port,bit) GPIO##port## -> ODR |= GPIO_ODR_ODR##bit // установить на порте 1 #define pin_off(port,bit) GPIO##port## -> ODR &= ~ GPIO_ODR_ODR##bit // установить на порте 0 #define pin_test(port,bit) GPIO##port## -> ODR &= GPIO_ODR_ODR##bit // возвращает истинное состояние на выводе ножки порта
//vvvvvvvvvvv Конфигурируем порты: направление и максимальная частота работы портов vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv #define set_in(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //00: Input mode (reset state) - порт работает на вход, устанавливается по умолчанию после ресета #define set_out_10MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_0); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //01: Output mode, max speed 10 MHz. #define set_out_2MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_0) //10: Output mode, max speed 2 MHz. #define set_out_50MHz(port,half,bit) GPIO##port##->CR##half##&=~(GPIO_CR##half##_MODE##bit##_1); GPIO##port##->CR##half##|=(GPIO_CR##half##_MODE##bit##_1) //11: Output mode, max speed 50 MHz. //если пин порта 0-7 то half=L //если пин порта 8-15 = то half=H // в регистре GPIOX_CR(L/H) меняет биты MODEx (режимы работы x ножки порта X) // Пример использования: // set_in(D,L,7); // устанавливает порт D.7 как вход // set_out_10MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 10 Мгц. // set_out_2MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 2 Мгц. // set_out_50MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 50 Мгц. //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #define pin_config(port,half,pin,b1,b0) GPIO##port##->CR##half##&=~(GPIO_CR##half##_CNF##pin##_0);GPIO##port##->CR##half##&=~(GPIO_CR##half##_CNF##pin##_1) ; // конфигурация регистра CNF
//vvvvvvvvvvv меняем настройки портов настроенных на выход, general/alternativ и push-pull/open-drain vvvvvvvvvvvvvvv #define general_push_pull(port,half,pin) pin_config(##port##,##half##,##pin##,0,0)//00: set port as General purpose output push-pull #define general_open_drain(port,half,pin) pin_config(##port##,##half##,##pin##,0,1)//01: set port as General purpose output Open-drain #define alternate_push_pull(port,half,pin) pin_config(##port##,##half##,##pin##,1,0)//10: set port as Alternate function output Push-pull #define alternate_open_drain(port,half,pin) pin_config(##port##,##half##,##pin##,1,1)//11: set port as Alternate function output Open-drain // пример использования: //out_general_push_pull(D,L,7); //set port D, pin7 as General purpose output push-pull //out_general_open_drain(D,L,7); //set port as General purpose output push-pull //out_alternate_push_pull(D,L,7); //set port as alternate output push-pull //out_alternate_open_drain(D,L,7);//set port as alternate output push-pull //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
//vvvvvvvvvvv меняем настройки портов настроенных на вход vvvvvvvvvvvvvvv #define input_analog(port,half,pin) pin_config(##port##,##half##,##pin##,0,0)//00: set port as Analog mode #define input_float(port,half,pin) pin_config(##port##,##half##,##pin##,0,1)//01: set port as Floating input (reset state) #define input_pull_up_down(port,half,pin) pin_config(##port##,##half##,##pin##,1,0)//10: set port as Input with pull-up / pull-down // пример использования: //input_analog(port,half,pin);// set port as Analog mode //input_float(port,half,pin);// set port as Floating input (reset state) //input_pull_up_down(port,half,pin); //set port as Input with pull-up / pull-down //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ CODE enable_clock(D);//включение тактирования порта set_out_2MHz(D,L,7); //устанавливает порт D.x как выход с максимальной частотой 2 Мгц. general_push_pull(D,L,7); //set port as General purpose output push-pull
while (1) { if (pin_test(D,7)) { pin_off(D,7); } else { pin_on(D,7); } for (d=0; d<1000000; ++d){e ++;}; теперь програмка моргания светодиодом выглядет высокоуровневее
Сообщение отредактировал super_puper - Feb 8 2013, 03:47
|
|
|
|
|
Feb 8 2013, 05:29
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(super_puper @ Feb 8 2013, 06:48)  никто не написал ещё? Бросьте фигнёй заниматься... займитесь лучше чем-то полезным...
|
|
|
|
|
Feb 8 2013, 06:23
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(super_puper @ Feb 8 2013, 06:27)  теперь програмка моргания светодиодом выглядет высокоуровневее Ну, ну... Почитайте этот же код через этак пару месяцев, занявшись в это время другим проектом. Уверен, что хрен поймете, что это за абстрактные "D", 7, что они делают в проге. Нормальный высокоуровневый код НЕ должен выглядеть, как куча дефайнов поверх других дефайнов. Не это - его цель. Если уже делаете обертки, то они должны отражать суть программы, ее действия, а вовсе не суть самой этой обертки - избавиться от чужого говнокода. Я тоже пытался что-то вразумительное сделать поверх либ от ST, но в итоге из всего осталось только - пинодрыгание. Остальное сделать удобным под все линейки процев, увы, нереально. По сути, ST-либы реально ускоряют разработку, а в последствии переписать "быстрые" куски кода в обход библиотеки - это уже оптимизация, которая, зачастую, не так уж и обязательна. Например, мне приходилось "разворачивать" и оптимизировать код этих либ в обработчиках прерываний CAN, т.к. это реально ускорило работу системы... Чтобы не быть голословным, поделюсь своим вариантом обертки для пинов (STM32L). Базовый класс пина: Код class PinBase { public: PinBase(GPIO_TypeDef * port, UNSIGNED8 pinIndex) { this->port = port; this->pinIndex = pinIndex; switch ((UNSIGNED32)(this->port)) { case ((UNSIGNED32)GPIOA): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); break; case ((UNSIGNED32)GPIOB): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); break; case ((UNSIGNED32)GPIOC): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); break; case ((UNSIGNED32)GPIOD): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); break; case ((UNSIGNED32)GPIOE): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); break; case ((UNSIGNED32)GPIOH): RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOH, ENABLE); break; default : break; } disablePullUpAndPullDown(); }
void setAsInput(void) // MODER = 0 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } void setAsOutput(void) // MODER = 1 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2)); }
typedef UNSIGNED8 AlternativeFunction; void setAsAlternative(AlternativeFunction function) // MODER = 2 { port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x02) << (pinIndex * 2)); if (pinIndex < 8) { port->AFR[0] &= ~(((UNSIGNED32)0x0F) << (pinIndex * 4)); port->AFR[0] |= (((UNSIGNED32)function & 0x0F) << (pinIndex * 4)); } else { port->AFR[1] &= ~(((UNSIGNED32)0x0F) << ((pinIndex - 8) * 4)); port->AFR[1] |= (((UNSIGNED32)function & 0x0F) << ((pinIndex - 8) * 4)); } } void setAsAnalogInput(void) // MODER = 3 { disablePullUpAndPullDown(); port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->MODER |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } void setAsPushPull(void) { port->OTYPER &= ~(1 << pinIndex); } // OTYPER = 0 void setAsOpenDrain(void) { port->OTYPER |= (1 << pinIndex); } // OTYPER = 1 void setOutputSpeed400kHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } // OSPEEDR = 0 void setOutputSpeed2MHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } // OSPEEDR = 1 void setOutputSpeed10MHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x02) << (pinIndex * 2)); } // OSPEEDR = 2 void setOutputSpeed40MHz(void) { port->OSPEEDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->OSPEEDR |= (((UNSIGNED32)0x03) << (pinIndex * 2)); } // OSPEEDR = 3 void disablePullUpAndPullDown(void) { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x00) << (pinIndex * 2)); } // PUPDR = 0 void enablePullUp(void) { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x01) << (pinIndex * 2)); } // PUPDR = 1 void enablePullDown(void) { port->PUPDR &= ~(((UNSIGNED32)0x03) << (pinIndex * 2)); port->PUPDR |= (((UNSIGNED32)0x02) << (pinIndex * 2)); } // PUPDR = 2 void lock(void) { volatile UNSIGNED32 tempRegister = ((UNSIGNED32)1 << pinIndex); port->LCKR = tempRegister | (1 << 16); // Set LCKK bit port->LCKR = tempRegister; // Reset LCKK bit port->LCKR = tempRegister | (1 << 16); // Set LCKK bit tempRegister = port->LCKR; // Read LCKK bit tempRegister = port->LCKR; // Read LCKK bit }
private: volatile GPIO_TypeDef * port; volatile UNSIGNED8 pinIndex; }; Шаблон класса пина: Код template <UNSIGNED32 PORT_ADDR, UNSIGNED8 PIN_INDEX> class Pin : public PinBase { public: Pin(void) : PinBase(((GPIO_TypeDef*)PORT_ADDR), PIN_INDEX) { setToLow(); }
inline void setToHigh(void) __attribute__((always_inline)) { ((GPIO_TypeDef*)PORT_ADDR)->BSRRL = (((UNSIGNED32)1) << PIN_INDEX); } inline void setToLow(void) __attribute__((always_inline)) { ((GPIO_TypeDef*)PORT_ADDR)->BSRRH = (((UNSIGNED32)1) << PIN_INDEX); } inline bool isHigh(void) const __attribute__((always_inline)) { return (((((GPIO_TypeDef*)PORT_ADDR)->IDR) & (((UNSIGNED32)1) << PIN_INDEX)) != 0); } inline bool isLow(void) const __attribute__((always_inline)) { return (((((GPIO_TypeDef*)PORT_ADDR)->IDR) & (((UNSIGNED32)1) << PIN_INDEX)) == 0); } }; Увы, в компиляторе KEIL нельзя в качестве параметров шаблонов использовать указатели, хотя стандарт C++ это вполне допускает. Поэтому приходится его обманывать: Код #define PORTA (((UNSIGNED32)GPIOA)) #define PORTB (((UNSIGNED32)GPIOB)) #define PORTC (((UNSIGNED32)GPIOC)) ..... Ну, и пример использования (внешний акселерометр с программным SPI). H-файл: Код // ACCELEROMETER #define PORT_ACCEL_CS (PORTB) #define PIN_ACCEL_CS (15)
#define PORT_ACCEL_SCK (PORTB) #define PIN_ACCEL_SCK (14)
#define PORT_ACCEL_MOSI (PORTB) #define PIN_ACCEL_MOSI (13)
#define PORT_ACCEL_MISO (PORTB) #define PIN_ACCEL_MISO (12)
#define PORT_ACCEL_INT (PORTB) #define PIN_ACCEL_INT (11)
..... ..... ....
class Accelerometer : public Singleton<Accelerometer> { .....
private: Pin<PORT_ACCEL_CS, PIN_ACCEL_CS> pinCS; Pin<PORT_ACCEL_SCK, PIN_ACCEL_SCK> pinSCK; Pin<PORT_ACCEL_MOSI, PIN_ACCEL_MOSI> pinMOSI; Pin<PORT_ACCEL_MISO, PIN_ACCEL_MISO> pinMISO; Pin<PORT_ACCEL_INT, PIN_ACCEL_INT> pinINT; ..... }; CPP-файл: Код void Accelerometer::initialize(void) { .... pinCS.setAsOutput(); pinCS.setAsPushPull(); pinCS.setOutputSpeed10MHz(); pinCS.setToLow();
.... pinMISO.setAsInput(); pinMISO.enablePullDown();
pinINT.setAsInput(); pinINT.enablePullDown(); .... }
void Accelerometer::writeRegister(UNSIGNED8 address, UNSIGNED8 value) { pinCS.setToLow(); pinSCK.setToLow();
for (UNSIGNED8 bit = 8; bit > 0; --bit) { if ((address & 0x80) != 0) pinMOSI.setToHigh(); else pinMOSI.setToLow(); pinSCK.setToHigh(); address = address << 1; pinSCK.setToLow(); }
for (UNSIGNED8 bit = 8; bit > 0; --bit) { if ((value & 0x80) != 0) pinMOSI.setToHigh(); else pinMOSI.setToLow(); pinSCK.setToHigh(); value = value << 1; pinSCK.setToLow(); }
pinSCK.setToHigh(); pinCS.setToHigh(); } p.s. Буду рад, если мои идеи кому-то еще пригодятся
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Feb 8 2013, 11:44
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(_Pasha @ Feb 7 2013, 18:11)  А вот с таймерами - уже засада. Или с АЦП. Ну а в чем именно засада? Если хорошо продумать имена функций API, плюс самодисциплина, то работать будет для любого проца, с минимальными изменениями, хоть для AVR, хоть для STM32. CODE //////////////////////////////////////////////////////////////////////////////// // USER INTERFACE ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void BspUifInit( void ) { //////////////////////////////////////////////////////////////////////////// McuTmrInit( BSP_TMR_UIF );
McuTmrConfig( BSP_TMR_UIF, MCU_TMR_TCKINT_DIV_1, MCU_TMR_PRELOAD_ENABLE, //MCU_TMR_MODE_UP_NONSTOP, MCU_TMR_MODE_UP_ONESHOT, MCU_TMR_UPDT_RQST_SRC_CNT_ONLY );
McuTmrPrescalerSet( BSP_TMR_UIF, BSP_MCLK_HZ / BSP_TMR_UIF_CLK_HZ );
McuTmrPeriodSet( BSP_TMR_UIF, BSP_TMR_UIF_PERIOD_LONG_TCKS );
//////////////////////////////////////////////////////////////////////////// McuTmrCompareConfig( BSP_TMR_UIF, BSP_TMR_CHNL_LEDR, MCU_TMR_CMPR_CLEAR_BY_ETRF_DISABLE, MCU_TMR_CMPR_MODE_PWM_POSITIVE, MCU_TMR_CMPR_PRELOAD_DISABLE, MCU_TMR_CMPR_FAST_OUTPUT_DISABLE );
McuTmrCompareConfig( BSP_TMR_UIF, BSP_TMR_CHNL_LEDB, MCU_TMR_CMPR_CLEAR_BY_ETRF_DISABLE, MCU_TMR_CMPR_MODE_PWM_POSITIVE, MCU_TMR_CMPR_PRELOAD_DISABLE, MCU_TMR_CMPR_FAST_OUTPUT_DISABLE );
McuTmrOutputConfig( BSP_TMR_UIF, BSP_TMR_CHNL_LEDR, MCU_TMR_OUT_P_NON_INVERTED, MCU_TMR_OUT_N_DISABLE );
McuTmrOutputConfig( BSP_TMR_UIF, BSP_TMR_CHNL_LEDB, MCU_TMR_OUT_P_NON_INVERTED, MCU_TMR_OUT_N_DISABLE );
McuTmrOutputsEnable( BSP_TMR_UIF );
McuTmrEnable( BSP_TMR_UIF );
//////////////////////////////////////////////////////////////////////////// McuPinConfig( BSP_PIN_LED_RED, MCU_PIN_MODE_OUT_PP_AF_2MHz ); McuPinConfig( BSP_PIN_LED_BLU, MCU_PIN_MODE_OUT_PP_AF_2MHz ); McuPinConfig( BSP_PIN_BEEP, MCU_PIN_MODE_OUT_PP_AF_2MHz ); }
Сообщение отредактировал IgorKossak - Feb 8 2013, 12:42
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Feb 8 2013, 12:05
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
разницы между set_port("D","7") и PORTD->OUT |= (1<<7) нету, что вы одно слово заменили на другое, а понятную всем кто занимается программированием операцию заменили словом, это все пустое, это шелуха которая не нужна.
Определитесь зачем вы это делаете? Если чтобы самому было удобно читать, то потратите времени больше чем на привыкание к определенному семейству процов. Увеличить читаемость кода? не увеличите. Добавить гибкости и переносимости коду? - сто пудово нет. В новой плате поменяют ножку на которой висел диод - и до свидания, или же правда через год откроете свой код и будите искать кто зажег диод.
если вы в своей программе сделаете TEST_LED_ON (PORTD->OUT |= (1<<7)) TEST_LED_OFF (PORTD->OUT &= (~(1<<7)))
вот это уже имеет смысл. 1. понятно что происходит. 2. при смене проца или переразводке платы, меняете макрос и все едет дальше как и было. Логика програмы сохраняется функционал остается.
Я лично всегда делю проект на то что зависит от проца и конкретной схемы и что не зависит.
В вашем примере с диодом, я бы сделал макрос на мигание как показано выше в отдельном файле тестовые диоды или что-то типа того. объявил бы константу #define TEST_LED_PIN (1<<7)
а порт бы инициализировал в общей для всего проца функции PORTD->DIR |= TEST_LED_PIN;
потому что изменений при смене проца или разводки в данном случае столько же сколько при добавленных макросах инициализации и так далее, но макросы писать не надо, то есть выигрыш имеется.
|
|
|
|
|
Feb 8 2013, 12:07
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Tahoe @ Feb 8 2013, 15:44)  Ну а в чем именно засада? Все правильно, только пространство методов надо сокращать до предела. Я так понимаю, "хоть на AVR" - это означает, что там, где фича не отлита в железе, она либо тупо не поддерживается либо включается программная эмуляция, там где не внапряг по ресурсам. И вот с таймерами - муки выбора - либо как у Вас, либо конкретно по областям применения - энкодер, хренсним, на авр зацепим прерывание, на пиках моторных - железный, на STM -железный. ШИМ для силовухи - то же самое. Каскадирование - там понятно, что эмуляция рулит. Непонятна методология, может, карты какие-то ассоциативные составлять? Уж очень много вариантов. С периферией очевидные вещи- {open, close, ioctl} - это легко, за счет инлайнов можно более не лезть в ДШ чтобы вспомнить, на какой шине оно сидит да что куда ремапится. Еще делал типа get_pending_clock(void *sfr) - для периферии вернуть тактовую частоту той шины, где она сидит. Тоже инлайн. Еще типа блочного устройства, но без хендлов dma_stream(void *dst, void *src, size_t size, size_t element_size) - чтобы само рулило кто у нас источник, кто приемник, накладные расходы есть. Цель мсм такая: чтобы можно было быстро что-то опробовать, без лишней писанины, но и без сильной специализации. и не лазать в книжку каждую секунду. Может, попробуем какие-то общие свойства выделить?
Сообщение отредактировал _Pasha - Feb 8 2013, 12:10
|
|
|
|
|
Feb 8 2013, 12:29
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(_Pasha @ Feb 8 2013, 16:07)  Я так понимаю, "хоть на AVR" - это означает, что там, где фича не отлита в железе, она либо тупо не поддерживается либо включается программная эмуляция, там где не внапряг по ресурсам. Примерно так. Только никакой эмуляции, как правило, нет. Если фичи нет, значит ее нет, "и никакие лекции не изменят этого соотношения сил, если каждый индивидуум в отдельности не будет постоянно тренироваться в шашк... то есть я хотел сказать в шахматы" (с).  Цитата(_Pasha @ Feb 8 2013, 16:07)  И вот с таймерами - муки выбора - либо как у Вас, либо конкретно по областям применения - энкодер, хренсним, на авр зацепим прерывание, на пиках моторных - железный, на STM -железный. ШИМ для силовухи - то же самое. Каскадирование - там понятно, что эмуляция рулит. Никаких мук. Даже странно, что этот вопрос поднимает тот, кто пишет на плюсах ( если не ошибаюсь  ). Есть объект, у него есть свойства. Если объект "таймер", то причем тут энкодер? Энкодер, это отдельная сущность, совершенно отдельный объект. Как частный случай, подключеный с помощью "таймер". Ничем не отлиается, например, от работы с внешней ЕЕПРОМ. Абсолютно не важно, как эта ЕЕПРОМ подключена, через объект "SPI" или объект "I2C", адресация адресация и размерность данных самой ЕЕПРОМ от этого не меняются. Цитата(_Pasha @ Feb 8 2013, 16:07)  Может, попробуем какие-то общие свойства выделить? Так см. мой пример, там именно по этому принципу сделано. Например, у таймера может быть, а может не быть канала Compare. Таймеру может требоваться, а может не требоваться инициализация ( в основном, как и другим объектам, включить/выключить системный клок, в AVR или MSP430 это не требуется ). Потому все и разбито на блоки. Кроме того, не следует пытаться запихнуть в AVR-таймер все фичи, доступные STM32-таймеру. Описания свойств таймеров у меня не отличаются, просто среди аргументов McuTmrConfig() какие-то есть, каких-то нет, это не трагедия. Еще предостерегу от попытки написать супер-пупер универсальный код, что бы прям можно было переносить копи-пастом из проекта AVR в проект LPC17xx. Этого не требуется и лишь усложнит дело. Достаточно просто иметь единообразные названия функций, с максимально типизированными аргументами.
|
|
|
|
|
Feb 8 2013, 13:32
|
Местный
  
Группа: Свой
Сообщений: 209
Регистрация: 6-01-12
Пользователь №: 69 197

|
Цитата(Golikov A. @ Feb 8 2013, 16:05)  разницы между set_port("D","7") и PORTD->OUT |= (1<<7) нету, что вы одно слово заменили на другое, а понятную всем кто занимается программированием операцию заменили словом, это все пустое, это шелуха которая не нужна.
Определитесь зачем вы это делаете? Я пытаюсь сделать чуть по-другому в bsp_board_def.h определяю ножку в виде дефайна, а затем ставлю SET_PIN(LED_PIN) и CLEAR_PIN(LED_PIN) соотвественно получается некоторая "ПЛАТОПЕРЕНОСИМОСТЬ"
--------------------
|
|
|
|
|
Feb 8 2013, 13:50
|
Знающий
   
Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231

|
Сам юзаю StdLib от STM, для инициализации вполне нормальная вещь (инициализация делается один раз скорости хватит даже на 1МГц работы), а для обработки использую уже регистры найденные в той же StdLib. Но пришла мысля, если эти же ф-ции для чтения записи периферии, перемести в H файл и заинлайнить, то компилятор должен их встроить, там где их вызывают, т.е. получим макс. быстродействие равное записи напрямую в регистр. например ф-ции из С файла Код uint16_t USART_ReceiveData(USART_TypeDef* USARTx) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); /* Receive Data */ return (uint16_t)(USARTx->DR & (uint16_t)0x01FF); } делаем в h файле только Код inline uint16_t USART_ReceiveData(USART_TypeDef* USARTx) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); /* Receive Data */ return (uint16_t)(USARTx->DR & (uint16_t)0x01FF); }
|
|
|
|
|
Feb 8 2013, 13:52
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(SyncLair @ Feb 8 2013, 17:32)  ставлю SET_PIN(LED_PIN) и CLEAR_PIN(LED_PIN) соотвественно получается некоторая "ПЛАТОПЕРЕНОСИМОСТЬ" Тут уже объясняли... что подобное не несёт никакой смысловой нагрузки... В случае малейшей ошибки, после двух-трёх бессоных ночей, у вас глаза откажут от всех этих повсеместных SET_PIN, CLEAR_PIN, SET_BIT и CLEAR_BIT... а вместе с ними и мозг...
|
|
|
|
|
Feb 8 2013, 14:17
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Rash @ Feb 8 2013, 16:50)  перемести в H файл и заинлайнить, то компилятор должен их встроить, там где их вызывают, т.е. получим макс. быстродействие равное записи напрямую в регистр. Совершенно ага! Если в параметрах будет const (разрулить возможные обращения по записи) - то на выходе получим минимум миниморум. Посмотрите на lib_at91samxxxxxxx.hЦитата(Tahoe @ Feb 8 2013, 15:29)  Никаких мук. Даже странно, что этот вопрос поднимает тот, кто пишет на плюсах ( если не ошибаюсь  ). Не-не, я на плюсах ни-ни Как только умрет последний PIC18, - тогда да.
|
|
|
|
|
Feb 8 2013, 14:49
|
Знающий
   
Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231

|
Цитата(_Pasha @ Feb 8 2013, 18:17)  Совершенно ага! Если в параметрах будет const (разрулить возможные обращения по записи) - то на выходе получим минимум миниморум. Посмотрите на lib_at91samxxxxxxx.h не понятно почему так не сделана либа STM, и к чему тогда возникающие периодические споры про корявую либу СТМ или какие то хитрые дефайны с регистрами, если всего то надо разок потратить время и перебить функции на инлайн.
|
|
|
|
|
Feb 8 2013, 15:00
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Rash @ Feb 8 2013, 17:49)  если всего то надо разок потратить время и перебить функции на инлайн. И некоторые из них просто станут неработоспособными... если не ошибаюсь... SPI, например...
|
|
|
|
|
Feb 8 2013, 15:08
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Rash @ Feb 8 2013, 17:49)  не понятно почему так не сделана либа STM Это вроде как логическое продолжение CMSIS. Потом, там MISRA2004 проехалась, потом - операции с битовыми полями априори неизвестно как себя ведут на разных компилерах, иначе все было бы попроще. Всему есть причины. Либой для АТ91 тоже не очень приятно пользоваться, я имею ввиду длинные префиксы в именах. -- Как альтернатива - Coocox"овые либы... Но там другая сторона медали: в STшных - инициализация через структуру, зато функции с 2-мя параметрами и повторное использование, в кокосовых - функции с большим числом параметров. Хрен редьки, как говорится. Цитата(HHIMERA @ Feb 8 2013, 18:00)  И некоторые из них просто станут неработоспособными... если не ошибаюсь... SPI, например... Ухты! Где?
|
|
|
|
|
Feb 8 2013, 15:33
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(_Pasha @ Feb 8 2013, 19:08)  Ухты! Где? Точно уже не припомню... Зато точно помню... что желание инлайнить весь этот колхоз, почему-то, не возникает...
|
|
|
|
|
Feb 8 2013, 18:18
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(Rash @ Feb 8 2013, 19:33)  Что удобно, что там объявлены большинство регистров, иногда даташит даже открывать не приходится, просто надо как и всё под себя с оптимизировать минимальными ресурсами. Даже имена им менять не нужно. Вот только есть одна неприятность. Учитывая, как у ST оъявлены биты, использовать bitband не получится. Остается уповать на компилер, но тот же IAR не торопится задействовать bitband регион.
|
|
|
|
|
Feb 8 2013, 19:05
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(_Pasha @ Feb 8 2013, 22:29)  выигрыш не особо просматривается... кроме атомарности. А прочего от него особо и не требуется. Ну и, как обычно, смотреть надо на проблему в целом, а не на стоимость отдельных частей. Использование bitband позволит избавиться от ENTER_CRITICAL()/EXIT_CRITICAL(). Ну и как теперь, выигрыш "просмотрелся"(с) ?
|
|
|
|
|
Feb 8 2013, 19:48
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(adnega @ Feb 8 2013, 23:14)  А, вроде, в новеньких F3 вход-вывод не попадает в bit-band?... Bitband, это фича ядра, не контроллера. Производители ядра говорят что такая фича есть, хоть и опционально. ST тоже говорит, что есть. См. STM32F3xxx and STM32F4xxx Cortex-M4 programming manual, "2.2.5 Bit-banding".
|
|
|
|
|
Feb 9 2013, 02:03
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(_Pasha @ Feb 9 2013, 03:02)  А конфигурацию пинов зачем атомарно менять? Я даже такой ситуёвины представить не могу Б-г с ней, с атомарностью. "Ситуевину представить"(с) - "легко, смеясь"(с) : как я налетел с ремапом. А именно: Цитата(Tahoe @ Jul 20 2012, 12:28)  А в библиотеках от ST просто в наглую подставляется константа. И совсем не факт, что она совпадет с тем, как ранее настроил программер. А теперь, хотелось бы услышать любой другой способ, кроме bit-band, позволяющий безопасно установить ремап-биты.
|
|
|
|
|
Feb 9 2013, 07:13
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(_Pasha @ Feb 9 2013, 03:02)  А смысл работы GPIO в означенном регионе? Если и так чтобы установить/сбросить атомарно - все есть. А конфигурацию пинов зачем атомарно менять? Я даже такой ситуёвины представить не могу Написал библиотеку для работы с UART. При инициализации передаем адрес бита ножки GPIO, отвечающую за передачу в RS-485. Как быть теперь? Применить свою виртуальную адресацию битов портов? По библиотеке для этих целей могу "протащить" лишь одну 32-битную переменную.
|
|
|
|
|
Feb 9 2013, 08:10
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Tahoe @ Feb 9 2013, 01:05)  Использование bitband позволит избавиться от ENTER_CRITICAL()/EXIT_CRITICAL(). Ну и как теперь, выигрыш "просмотрелся"(с) ?  С чего-бы это?? Только разве что в одном конкретном случае - если область, которую надо защитить критической секцией, ограничивается одним словом и только на одну операцию (укладывающуюся в одну команду ASM). Всё то же самое (и даже гораздо больше) решается с помощью LDREX/STREX. Ну-ка реализуйте мне пожалуйста с помощью битбандинга стандартную атомарную операцию CompareAndExchange? А с помощью LDREX/STREX это делается легко (или с помощью ENTER_CRITICAL()/EXIT_CRITICAL()). Цитата(_Pasha @ Feb 9 2013, 12:22)  А в RMW-операциях можно налететь на грабли и по другому - просто записав битик туда, куда не нужно, - помечено как reserved биты, а каким образом оно себя проявить может - хз. Думаю - вряд-ли. Скорей всего такие биты прочитаются с тем значением, которое туда можно безопасно записывать. Цитата(adnega @ Feb 9 2013, 13:13)  Написал библиотеку для работы с UART. При инициализации передаем адрес бита ножки GPIO, отвечающую за передачу в RS-485. Как быть теперь? Применить свою виртуальную адресацию битов портов? По библиотеке для этих целей могу "протащить" лишь одну 32-битную переменную. А что - так трудно упаковать номер бита в порту в младшие 5 бит, а номер порта - в старшую часть 32бит? Пока не выпустили корпуса с 2^32 ног это вроде не должно составлять проблем... Можно даже с помощью макросов сделать это красиво, а-ля: Код //определения пинов: #define PIN_RS485_1_OE 1, 25 #define PIN_RS485_2_OE 0, 26 // #define RS485init2(..., port, pin) RS485_Init(..., (port) << 5 | (pin)) #define RS485init(..., port_pin) RS485init2(..., port_pin) void RS485_Init(..., uint pinOE) { ... } //Вызов: RS485init(..., PIN_RS485_1_OE); RS485init(..., PIN_RS485_2_OE); Если Вам больше нравится именование портов не через 0,1,2..., а через A,B,C,... то нетрудно выполнить макрозамену: Код #define PIN_RS485_1_OE B, 25 #define PIN_RS485_2_OE A, 26 // #define PORTA 0 #define PORTB 1 ... #define concatAB_(a, b) a##b #define concatAB(a, b) concatAB_(a, b) #define RS485init2(..., port, pin) RS485_Init(..., concatAB(PORT, port) << 5 | (pin)) ...
|
|
|
|
|
Feb 9 2013, 10:23
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(_Pasha @ Feb 9 2013, 10:22)  А в RMW-операциях можно налететь на грабли и по другому - просто записав битик туда, куда не нужно, - помечено как reserved биты, а каким образом оно себя проявить может - хз. Можно. Но я же спросил не о новых проблемах, а о решении конкретной и реально существующей. Так кроме bitband, ещё как-то можно корректно и безопасно сделать ремап? Кстати, даже с bitband тоже не все так просто оказалось, но в итоге решилось.
|
|
|
|
|
Feb 9 2013, 11:02
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Feb 9 2013, 13:23)  Можно. Но я же спросил не о новых проблемах, а о решении конкретной и реально существующей. Нет там никакой проблемы с ремап... есть временное недопонимание/трактование по своему... Это всё из ряда: Цитата Кстати, даже с bitband тоже не все так просто оказалось, но в итоге решилось.
|
|
|
|
|
Feb 9 2013, 11:23
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(jcxz @ Feb 9 2013, 12:10)  А что - так трудно упаковать номер бита в порту в младшие 5 бит, а номер порта - в старшую часть 32бит? Пока не выпустили корпуса с 2^32 ног это вроде не должно составлять проблем... Можно даже с помощью макросов сделать это красиво, а-ля: Сравните с существующей реализацией: Код if(con->txena) *con->txena = TX_ON; и во что она скомпилируется. Или вот такое: Код WORKLED_bit ^= 1; В этом плане GPIO на bit-band очень удобен. При этом "цена вопроса" - 6кБ в соответствующем регионе!
|
|
|
|
|
Feb 9 2013, 12:47
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(HHIMERA @ Feb 9 2013, 15:02)  Нет там никакой проблемы с ремап... есть временное недопонимание/трактование по своему...
Это всё из ряда: Ребят, что в той ветке, что сейчас, вы оба просто не вникли в суть проблемы. поэтому ее не видите. Придется повторить ещё раз. Есть регистр AFIO_MAPR, в котором есть три write only бита SWJ_CFG[2:0]. Результат чтения из них - не определен. Как модифицировать произвольный бит этого регистра, сохранив ранее установленные в SWJ_CFG[2:0] значения? Учитывая, что прочитать SWJ_CFG[2:0] невозможно. Причем это не высосано из пальца, я реально налетел на эту проблему, когда понадобился remap SPI1, а биты SWJ_CFG были уже установлены. Тот редкий случай, когда получу удовольствие, если меня ткнут носом. Вот только шансов на это нет.
|
|
|
|
|
Feb 9 2013, 14:03
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Feb 9 2013, 16:47)  Ребят, что в той ветке, что сейчас, вы оба просто не вникли в суть проблемы. поэтому ее не видите. Придется повторить ещё раз.
Есть регистр AFIO_MAPR, в котором есть три write only бита SWJ_CFG[2:0]. Результат чтения из них - не определен. Как модифицировать произвольный бит этого регистра, сохранив ранее установленные в SWJ_CFG[2:0] значения? Учитывая, что прочитать SWJ_CFG[2:0] невозможно. А как вы думаете... как боролись с RMW в младших ПИКах, в которых не было регистра LAT ??? Создавали "фантомный" регистр... типа: Цитата(Golikov A. @ Feb 9 2013, 16:52)  запомнить значение битов в переменной%) И это не считалось проблемой... считалось - решением... Цитата Причем это не высосано из пальца, я реально налетел на эту проблему, когда понадобился remap SPI1, а биты SWJ_CFG были уже установлены. Тот редкий случай, когда получу удовольствие, если меня ткнут носом. Вот только шансов на это нет. Сколько налетал на "проблему" в STM32, столько раз сам и убеждался, что просто "не дочитал/не досмотрел/не угадал вариант неоднозначной трактовки"... ИМХО... Вся сложность STM32 - в его простоте... при широких возможностях...
Сообщение отредактировал HHIMERA - Feb 9 2013, 14:04
|
|
|
|
|
Feb 9 2013, 14:23
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(HHIMERA @ Feb 9 2013, 18:03)  И это не считалось проблемой... считалось - решением... С каких пор, вырезание гландов через анус, называется "решением"? И что тогда называть "костылём", если создание фантомного регистра - "решение". Реальное решение, это использовать bit-band. Вот это - действительно решение. А наплодить тонну фантомных регистров, создать прослойку для работы с ними и радоваться, что хоть как-то разрулили аппаратный недостаток... Философия Microchip/Microsoft в действии?  Цитата(HHIMERA @ Feb 9 2013, 18:03)  Сколько налетал на "проблему" в STM32, столько раз сам и убеждался, что просто "не дочитал/не досмотрел/не угадал вариант неоднозначной трактовки"... ИМХО... Вся сложность STM32 - в его простоте... при широких возможностях... Ну вот, опять общие слова - "вы не поняли", "вы не дочитали". Ну а конкретно-то можно? Что именно я "недочитал" и "не понял", касательно работы с AFIO_MAPR_SWJ_CFG? Может наоборот, это вы оба недочитали, раз не используете bit-band, а заводите какую-то левую переменную в памяти? Да чего уж скромничать, продублируем все регистры ядра и периферии в памяти. Вот будет веселье.
|
|
|
|
|
Feb 9 2013, 14:49
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Feb 9 2013, 17:23)  С каких пор, вырезание гландов через анус, называется "решением"? И что тогда называть "костылём", если создание фантомного регистра - "решение". Реальное решение, это использовать bit-band. Вот это - действительно решение. А наплодить тонну фантомных регистров, создать прослойку для работы с ними и радоваться, что хоть как-то разрулили аппаратный недостаток... Философия Microchip/Microsoft в действии?  Разрулить аппаратный "недостаток" (а для меня это просто факт, особенность регистра, не более) - и есть решение... А постоянно ныть о "проблемах" (которые многие просто, почему-то, и не замечают) - и есть хождение "на костылях"... Цитата Вот будет веселье.  Вот... лучше не надо... веселья... поверьте...
|
|
|
|
|
Feb 9 2013, 14:53
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(HHIMERA @ Feb 9 2013, 18:49)  Разрулить аппаратный "недостаток" (а для меня это просто факт, особенность регистра, не более) - и есть решение... Есть много разных способов избавиться от головной боли. Гильотина - не лучший. Хотя некоторые сочтут его вполне годным. В данном случае, никто не ноет. Есть вариант с bit-band. Это - решение. Все остальное - не решения, а какая-то отрыжка из конца 90-х, с их кривыми PIC-ами.
|
|
|
|
|
Feb 9 2013, 15:13
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Feb 9 2013, 18:53)  Есть много разных способов избавиться от головной боли. Гильотина - не лучший. Хотя некоторые сочтут его вполне годным. "Проблемы индейцев - вождя не колышат!"(С)... Цитата В данном случае, никто не ноет. Есть вариант с bit-band. Это - решение. Все остальное - не решения, а какая-то отрыжка из конца 90-х, с их кривыми PIC-ами.  "Решение"... или... "праздничный костыль"???
|
|
|
|
|
Feb 9 2013, 15:17
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
не очень понимаю в чем спор то? раньше бит-банда не было, его не хватало, его сделали. Появился инструмент, появился он не просто так, значит он нужен, и его надо использовать. Но с другой стороны и без него решали задачи, в 9 и 7 арме если не ошибаюсь его не было.
Мои проекты вообще далеки от драйверов, операционок и прочих прелестей, я если что-то иничу или ремаплю, то делаю это один раз, и могу выбрать последовательность в которой все пройдет гладко, и могу не заморачиватся с ним. Но и отрицать его и гонятся за ним с крестом тоже не стану%)...
|
|
|
|
|
Feb 9 2013, 15:59
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Golikov A. @ Feb 9 2013, 18:17)  не очень понимаю в чем спор то? Да если честно... я тоже... Нет там никаких проблем с ремапом... ни в каком виде... изначально... всё это надуманно...
|
|
|
|
|
Feb 9 2013, 16:07
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(Golikov A. @ Feb 9 2013, 19:17)  не очень понимаю в чем спор то? Изначально - нужен bit-band или "можно и без него обойтись, не очень-то и хотелось". Цитата(Golikov A. @ Feb 9 2013, 19:17)  я если что-то иничу или ремаплю, то делаю это один раз, и могу выбрать последовательность в которой все пройдет гладко Ключевое слово здесь "я". Это частный случай. Но начиная с какого-то размера, трудоемкость raw кодирования сильно увеличивается. Избежать этого поможет разбиение на блоки. Но появляется ограничение - блоки должны работать корреткно, в т.ч. независимо от того, в какой последовательности их вызывают. В моем случае, есть несколько разных модулей верхнего уровня, каджый из которых может вызвать инициализацию в произвольный момент, а не только в начале программы. Больше того, модули верхнего уровня могут быть написаны сторонними людьми, поэтому достоверно определить, когда вызывается инициализация - затруднительно. Совсем не факт, что она вызывается только один раз в самом начале. Цитата(HHIMERA @ Feb 9 2013, 19:59)  Нет там никаких проблем с ремапом... ни в каком виде... изначально... всё это надуманно... Вообще-то, проблему я выше изложил. Позже даже разжевал, причем подробно. Но раз нет - значит нет. На том и порешим. P.S. "Пушкин, он как гамлЕт. Все отрицал." (с) Шура Каретный
|
|
|
|
|
Feb 9 2013, 16:40
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Feb 9 2013, 20:07)  проблему я выше изложил. Позже даже разжевал, причем подробно. Но раз нет - значит нет. Хорошо... Почему проблема возникла только у вас... судя по отсутствию "горячего" обсуждения... проблема "чисто ваша"... Иначе... было-бы и обсуждение и методы решения... Думать, что ремапом пользуетесь только вы.... наивно, по крайней мере... Отсюда: Проблемы нет... и она никому не интересна, ввиду её полного отсутствия... Дальше... Регистр прочитать нельзя... но писать то можно??? Трудности с установкой/ очисткой битов??? Не знаете что такое маска??? Очистили нужные биты, потом установили... в хэдэр хоть заглядывали??? Так в чём проблемы??? А бит-бэндинг/ не бит-бэндинг это уже частности... а не панацея...
|
|
|
|
|
Feb 9 2013, 17:24
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Petka @ Feb 9 2013, 21:07)  Это-то тут причём? Ради флуда? Цитата Отказ от "дефайнов" приводит к более красивому коду и к простоте отладки. Дефайны не осуществляют проверку типов и т.п.
|
|
|
|
|
Feb 9 2013, 17:26
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата(HHIMERA @ Feb 9 2013, 20:40)  Дальше... Регистр прочитать нельзя... но писать то можно??? Трудности с установкой/ очисткой битов??? Не знаете что такое маска??? Очистили нужные биты, потом установили... в хэдэр хоть заглядывали??? Так в чём проблемы??? А бит-бэндинг/ не бит-бэндинг это уже частности... а не панацея... вы не совсем правы. Если регистр прочитать нельзя, то нельзя установить его значения. Следовательно присвоение по маске тоже не сработает. так как общее правило для него считать значение, изменить нужные маскированные биты, и записать значение обратно. В этом случае если нет возможности достоверного считывания значения то и нет возможности записать его достоверно обратно. к примеру бит который читается всегда как 0, но может быть выставлен в единицу, после считывания и записывания обратно гарантировано занулиться... единственное мне очень странно слышать недоступный для чтения бит, недоступный для записи я могу понять, но для чтения?... Зачем они такие... Такое возможно только если этот бит реально не надо читать, то есть допустим он задает режим работы, который жестко определен и не может быть изменен, тогда этот режим определяет константную часть регистра, которую либо вычисляют от состояния либо хранять в памяти. как то так.... но бит-банд на самом деле сделан для экономии инструкций и увеличения скорости битошевеления, замена изменения одного бита - одной инструкцией против читать, маскировать, менять, записывать весьма соблазнительная для быстрого кода. а что нет портов ввода вывода, так это потому что часто для них есть свой регистр поставить бит и стереть бит, меняющий именно один бит одного регистра за один такт, и нет смысла отъедать лишнюю память... резюме: без бит-банда можно обойтись, иначе не было прошлых процов без него, он также удобен - иначе бы его не делали. То есть это инструмент который делает нашу жизнь лучше и не надо его отрицать  , ровно как и положить за него жизнь... ИМХО
|
|
|
|
|
Feb 9 2013, 18:01
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Golikov A. @ Feb 9 2013, 20:26)  вы не совсем правы. Если регистр прочитать нельзя, то нельзя установить его значения. Следовательно присвоение по маске тоже не сработает. Ещё раз... читать нельзя... но есть Reset value... есть от чего отталкиваться... А дальше... или я по маске набью переменную и целиком затолкаю в регистр... или положу в регистр заранее подготовленное значение... или буду дёргать бит-бэндом... всё от задачи... А сама проблема ремапа... где???
|
|
|
|
|
Feb 9 2013, 18:16
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(HHIMERA @ Feb 9 2013, 22:01)  Ещё раз... читать нельзя... но есть Reset value... есть от чего отталкиваться... Индусский подход? Именно так в либах от ST и сделано ( о чудо, оказывается я заглядываю в "хидеры" и "либы" ). К чему это приводит, я уже объяснял. По второму разу жевать одно и тоже - никакого желания. Цитата(HHIMERA @ Feb 9 2013, 22:01)  А сама проблема ремапа... где??? Круто. Расписать несколько вариантов "костылей", а потом самому же скромно спросить - а где, собственно, проблема? Я оценил.  Цитата(Petka @ Feb 9 2013, 20:45)  Отказ от "дефайнов" приводит к более красивому коду и к простоте отладки. Дефайны не осуществляют проверку типов и т.п. Все верно. И таким образом, тема плавно перетекает в грамотно продуманный API.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|