среда, 9 ноября 2011 г.

четверг, 10 марта 2011 г.

Настройка среды разработки

Когда уже имеется работающий копилятор, можно писать программы и собирать их с помощью командной строки, но гораздо удобнее делать все это с помощью любимой среды разработки (IDE, Integrated Development Environment).




Среда разработки 

В качестве IDE я выбрал Code::Blocks 10.05, потому что Eclipse мне разонравилось из-за своей тяжеловесности и приверженности Java.
Сначала попробовал воспользоваться встроенными в CB шаблонами проектов для ARM, но они оказались предназначенными для конкретныех отладочных плат, среди них даже не нашлось ни одной на нужном мне процессоре.
Поэтому пришлось создать пустой проект и настроить там все вручную.
Первым делом, создав пустой проект, нужно пойти на "Settings->Compiler and Debugger settings" и в разделе "Global compiler settings" выбрать GNU ARM Compilator. 
Сначала нужно указать, где находятся исполняемые файлы компилятора и утилит, для этого надо перейти на вкладку "Toolchain executables" и указать там пути и названия. Автообнаружение компилятора не сработало, поэтому я руками вписал путь (/usr/arm) и ко всем утилитам ниже добавил приставку "arm-none-eabi-". Получилось очень красиво.
Еще на вкладке "Other settings" нужно выбрать значение для "Compiler logging": "Full command line", чтобы видеть в журнале компиляции все, что происходит.
На этом настройка глобальных параметров компилятора закончена.

Теперь настройка сборки проекта: "Project->Build Options". 
Здесь нужно в самом левом окошке выбрать название проекта, тогда настройки будут для всех вариантов сборки - и Debug, и Release.
На вкладке "Compiler settings->Other settings" вписал параметры "-mcpu=cortex-m3 -mthumb -fno-exceptions", больше никаких флагов трогать не стал. В процессорах STM32F103x нет сопроцессора, поэтому нужно использовать программный вариант арифметики с плавающей запятой (soft), что считается параметром по умолчанию.
"-mcpu=cortex-m3" - выбирается тип процессора,
"-mthumb" - система команд, все вместе приведет к использованию семейства команд thumb-2, что в данном случае и нужно.
"-fno-exceptions" - позволяет в несколько раз уменьшить размер выходного файла, потому что выкидывается поддержка исключений для С++, которая в данном случае не нужна. Еще рекомендуют использовать параметр "-fno-rtti", который убирает накладные расходы, связанные с использованием идентификации типов во время исполнения (например, при наследовании).
В настроках компоновщика ("Linker settings") в поле Other linker options" нужно добавитьтакие параметры:
"-mcpu=cortex-m3 -mthumb
-Tstm32.ld
-Wl,-Map=$(TARGET_OUTPUT_FILE).map,--cref,--gc-sections".
"-Tstm32_flash.ld" - для размещения секций памяти, описанных в файле stm32_flash.ld,
"-Wl,-Map=$(TARGET_OUTPUT_FILE).map,--cref,--gc-sections" - чтобы получить карту памяти.
Часто встречается использование параметров
"-nostartfiles" и "-nostdlib", но это нужно делать сугубо индивидуально в зависимости от конкретной ситуации.
"-nostartfiles" -  отключается использование, например, crt0.o, где производится настройка многих вещей в самом начале работы программы: инициализация стека, настройка таблицы векторов прерываний, обнуление  глобальных переменных, присвоение начальных значений. Если имеется свой собственный начальный файл. то стандартный лучше отключить.
"-nostdlib" - аналогично, если нежелательно использование стандартных библиотек libc, libm и libgcc.
Еще я на вкладке "Compiler settings-># defines" добавил следующие определения:
STM32F10X_HD
HSE_VALUE=12000000UL
Они нужны для указания параметров используемого процессора, используются стандартной библиотекой STM32.
На вкладке "Search directories" все поля пустые.
На вкладке "Pre/post build steps" в поле "Post-build steps" я добавил такие строки:
arm-none-eabi-size $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_FILE) - чтобы получать информацию о размере используемой памяти,
arm-none-eabi-objcopy -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_FILE).hex - чтобы получить файл для прошивки,
arm-none-eabi-objcopy -O binary $(TARGET_OUTPUT_FILE) $TARGET_OUTPUT_FILE).bin - собственно, тоже можно использовать для прошивки процессора,
arm-none-eabi-objdump -h -S $(TARGET_OUTPUT_FILE) > $(TARGET_OUTPUT_FILE).lss - чтобы получить дизассемблерный листинг. Для листинга, по другим рекомендациям, можно использовать ключи -D -S - тогда листинг получается в несколько раз больше.

