Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: давайте делится удобными дефайнами для stm32f10x
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
super_puper
например я вот такие сделал :
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);
//^^^^^^^^^^^^ Задаём направление и максимальную частоту работы портов ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
jcxz
хм.... И что-ж тут удобного??? smile3046.gif
Во-первых - неудобно, во-вторых - баги в каждом макросе.
Вот вам для примера мои аналогичные макросы, для управления пинами GPIO (NXP). Найдите отличия и поймите где баги: laughing.gif

Код
#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);
ISK2010
Ну, раз для 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;
super_puper
я обнаружил что есть готовые стандартные бибилотеки) STM32F10x_StdPeriph_Driver ,изучаю щас их и пытаюсь пользоваться
_Pasha
Цитата(super_puper @ Feb 7 2013, 06:04) *
я обнаружил что есть готовые стандартные бибилотеки) STM32F10x_StdPeriph_Driver ,изучаю щас их и пытаюсь пользоваться

Совет: если собираетесь что-то написать с плотным использованием этой либы, не отходите далеко от предложенного темплейта проекта, - только в этом случае у Вас не съедет крыша от количества мелких ньюансов, которые надо держать в голове и которые отвлекают от того, что нужно.
super_puper
поизучал и ужаснулся как то мягко говоря неудобно они сделали.. непонятно зачем диверсия или глупость их или я что то не понимаю.
опять решил сам писать
_Pasha
Цитата(super_puper @ Feb 7 2013, 12:14) *
опять решил сам писать

Вот это и есть главная опасность, если Вам уже пора результат какой-то получить, а Вы начинаете с нуля все переписывать. Рискуете свалиться в бесконечную писанину. Кривизна этих либ бесспорна, но сделать лучше таки сложновато с первого захода, если надо получить нечто, работающее на всех STM32.
Как промежуточный вариант - отлаживаю bsp в симуле кейла, затем добавляю несколько wrapper"ов касательно синтаксиса и перехожу в GCC.
Или хватаю пример использования чего-то там (с этой либой, а как жеж) - и пилю своё.
jcxz
Цитата(_Pasha @ Feb 7 2013, 15:38) *
Кривизна этих либ бесспорна, но сделать лучше таки сложновато с первого захода, если надо получить нечто, работающее на всех STM32.
Не соглашусь с Вами. Вполне можно написать свои макросы, гораздо более лёгкие и понятные чем эти библиотеки.
У меня вызовы макросов типа установить/обнулить/проинвертировать/... пин GPIO одинаковы для разных процессоров, что часто позволяет переносить исходники с одного CPU на другой другого производителя с минимальными модификациями (или вообще без оных).
_Pasha
Цитата(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 какой-то сферический пин - нету. laughing.gif

super_puper
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
теперь нужно для частот тактирования, выбор источника тактирования , и ПЛЛек писать дефайны или функции
никто не написал ещё?
HHIMERA
Цитата(super_puper @ Feb 8 2013, 06:48) *
никто не написал ещё?

Бросьте фигнёй заниматься... займитесь лучше чем-то полезным...
Lmx2315
QUOTE (super_puper @ Feb 8 2013, 06:48) *
теперь нужно для частот тактирования, выбор источника тактирования , и ПЛЛек писать дефайны или функции
никто не написал ещё?

http://electronix.ru/forum/lofiversion/ind...hp/t103011.html

вот тут посмотрите : STM32 генератор кода
Forger
Цитата(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. Буду рад, если мои идеи кому-то еще пригодятся sm.gif
_Pasha
Цитата(Lmx2315 @ Feb 8 2013, 10:18) *
http://electronix.ru/forum/lofiversion/ind...hp/t103011.html

вот тут посмотрите : STM32 генератор кода

Это миф, не умеет оно код генерить. Вижуалти хорошее, иногда полезно для полноты впечатлений. Пользуюсь плагином для клипсы
Lmx2315
QUOTE (_Pasha @ Feb 8 2013, 11:32) *
Это миф, не умеет оно код генерить. Вижуалти хорошее, иногда полезно для полноты впечатлений. Пользуюсь плагином для клипсы


всмысле миф - генерируемое не работает?
..сам не прогал стм32 но вдруг понадобиться.
_Pasha
Цитата(Lmx2315 @ Feb 8 2013, 12:08) *
всмысле миф - генерируемое не работает?
..сам не прогал стм32 но вдруг понадобиться.

Code generation is currently not iplemented
MrYuran
Цитата(_Pasha @ Feb 7 2013, 18:11) *
А дергать пинами - у меня лично такого уровня просто нет. У меня в board.h есть например "включить реле", а set-reset какой-то сферический пин - нету. laughing.gif

++
В основном тексте не должно быть ни пинов, ни портов.
Во-первых, читабельность повышается, а во-вторых, легким движением руки в одном маленьком файлике можно "поменять то на это"
Lmx2315
QUOTE (_Pasha @ Feb 8 2013, 12:22) *
Code generation is currently not iplemented



ничего не пойму, скачал эту прогу : "STM32 генератор кода" - выбираю фичи , снизу генерится код.
Код не рабочий?

_Pasha
Цитата(Lmx2315 @ Feb 8 2013, 13:45) *
ничего не пойму, скачал эту прогу : "STM32 генератор кода" - выбираю фичи , снизу генерится код.
Код не рабочий?

cranky.gif Хде?
Version 2.2
Нету!
Tahoe
Цитата(_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 );
}
Golikov A.
разницы между
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;

потому что изменений при смене проца или разводки в данном случае столько же сколько при добавленных макросах инициализации и так далее, но макросы писать не надо, то есть выигрыш имеется.
_Pasha
Цитата(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) - чтобы само рулило кто у нас источник, кто приемник, накладные расходы есть.

Цель мсм такая:
чтобы можно было быстро что-то опробовать, без лишней писанины, но и без сильной специализации. и не лазать в книжку каждую секунду.

Может, попробуем какие-то общие свойства выделить?
Tahoe
Цитата(_Pasha @ Feb 8 2013, 16:07) *
Я так понимаю, "хоть на AVR" - это означает, что там, где фича не отлита в железе, она либо тупо не поддерживается либо включается программная эмуляция, там где не внапряг по ресурсам.

Примерно так. Только никакой эмуляции, как правило, нет. Если фичи нет, значит ее нет, "и никакие лекции не изменят этого соотношения сил, если каждый индивидуум в отдельности не будет постоянно тренироваться в шашк... то есть я хотел сказать в шахматы" (с). sm.gif

Цитата(_Pasha @ Feb 8 2013, 16:07) *
И вот с таймерами - муки выбора - либо как у Вас, либо конкретно по областям применения - энкодер, хренсним, на авр зацепим прерывание, на пиках моторных - железный, на STM -железный. ШИМ для силовухи - то же самое. Каскадирование - там понятно, что эмуляция рулит.

Никаких мук. Даже странно, что этот вопрос поднимает тот, кто пишет на плюсах ( если не ошибаюсь sm.gif ). Есть объект, у него есть свойства. Если объект "таймер", то причем тут энкодер? Энкодер, это отдельная сущность, совершенно отдельный объект. Как частный случай, подключеный с помощью "таймер". Ничем не отлиается, например, от работы с внешней ЕЕПРОМ. Абсолютно не важно, как эта ЕЕПРОМ подключена, через объект "SPI" или объект "I2C", адресация адресация и размерность данных самой ЕЕПРОМ от этого не меняются.

Цитата(_Pasha @ Feb 8 2013, 16:07) *
Может, попробуем какие-то общие свойства выделить?

Так см. мой пример, там именно по этому принципу сделано. Например, у таймера может быть, а может не быть канала Compare. Таймеру может требоваться, а может не требоваться инициализация ( в основном, как и другим объектам, включить/выключить системный клок, в AVR или MSP430 это не требуется ). Потому все и разбито на блоки.
Кроме того, не следует пытаться запихнуть в AVR-таймер все фичи, доступные STM32-таймеру. Описания свойств таймеров у меня не отличаются, просто среди аргументов McuTmrConfig() какие-то есть, каких-то нет, это не трагедия.

Еще предостерегу от попытки написать супер-пупер универсальный код, что бы прям можно было переносить копи-пастом из проекта AVR в проект LPC17xx. Этого не требуется и лишь усложнит дело. Достаточно просто иметь единообразные названия функций, с максимально типизированными аргументами.
Golikov A.
сдается мне что писать код который учитывает особенности реализации типа есть клок на шине и нет - тоже не особо нужно.
Очень много времени тратиться на такие функции, они становятся большими, с кучами дефайнов и ифдефов, а в итоге что?

включаешь ее и думаешь, а правильно ли она сработает, точно все проинититься как надо? все флажки расставил?
Tahoe
Цитата(Golikov A. @ Feb 8 2013, 16:33) *
включаешь ее и думаешь, а правильно ли она сработает, точно все проинититься как надо? все флажки расставил?

+1 sm.gif
SyncLair
Цитата(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) соотвественно получается некоторая "ПЛАТОПЕРЕНОСИМОСТЬ"

Rash
Сам юзаю 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);
}

HHIMERA
Цитата(SyncLair @ Feb 8 2013, 17:32) *
ставлю SET_PIN(LED_PIN) и CLEAR_PIN(LED_PIN) соотвественно получается некоторая "ПЛАТОПЕРЕНОСИМОСТЬ"