Создание проекта

Поскольку проект был пустой, то пришлось в нем создать новый файл main.cpp такого содержания:

#include "stm32f10x.h"

int main(void)
{
    uint32_t i = 0;
    while(true)
    {
        for (uint32_t k = 0; k < 2000; k++)
            i = k;
    }
    return 0;
}
Текст сделан так, чтобы компилятору можно было хоть что-то сделать. Для поддержки своих процессоров STMicroelectronics  дает возможность загрузить со своего сайта библиотеку поддержки stm32f10x_stdperiph_lib.zip (примерно 14 МБ размером).
В этом пакете есть файл описания процессора STM32F10x_StdPeriph_Lib_V3.3.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h, в нем содержатся названия и привязки битов, регистров и всего прочего для процессора. В нем необходимо примерно в 50-й строке раскомментарить строчку, характеризующую используемый процессор, в моем случае это была строка 53:
#define STM32F10X_HD     /*!< STM32F10X_HD: STM32 High density devices */
или определить в командной строке компилятора параметр -DSTM32F10X_HD. Кроме того, необходимо указать частоту используемого кварца. По умолчанию считается, что используется кварц на 8 МГц, поэтому нужно указать свое значение (-DHSE_VALUE=12000000UL в моем случае, поскольку на плату установили кварц на 12 МГц). Но, к сожалению, этого недостаточно, потому что в функции
SetSysClockTo72() все равно жестко используется умножение на 9:
/*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
что рассчитано только на использование кварца 8 МГц. В моем случае мне нужно было бы в этом файле (system_stm32f10x.h) вместо RCC_CFGR_PLLMULL9 вписать RCC_CFGR_PLLMULL6, либо написать собственную вариант настройки всех частот процессора.
В строке 412 и 413 файла stm32f10x.h видно, что нужны еще два файла:
#include "core_cm3.h"
#include "system_stm32f10x.h"
поэтому их и соответствующие им С-файлы тоже нужно скопировать в свой проект.
Файлы core_cm3.h и core_cm3.c находятся в каталоге STM32F10x_StdPeriph_Lib_V3.3.0/Libraries/CMSIS/CM3/CoreSupport,
 а system_stm32f10x.h и system_stm32f10x.c - рядом с файлом stm32f10x.h.
В core_cm3.* описывается то, что односится к ядру cortex-m3, а в остальных файлах - периферия.
Периферийные описания, оказывается, можно брать и из другого каталога: STM32F10x_StdPeriph_Lib_V3.3.0/Libraries/STM32F10x_StdPeriph_Driver. Там находятся небольшие программные модули для обслуживания той или иной периферии. Но, чтобы не заморачиваться, еще и с интерфейсом этих вызовов, я использую базовую конфигурацию, а чтобы понять, как работать с тем или иным устройством процессора, заглядываю в этот каталог.
Для правильной инициализации некоторых вещей еще до передачи управления С-программе используется стартовый модуль на ассемблере, который можно взять из каталога STM32F10x_StdPeriph_Lib_V3.3.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7 (потому что компилятор Raisonance построен на базе GCC) - для процессора STM32103VCT подходит файл startup_stm32f10x_hd.s.
Но я нашел примеры стартовых файлов на С и решил использовать именно такой файл:

#include "stm32f10x.h"

typedef void( *const intfunc )( void );

#define WEAK __attribute__ ((weak))

extern unsigned long _etext;
extern unsigned long _sidata;
extern unsigned long _sdata;
extern unsigned long _edata;
extern unsigned long _sbss;
extern unsigned long _ebss;
extern unsigned long _estack;

void Reset_Handler(void) __attribute__((__interrupt__));
void __Init_Data(void);
void Default_Handler(void);

extern int main(void);
extern void __libc_init_array(void);  /* calls CTORS of static objects */

void WEAK NMI_Handler(void);
void WEAK HardFault_Handler(void);
void WEAK MemManage_Handler(void);
void WEAK BusFault_Handler(void);
void WEAK UsageFault_Handler(void);
void WEAK MemManage_Handler(void);
void WEAK SVC_Handler(void);
void WEAK DebugMon_Handler(void);
void WEAK PendSV_Handler(void);
void WEAK SysTick_Handler(void);