Тут уже объясняли... что подобное не несёт никакой смысловой нагрузки...
В случае малейшей ошибки, после двух-трёх бессоных ночей, у вас глаза откажут от всех этих повсеместных SET_PIN, CLEAR_PIN, SET_BIT и CLEAR_BIT... а вместе с ними и мозг...
_Pasha
Цитата(Rash @ Feb 8 2013, 16:50) *
перемести в H файл и заинлайнить, то компилятор должен их встроить, там где их вызывают, т.е. получим макс. быстродействие равное записи напрямую в регистр.

Совершенно ага!
Если в параметрах будет const (разрулить возможные обращения по записи) - то на выходе получим минимум миниморум. Посмотрите на lib_at91samxxxxxxx.h


Цитата(Tahoe @ Feb 8 2013, 15:29) *
Никаких мук. Даже странно, что этот вопрос поднимает тот, кто пишет на плюсах ( если не ошибаюсь sm.gif ).

Не-не, я на плюсах ни-ни sm.gif
Как только умрет последний PIC18, - тогда да.
Rash
Цитата(_Pasha @ Feb 8 2013, 18:17) *
Совершенно ага!
Если в параметрах будет const (разрулить возможные обращения по записи) - то на выходе получим минимум миниморум. Посмотрите на lib_at91samxxxxxxx.h


не понятно почему так не сделана либа STM, и к чему тогда возникающие периодические споры про корявую либу СТМ или какие то хитрые дефайны с регистрами, если всего то надо разок потратить время и перебить функции на инлайн.
HHIMERA
Цитата(Rash @ Feb 8 2013, 17:49) *
если всего то надо разок потратить время и перебить функции на инлайн.

И некоторые из них просто станут неработоспособными... если не ошибаюсь... SPI, например...
_Pasha
Цитата(Rash @ Feb 8 2013, 17:49) *
не понятно почему так не сделана либа STM

Это вроде как логическое продолжение CMSIS. Потом, там MISRA2004 проехалась, потом - операции с битовыми полями априори неизвестно как себя ведут на разных компилерах, иначе все было бы попроще. Всему есть причины.

Либой для АТ91 тоже не очень приятно пользоваться, я имею ввиду длинные префиксы в именах.

--
Как альтернатива - Coocox"овые либы... Но там другая сторона медали: в STшных - инициализация через структуру, зато функции с 2-мя параметрами и повторное использование, в кокосовых - функции с большим числом параметров. Хрен редьки, как говорится.

Цитата(HHIMERA @ Feb 8 2013, 18:00) *
И некоторые из них просто станут неработоспособными... если не ошибаюсь... SPI, например...

Ухты! Где?
HHIMERA
Цитата(_Pasha @ Feb 8 2013, 19:08) *
Ухты! Где?

Точно уже не припомню...
Зато точно помню... что желание инлайнить весь этот колхоз, почему-то, не возникает...
Rash
ну да стандарты, есть стандарты. Но для себя решил, надо выделить время и по той периферии которая используется заинлайних их функции. Что удобно, что там объявлены большинство регистров, иногда даташит даже открывать не приходится, просто надо как и всё под себя с оптимизировать минимальными ресурсами. Даже имена им менять не нужно.
Tahoe
Цитата(Rash @ Feb 8 2013, 19:33) *
Что удобно, что там объявлены большинство регистров, иногда даташит даже открывать не приходится, просто надо как и всё под себя с оптимизировать минимальными ресурсами. Даже имена им менять не нужно.

Вот только есть одна неприятность. Учитывая, как у ST оъявлены биты, использовать bitband не получится. Остается уповать на компилер, но тот же IAR не торопится задействовать bitband регион.
_Pasha
Смотрю я на этот битбанд и что-то выигрыш не особо просматривается... кроме атомарности.
Tahoe
Цитата(_Pasha @ Feb 8 2013, 22:29) *
выигрыш не особо просматривается... кроме атомарности.

А прочего от него особо и не требуется.

Ну и, как обычно, смотреть надо на проблему в целом, а не на стоимость отдельных частей. Использование bitband позволит избавиться от ENTER_CRITICAL()/EXIT_CRITICAL(). Ну и как теперь, выигрыш "просмотрелся"(с) ? wink.gif
adnega
А, вроде, в новеньких F3 вход-вывод не попадает в bit-band?...
Tahoe
Цитата(adnega @ Feb 8 2013, 23:14) *
А, вроде, в новеньких F3 вход-вывод не попадает в bit-band?...