void WEAK WWDG_IRQHandler(void);
void WEAK PVD_IRQHandler(void);
void WEAK TAMPER_IRQHandler(void);
void WEAK RTC_IRQHandler(void);
void WEAK FLASH_IRQHandler(void);
void WEAK RCC_IRQHandler(void);
void WEAK EXTI0_IRQHandler(void);
void WEAK EXTI1_IRQHandler(void);
void WEAK EXTI2_IRQHandler(void);
void WEAK EXTI3_IRQHandler(void);
void WEAK EXTI4_IRQHandler(void);
void WEAK DMA1_Channel1_IRQHandler(void);
void WEAK DMA1_Channel2_IRQHandler(void);
void WEAK DMA1_Channel3_IRQHandler(void);
void WEAK DMA1_Channel4_IRQHandler(void);
void WEAK DMA1_Channel5_IRQHandler(void);
void WEAK DMA1_Channel6_IRQHandler(void);
void WEAK DMA1_Channel7_IRQHandler(void);
void WEAK ADC1_2_IRQHandler(void);
void WEAK USB_HP_CAN1_TX_IRQHandler(void);
void WEAK USB_LP_CAN1_RX0_IRQHandler(void);
void WEAK CAN1_RX1_IRQHandler(void);
void WEAK CAN1_SCE_IRQHandler(void);
void WEAK EXTI9_5_IRQHandler(void);
void WEAK TIM1_BRK_IRQHandler(void);
void WEAK TIM1_UP_IRQHandler(void);
void WEAK TIM1_TRG_COM_IRQHandler(void);
void WEAK TIM1_CC_IRQHandler(void);
void WEAK TIM2_IRQHandler(void);
void WEAK TIM3_IRQHandler(void);
void WEAK TIM4_IRQHandler(void);
void WEAK I2C1_EV_IRQHandler(void);
void WEAK I2C1_ER_IRQHandler(void);
void WEAK I2C2_EV_IRQHandler(void);
void WEAK I2C2_ER_IRQHandler(void);
void WEAK SPI1_IRQHandler(void);
void WEAK SPI2_IRQHandler(void);
void WEAK USART1_IRQHandler(void);
void WEAK USART2_IRQHandler(void);
void WEAK USART3_IRQHandler(void);
void WEAK EXTI15_10_IRQHandler(void);
void WEAK RTCAlarm_IRQHandler(void);
void WEAK USBWakeUp_IRQHandler(void);
void WEAK TIM8_BRK_IRQHandler(void);
void WEAK TIM8_UP_IRQHandler(void);
void WEAK TIM8_TRG_COM_IRQHandler(void);
void WEAK TIM8_CC_IRQHandler(void);
void WEAK ADC3_IRQHandler(void);
void WEAK FSMC_IRQHandler(void);
void WEAK SDIO_IRQHandler(void);
void WEAK TIM5_IRQHandler(void);
void WEAK SPI3_IRQHandler(void);
void WEAK UART4_IRQHandler(void);
void WEAK UART5_IRQHandler(void);
void WEAK TIM6_IRQHandler(void);
void WEAK TIM7_IRQHandler(void);
void WEAK DMA2_Channel1_IRQHandler(void);
void WEAK DMA2_Channel2_IRQHandler(void);
void WEAK DMA2_Channel3_IRQHandler(void);
void WEAK DMA2_Channel4_5_IRQHandler(void);

__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
    (intfunc)((unsigned long)&_estack), /* The stack pointer after relocation */
    Reset_Handler,              /* Reset Handler */
    NMI_Handler,                /* NMI Handler */
    HardFault_Handler,          /* Hard Fault Handler */
    MemManage_Handler,          /* MPU Fault Handler */
    BusFault_Handler,           /* Bus Fault Handler */
    UsageFault_Handler,         /* Usage Fault Handler */
    0,                          /* Reserved */
    0,                          /* Reserved */
    0,                          /* Reserved */
    0,                          /* Reserved */
    SVC_Handler,                /* SVCall Handler */
    DebugMon_Handler,           /* Debug Monitor Handler */
    0,                          /* Reserved */
    PendSV_Handler,             /* PendSV Handler */
    SysTick_Handler,            /* SysTick Handler */

    /* External Interrupts */
    WWDG_IRQHandler,            /* Window Watchdog */
    PVD_IRQHandler,             /* PVD through EXTI Line detect */
    TAMPER_IRQHandler,          /* Tamper */
    RTC_IRQHandler,             /* RTC */
    FLASH_IRQHandler,           /* Flash */
    RCC_IRQHandler,             /* RCC */
    EXTI0_IRQHandler,           /* EXTI Line 0 */
    EXTI1_IRQHandler,           /* EXTI Line 1 */
    EXTI2_IRQHandler,           /* EXTI Line 2 */
    EXTI3_IRQHandler,           /* EXTI Line 3 */
    EXTI4_IRQHandler,           /* EXTI Line 4 */
    DMA1_Channel1_IRQHandler,   /* DMA1 Channel 1 */
    DMA1_Channel2_IRQHandler,   /* DMA1 Channel 2 */
    DMA1_Channel3_IRQHandler,   /* DMA1 Channel 3 */
    DMA1_Channel4_IRQHandler,   /* DMA1 Channel 4 */
    DMA1_Channel5_IRQHandler,   /* DMA1 Channel 5 */
    DMA1_Channel6_IRQHandler,   /* DMA1 Channel 6 */
    DMA1_Channel7_IRQHandler,   /* DMA1 Channel 7 */
    ADC1_2_IRQHandler,          /* ADC1 & ADC2 */
    USB_HP_CAN1_TX_IRQHandler,  /* USB High Priority or CAN1 TX */
    USB_LP_CAN1_RX0_IRQHandler, /* USB Low  Priority or CAN1 RX0 */
    CAN1_RX1_IRQHandler,        /* CAN1 RX1 */
    CAN1_SCE_IRQHandler,        /* CAN1 SCE */
    EXTI9_5_IRQHandler,         /* EXTI Line 9..5 */
    TIM1_BRK_IRQHandler,        /* TIM1 Break */
    TIM1_UP_IRQHandler,         /* TIM1 Update */
    TIM1_TRG_COM_IRQHandler,    /* TIM1 Trigger and Commutation */
    TIM1_CC_IRQHandler,         /* TIM1 Capture Compare */
    TIM2_IRQHandler,            /* TIM2 */
    TIM3_IRQHandler,            /* TIM3 */
    TIM4_IRQHandler,            /* TIM4 */
    I2C1_EV_IRQHandler,         /* I2C1 Event */
    I2C1_ER_IRQHandler,         /* I2C1 Error */
    I2C2_EV_IRQHandler,         /* I2C2 Event */
    I2C2_ER_IRQHandler,         /* I2C2 Error */
    SPI1_IRQHandler,            /* SPI1 */
    SPI2_IRQHandler,            /* SPI2 */
    USART1_IRQHandler,          /* USART1 */
    USART2_IRQHandler,          /* USART2 */
    USART3_IRQHandler,          /* USART3 */
    EXTI15_10_IRQHandler,       /* EXTI Line 15..10 */
    RTCAlarm_IRQHandler,        /* RTC Alarm through EXTI Line */
    USBWakeUp_IRQHandler,       /* USB Wakeup from suspend */
    TIM8_BRK_IRQHandler,
    TIM8_UP_IRQHandler,
    TIM8_TRG_COM_IRQHandler,
    TIM8_CC_IRQHandler,
    ADC3_IRQHandler,
    FSMC_IRQHandler,
    SDIO_IRQHandler,
    TIM5_IRQHandler,
    SPI3_IRQHandler,
    UART4_IRQHandler,
    UART5_IRQHandler,
    TIM6_IRQHandler,
    TIM7_IRQHandler,
    DMA2_Channel1_IRQHandler,
    DMA2_Channel2_IRQHandler,
    DMA2_Channel3_IRQHandler,
    DMA2_Channel4_5_IRQHandler,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0,
    (intfunc)0xF1E0F85F         /* @0x1E0. This is for boot in RAM mode for STM32F10x High Density devices. */
};

void __Init_Data(void) {
    unsigned long *src, *dst;
    /* copy the data segment into ram */
    src = &_sidata;
    dst = &_sdata;
    if (src != dst)
        while(dst < &_edata)
            *(dst++) = *(src++);

    /* zero the bss segment */
    dst = &_sbss;
    while(dst < &_ebss)
        *(dst++) = 0;
}

void Reset_Handler(void) {
    /* Initialize data and bss */
    __Init_Data();

    __libc_init_array(); // call all static construcors in C++ (harmless in C programs)
    SCB->VTOR = 0x08000000;
    SystemInit();
    main();
    while(1) {}
}