Bitband, это фича ядра, не контроллера. Производители ядра говорят что такая фича есть, хоть и опционально. ST тоже говорит, что есть. См. STM32F3xxx and STM32F4xxx Cortex-M4 programming manual, "2.2.5 Bit-banding".
adnega
Про фичу ядра согласен. Но в приведенном Вами документе для периферии выделяется Peripheral bit-band region 0x40000000-0x400FFFFF (см. стр. 31). Легко убедится (см. RM для stm32f3xx), что GPIOx туда не попадает, т.к. начинается с 0x48000000. ((
Сам с данной неприятностью столкнулся при использовании "универсальных дефайнов для работы с GPIO"...
_Pasha
biggrin.gif
А смысл работы GPIO в означенном регионе? Если и так чтобы установить/сбросить атомарно - все есть.
А конфигурацию пинов зачем атомарно менять? Я даже такой ситуёвины представить не могу
Tahoe
Цитата(_Pasha @ Feb 9 2013, 03:02) *
А конфигурацию пинов зачем атомарно менять? Я даже такой ситуёвины представить не могу

Б-г с ней, с атомарностью. "Ситуевину представить"(с) - "легко, смеясь"(с) : как я налетел с ремапом. А именно:
Цитата(Tahoe @ Jul 20 2012, 12:28) *
А в библиотеках от ST просто в наглую подставляется константа. И совсем не факт, что она совпадет с тем, как ранее настроил программер.


А теперь, хотелось бы услышать любой другой способ, кроме bit-band, позволяющий безопасно установить ремап-биты. biggrin.gif
_Pasha
Цитата(Tahoe @ Feb 9 2013, 06:03) *
А теперь, хотелось бы услышать любой другой способ, кроме bit-band, позволяющий безопасно установить ремап-биты. biggrin.gif

А в RMW-операциях можно налететь на грабли и по другому - просто записав битик туда, куда не нужно, - помечено как reserved биты, а каким образом оно себя проявить может - хз.
adnega
Цитата(_Pasha @ Feb 9 2013, 03:02) *
А смысл работы GPIO в означенном регионе? Если и так чтобы установить/сбросить атомарно - все есть.
А конфигурацию пинов зачем атомарно менять? Я даже такой ситуёвины представить не могу

Написал библиотеку для работы с UART.
При инициализации передаем адрес бита ножки GPIO, отвечающую за передачу в RS-485.
Как быть теперь? Применить свою виртуальную адресацию битов портов?
По библиотеке для этих целей могу "протащить" лишь одну 32-битную переменную.
jcxz
Цитата(Tahoe @ Feb 9 2013, 01:05) *
Использование bitband позволит избавиться от ENTER_CRITICAL()/EXIT_CRITICAL(). Ну и как теперь, выигрыш "просмотрелся"(с) ? wink.gif
С чего-бы это?? Только разве что в одном конкретном случае - если область, которую надо защитить критической секцией, ограничивается одним словом и только на одну операцию (укладывающуюся в одну команду ASM).
Всё то же самое (и даже гораздо больше) решается с помощью LDREX/STREX.
Ну-ка реализуйте мне пожалуйста с помощью битбандинга стандартную атомарную операцию CompareAndExchange? laughing.gif
А с помощью 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 ног это вроде не должно составлять проблем... laughing.gif
Можно даже с помощью макросов сделать это красиво, а-ля:
Код
//определения пинов:
#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))
...
Tahoe
Цитата(_Pasha @ Feb 9 2013, 10:22) *
А в RMW-операциях можно налететь на грабли и по другому - просто записав битик туда, куда не нужно, - помечено как reserved биты, а каким образом оно себя проявить может - хз.

Можно. Но я же спросил не о новых проблемах, а о решении конкретной и реально существующей. Так кроме bitband, ещё как-то можно корректно и безопасно сделать ремап? Кстати, даже с bitband тоже не все так просто оказалось, но в итоге решилось.
HHIMERA
Цитата(Tahoe @ Feb 9 2013, 13:23) *
Можно. Но я же спросил не о новых проблемах, а о решении конкретной и реально существующей.

Нет там никакой проблемы с ремап... есть временное недопонимание/трактование по своему...

Это всё из ряда:
Цитата
Кстати, даже с bitband тоже не все так просто оказалось, но в итоге решилось.

adnega
Цитата(jcxz @ Feb 9 2013, 12:10) *
А что - так трудно упаковать номер бита в порту в младшие 5 бит, а номер порта - в старшую часть 32бит?
Пока не выпустили корпуса с 2^32 ног это вроде не должно составлять проблем... laughing.gif
Можно даже с помощью макросов сделать это красиво, а-ля:


Сравните с существующей реализацией:
Код
if(con->txena) *con->txena = TX_ON;

и во что она скомпилируется.

Или вот такое:
Код
WORKLED_bit ^= 1;


В этом плане GPIO на bit-band очень удобен.
При этом "цена вопроса" - 6кБ в соответствующем регионе!
Tahoe
Цитата(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 были уже установлены. Тот редкий случай, когда получу удовольствие, если меня ткнут носом. Вот только шансов на это нет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.