#pragma weak MMI_Handler        = Default_Handler
#pragma weak MemManage_Handler        = Default_Handler
#pragma weak BusFault_Handler        = Default_Handler
#pragma weak UsageFault_Handler        = Default_Handler
#pragma weak SVC_Handler        = Default_Handler
#pragma weak DebugMon_Handler        = Default_Handler
#pragma weak PendSV_Handler        = Default_Handler
#pragma weak SysTick_Handler        = Default_Handler
#pragma weak WWDG_IRQHandler        = Default_Handler
#pragma weak PVD_IRQHandler        = Default_Handler
#pragma weak TAMPER_IRQHandler        = Default_Handler
#pragma weak RTC_IRQHandler        = Default_Handler
#pragma weak FLASH_IRQHandler        = Default_Handler
#pragma weak RCC_IRQHandler        = Default_Handler
#pragma weak EXTI0_IRQHandler        = Default_Handler
#pragma weak EXTI1_IRQHandler        = Default_Handler
#pragma weak EXTI2_IRQHandler        = Default_Handler
#pragma weak EXTI3_IRQHandler        = Default_Handler
#pragma weak EXTI4_IRQHandler        = Default_Handler
#pragma weak DMA1_Channel1_IRQHandler    = Default_Handler
#pragma weak DMA1_Channel2_IRQHandler    = Default_Handler
#pragma weak DMA1_Channel3_IRQHandler    = Default_Handler
#pragma weak DMA1_Channel4_IRQHandler    = Default_Handler
#pragma weak DMA1_Channel5_IRQHandler    = Default_Handler
#pragma weak DMA1_Channel6_IRQHandler    = Default_Handler
#pragma weak DMA1_Channel7_IRQHandler    = Default_Handler
#pragma weak ADC1_2_IRQHandler        = Default_Handler
#pragma weak USB_HP_CAN1_TX_IRQHandler    = Default_Handler
#pragma weak USB_LP_CAN1_RX0_IRQHandler    = Default_Handler
#pragma weak CAN1_RX1_IRQHandler    = Default_Handler
#pragma weak CAN1_SCE_IRQHandler    = Default_Handler
#pragma weak EXTI9_5_IRQHandler        = Default_Handler
#pragma weak TIM1_BRK_IRQHandler    = Default_Handler
#pragma weak TIM1_UP_IRQHandler        = Default_Handler
#pragma weak TIM1_TRG_COM_IRQHandler    = Default_Handler
#pragma weak TIM1_CC_IRQHandler        = Default_Handler
#pragma weak TIM2_IRQHandler        = Default_Handler
#pragma weak TIM3_IRQHandler        = Default_Handler
#pragma weak TIM4_IRQHandler        = Default_Handler
#pragma weak I2C1_EV_IRQHandler        = Default_Handler
#pragma weak I2C1_ER_IRQHandler        = Default_Handler
#pragma weak I2C2_EV_IRQHandler        = Default_Handler
#pragma weak I2C2_ER_IRQHandler        = Default_Handler
#pragma weak SPI1_IRQHandler        = Default_Handler
#pragma weak SPI2_IRQHandler        = Default_Handler
#pragma weak USART1_IRQHandler        = Default_Handler
#pragma weak USART2_IRQHandler        = Default_Handler
#pragma weak USART3_IRQHandler        = Default_Handler
#pragma weak EXTI15_10_IRQHandler    = Default_Handler
#pragma weak RTCAlarm_IRQHandler    = Default_Handler
#pragma weak USBWakeUp_IRQHandler    = Default_Handler
#pragma weak TIM8_BRK_IRQHandler    = Default_Handler
#pragma weak TIM8_UP_IRQHandler        = Default_Handler
#pragma weak TIM8_TRG_COM_IRQHandler    = Default_Handler
#pragma weak TIM8_CC_IRQHandler        = Default_Handler
#pragma weak ADC3_IRQHandler        = Default_Handler
#pragma weak FSMC_IRQHandler        = Default_Handler
#pragma weak SDIO_IRQHandler        = Default_Handler
#pragma weak TIM5_IRQHandler        = Default_Handler
#pragma weak SPI3_IRQHandler        = Default_Handler
#pragma weak UART4_IRQHandler        = Default_Handler
#pragma weak UART5_IRQHandler        = Default_Handler
#pragma weak TIM6_IRQHandler        = Default_Handler
#pragma weak TIM7_IRQHandler        = Default_Handler
#pragma weak DMA2_Channel1_IRQHandler    = Default_Handler
#pragma weak DMA2_Channel2_IRQHandler    = Default_Handler
#pragma weak DMA2_Channel3_IRQHandler    = Default_Handler
#pragma weak DMA2_Channel4_5_IRQHandler    = Default_Handler

void Default_Handler(void) {
    while (1) {}
}
Этот файл я назвал startup.c и включил в состав проекта. Большую часть этого файла занимает определение векторов прерываний. Они специально объявляются с помощью "#pragma weak", чтобы вместо них потом могли быть вставлены адреса фактических функций обработки прерываний. Изначально все вектора прерываний указывают на Default_Handler(), куда попадает программа в случае неправильно оформленной обработки прерывания.
После сброса или подачи питания работа начинается с Reset_Handler(), который сначала инициализирует области данных, вызывает статические конструкторы, если они есть, затем заносит в регистр  SCB->VTOR адрес начала таблицы векторов - без этого у меня программа упорно не хотела работать с прерываниями, и именно по этой причине я отказался от стандартного стартового файла на ассемблере, потому что он не настраивал этот регистр.
Далее вызывается функция SystemInit(), которая настраивает тактовые частоты и параметры всей системы.
И только после этого управление передается функции main().
Программа не будет работать без еще одного важного файла: командного файла для компоновщика, который я взял готовым, только подправил фактические параметры памяти.


Отладка


Для отладки нужно сделать следующие настройки проекта: перейти на пункт "Project->Properties...->Debugger". Здесь можно сделать настройки отладчика как для всего проекта, так и для отдельных целей сборки, я сделал для всего проекта.
Для этого в окне "Select target:" нужно выбрать "". На вкладке "Remote connection" выбрать тип "TCP", "IP address:" = localhost, "Port:" = 3333. 
Перейти на вкладку "Additional GDB commands" и в поле "After connection:" вставить строки:
monitor reset halt
break main
continue
 После этого все готово для отладки. Нужно запустить openocd, а после этого можно запускать отладку: "Debugger->Start".
Для отладчика есть полезные глобальные настройки на "Settings->Compiler and debugger settings->Debugger settings". Например, такой полезный параметр: "Evaluate expression under cursor".



вторник, 28 декабря 2010 г.

Проблема с avrdude

После перехода на Fedora 14 при попытке обратиться к программатору:
avrdude -p m1280 -c avrispmkII -P usb
получил ошибку:
...
avrdude: usbdev_open(): error setting configuration 1: could not set config 1: Operation not permitted

Повозившись в инете, добавил в /etc/udev/rules.d файл 11-avrdude.rules
такого содержания:
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2104", MODE="0666", GROUP="plugdev"

Чтобы определить, какие числа нужно вставлять в поля idVendor и idProduct, нужно выполнить команду lsusb, из полученного списка устройств взять номер после ID:

Bus 003 Device 002: ID 03eb:2104 Atmel Corp. AVR ISP mkII

и запросить более подробные сведения:
lsusb -v -d 0471:0669
 
Не забыть после этого добавить себя в группу (в данном случае) plugdev.

вторник, 16 ноября 2010 г.

Пакет средств разработки для ARM Cortex-M3


На работе решили осваивать и внедрять процессоры STM32F103x, поэтому я решил создать собственный "велосипед" - скомпилировать набор средств разработки под эту архитектуру.
Для ситуации, когда никакой операционной системы нет, а используется только "голое" железо, используется, как пишут, варианты gcc с префиксом arm-elf-* и arm-none-eabi-*. В чем разница между этими двумя вариантами, мне пока не удалось понять. Но поскольку мой проект удалось успешно скомпилировать только с помощью бесплатного CodeSorcery G++ Lite, а он использует вариант arm-none-eabi-gcc, то, видимо, и мне нужно пробовать идти этим путем.


Сборка компилятора и утилит

Для простоты я взял binutils и gcc в виде файлов src.rpm с репозитория Fedora 14. Newlib загрузил с ftp://sources.redhat.com/pub/newlib/index.html.
Порядок и параметры сборки я в основном взял отсюда:
http://www.eluaproject.net/en_tc_cortex.html,
в качестве примеров spec-файлов использовал файлы с сайтов:
http://frank.harvard.edu/~coldwell/toolchain/,
http://www.eluaproject.net/en_tc_cortex.htmlhttp://home.comcast.net/~mcatudal/,
http://mes.sourceforge.jp/mes24/linux.html,
http://www.ethernut.de/arc/,
http://michaldemin.wordpress.com/2010/02/09/arm-toolchain-newlib-part1/,
http://blog.nutaksas.com/2009/05/installing-gnuarm-arm-toolchain-on.html,
и еще кучи других мест.
Необходимо, чтобы перед сборкой в системе были установлены пакеты:
flex, flex-static, bison, mpfr, mpfr-devel, texinfo, rpm-build, gmp, gmp-devel,
libmpc, libmpc-devel. Может быть, понадобится еще что-то , но я этого не знаю, поскольку многое в системе уже было установлено по умолчанию.

1. binutils
Во всех spec-файлах я указал стандартный путь установки и цель сборки:
%define _prefix /usr/arm
%define _target arm-none-eabi
В готовом spec-файле заменил строчку конфигурирования:
../configure --target=%{_target} --prefix=%{_prefix} \
 --enable-interwork --enable-multilib \
 --with-gnu-as --with-gnu-ld \
 --with-float=soft 2>&1 | tee configure.out
"--enable-interwork" я вписал на всякий случай, для cortex-m3 этого не нужно, но вдруг придется работать с другим процессором.
"--enable-multilib" - добавил, чтобы не ошибиться, вдруг разные библиотеки потребуются.
"--with-float=soft" - вынужден был добавить, иначе получались библиотеки с поддержкой VFP-команд для операций с плавающей запятой.

2. gcc
Про компилятор везде пишут, что собирать его нужно в два этапа. Сначала собирают "начальный" вариант, чтобы можно было собрать с его помощью newlib. Для сборки начального gcc используются такие параметры:
../configure --target=%{_target} --prefix=%{_prefix} \
    --enable-languages="c,c++" \
    --with-newlib \
    --without-headers \
    --disable-nls \
    --with-gnu-as --with-gnu-ld \
    --disable-shared \
    --with-float=soft 2>&1 | tee configure.out
"--without-headers" - потому что пока еще нет библиотеки newlib,
"--disable-nls" - пока еще не нужна поддержка различных человеческих языков.
Для того, чтобы появилась поддержка cortex-m3 и soft-варианта библиотек для операций с плавающей запятой, необходимо внести изменения в файл config/gcc/arm/t-arm-elf:
--- gcc/config/arm/t-arm-elf.orig    2010-09-21 18:33:40.000000000 +0400
+++ gcc/config/arm/t-arm-elf    2011-03-05 08:21:48.000000000 +0300
@@ -36,22 +36,22 @@
 MULTILIB_EXCEPTIONS  =
 MULTILIB_MATCHES     =
 
-#MULTILIB_OPTIONS      += march=armv7
-#MULTILIB_DIRNAMES     += thumb2
-#MULTILIB_EXCEPTIONS   += march=armv7* marm/*march=armv7*
-#MULTILIB_MATCHES      += march?armv7=march?armv7-a
-#MULTILIB_MATCHES      += march?armv7=march?armv7-r
-#MULTILIB_MATCHES      += march?armv7=march?armv7-m
-#MULTILIB_MATCHES      += march?armv7=mcpu?cortex-a8
-#MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
-#MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
+MULTILIB_OPTIONS      += march=armv7
+MULTILIB_DIRNAMES     += thumb2
+MULTILIB_EXCEPTIONS   += march=armv7* marm/*march=armv7*
+MULTILIB_MATCHES      += march?armv7=march?armv7-a
+MULTILIB_MATCHES      += march?armv7=march?armv7-r
+MULTILIB_MATCHES      += march?armv7=march?armv7-m
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-a8
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-r4
+MULTILIB_MATCHES      += march?armv7=mcpu?cortex-m3
 
 # Not quite true.  We can support hard-vfp calling in Thumb2, but how do we
 # express that here?  Also, we really need architecture v5e or later
 # (mcrr etc).
-MULTILIB_OPTIONS       += mfloat-abi=hard
-MULTILIB_DIRNAMES      += fpu
-MULTILIB_EXCEPTIONS    += *mthumb/*mfloat-abi=hard*
+#MULTILIB_OPTIONS       += mfloat-abi=hard
+#MULTILIB_DIRNAMES      += fpu
+#MULTILIB_EXCEPTIONS    += *mthumb/*mfloat-abi=hard*
 
 # MULTILIB_OPTIONS    += mcpu=ep9312
 # MULTILIB_DIRNAMES   += ep9312
@@ -61,9 +61,9 @@
 # MULTILIB_DIRNAMES    += le be
 # MULTILIB_MATCHES     += mbig-endian=mbe mlittle-endian=mle
 #
-# MULTILIB_OPTIONS    += mhard-float/msoft-float
-# MULTILIB_DIRNAMES   += fpu soft
-# MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
+ MULTILIB_OPTIONS    += mfloat-abi=hard/mfloat-abi=soft
+ MULTILIB_DIRNAMES   += fpu soft
+ MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard*
 #
 # MULTILIB_OPTIONS    += mno-thumb-interwork/mthumb-interwork
 # MULTILIB_DIRNAMES   += normal interwork

После сборки начального пакета gcc его нужно установить перед сборкой newlib.

3. Newlib
Здесь я использовал такие параметры сборки:
../configure --target=%{_target} --prefix=%{_prefix} \
    --enable-interwork --enable-multilib \
    --disable-newlib-supplied-syscalls \
    --with-float=soft 2>&1 | tee configure.out
"--disable-newlib-supplied-syscalls" - этот параметр отключает целый набор стандартных системных вызовов (обращение к файлу, выделение памяти и т.д.). Поскольку зачастую эти функции очень специфичны для конкретной реализации оборудования, то нужно использовать свои вызовы или ставить хотя бы заглушки.
Еще можно вставить параметр "--disable-libgloss", тогда не будет создаваться, например, библиотека crt0.o, на что будет ругаться компоновщик, и придется реализовать ее функции самостоятельно, а затем использовать при сборке программ параметры "-nostartfiles" или "-nodefaultlibs", "-nostdlib".
После сборки newlib ее нужно установить и переходить к этапу сборки полной версии gcc.

4. Полный gcc
Для этого я использовал такую конфигурацию сборки:
../configure --target=%{_target} --prefix=%{_prefix} \
     --enable-interwork --enable-multilib \
    --enable-languages="c,c++" --with-newlib \
    --with-headers=%{_prefix}/%{_target}/include \
    --disable-shared \
    --with-gnu-as --with-gnu-ld \
    --with-float=soft 2>&1 | tee configure.out

Здесь я указал путь к заголовкам уже установленной newlib. Но я пробовал собирать и без этого параметра, разницы не заметил.
Если установить этот пакет, то набор средств для разработки уже почти готов, осталось только собрать отладчик.

5. gdb
Тут все совсем просто:
../configure                                            \
    --target=%{target}                 \
    --prefix=%{_prefix}                             \
    --enable-interwork --enable-multilib
Возможно, два последних параметра и не нужны, но мне они и не помешали пока. Можно было бы собрать gdb-tui или insight, но поскольку используемая мною IDE (Code::Blocks) отлично работает именно с gdb, к тому же мне удалось с ним поработать и непосредственно в терминальном окошке, то я ограничился простым добрым gdb.



Немного о вариантах сборки пакетов

Почему-то gcc и newlib, собранные с префиксом arm-elf- при тех же параметрах и патче t-arm-elf в моем проекте ругались на плавающую запятую. Компоновщик говорил, что собранные библиотеки поддерживают формат VFP, а проект нет. В общем, надо разбираться.

Информацию о получившихся библиотеках или файлах можно получить с помощью команды arm-none-eabi-readelf -a имя_файла.
Еще можно воспользоваться командой: arm-none-eabi-objdump -p файл




понедельник, 6 сентября 2010 г.

Установка драйвера NVidia для устаревшей видеоплаты

Сегодня наконец-то удалось установить драйвер для Geforce MX 440! Для этого пришлось прочитать кучу форумов.
Делал так:
1. Загрузил с сайта NVidia пакет NVIDIA-Linux-x86-96.43.18-pkg1.run.
2. В /etc/grub.conf в конец строки для загрузки ядра добавил известную
строчку "rdblacklist=nouveau".
3. В /etc/modprobe.d/ добавил файл для предотвращения загрузки nouveau (неизвестно, влияет ли это на что-нибудь):
# echo "blacklist nouveau" >> /etc/modprobe.d/blacklist-nouveau.conf
4. В /etc/inittab указал уровень загрузки 3 и перезагрузил систему.
4. После перезагрузки из командной строки запустил установку драйвера с ключом -k: sh NVIDIA*.run -k $(uname -r)
Установка на этот раз прошла без проблем.

воскресенье, 1 августа 2010 г.

Первая запись

Опять придется разбираться с драйвером WizardPen в Fedora 13. Курсор пера просто уходит в левый верхний угол и больше не движется.