|
ARM, C++, IAR. Проблема., STM32F4 |
|
|
|
Nov 11 2012, 22:02
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-07-12
Пользователь №: 72 756

|
Всем добрый день! Возникла проблема следующего рода. При компиляции проекта на С++, программа стопорится при попытке вызова системного прерывания. Используется IAR версии 6.40.2, стандартные библиотеки CMSIS. Конкрентно виснет на функции delay(), которая реализована следующим образом: Код // Функция задержки (паузы) в работе void Delay(__IO uint32_t nTime) { TimingDelay = nTime;
// Крутимся в бесконечном цикле, пока счетчик // оставшегося времени не станет равным нулю. // Уменьшение счетчика происходит с помощью // прерываний системного таймера. while(TimingDelay != 0); }
// Функция уменьшения счетчика задержки (паузы) void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } } В файле stm32f4xx_it.c определяем функцию Код void SysTick_Handler() { TimingDelay_Decrement(); } Виснет в файле startup_stm32f4xx.s в блоке Код PUBWEAK SysTick_Handler SECTION .text:CODE:REORDER(1) SysTick_Handler B SysTick_Handler /// !!!!!!!! Вот тут останавливается исполнение. То есть как я понимаю, не может найти реализацию функции SysTick_Handler(). Когда проект был на С, данный код работал. Может кто знает, как его заставить работать на С++ ?
|
|
|
|
|
Nov 11 2012, 22:27
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Geniok @ Nov 12 2012, 00:02)  То есть как я понимаю, не может найти реализацию функции SysTick_Handler().
Когда проект был на С, данный код работал. Может кто знает, как его заставить работать на С++ ? Что-то мне кажется что это где-то было... Можно попробовать например 1) Код extern "C" void SysTick_Handler() { //код обработчика } 2) Вариант посложней Отредактировать хидеры от ST Код #ifdef __cplusplus extern "C" { #endif
#include <stdint.h>
/******************************************************************************* ************************** GLOBAL VARIABLES ******************************* ******************************************************************************/
extern uint32_t SystemCoreClock; /**< System Clock Frequency (Core Clock) */
/******************************************************************************* ***************************** PROTOTYPES ********************************** ******************************************************************************/
/* Interrupt routines - prototypes */ void Reset_Handler(void); void NMI_Handler(void); void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); // и так далее #ifdef __cplusplus } #endif Ну и так далее - думаю там много чего можно добавить или выкинуть.
|
|
|
|
|
Nov 11 2012, 22:30
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Geniok @ Nov 12 2012, 00:02)  В файле stm32f4xx_it.c определяем функцию Код void SysTick_Handler() { TimingDelay_Decrement(); } Странно. Обработчик-то определен в файле с расширением С, он должен вызываться, только до этого не должно дойти, должна быть ошибка линковки, если TimingDelay_Decrement(); определена в C++ файле. Или у него в режиме компиляции С++ все файлы компилируются в С++ режиме? Попробуйте Код #ifdef __cplusplus extern "C" #endif void SysTick_Handler() { TimingDelay_Decrement(); }
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 11 2012, 22:43
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-07-12
Пользователь №: 72 756

|
Цитата(_Артём_ @ Nov 12 2012, 02:27)  Что-то мне кажется что это где-то было... Можно попробовать например 1) Код extern "C" void SysTick_Handler() { //код обработчика } Первый вариант помог, спасибо! На всякий случай, если кому пригодится в файле stm32f4xx_it.h объявляем Код extern "C" { void SysTick_Handler(void); } а потом уже в файле stm32f4xx_it.с пишем Код extern "C" { void SysTick_Handler() { TimingDelay_Decrement(); } } Пробовал такой вариант, в начале файла stm32f4xx_it.с ставить Код #ifdef __cplusplus extern "C" { #endif
.......
в конце файла
#ifdef __cplusplus } #endif начинают всплывать куча ошибок при компиляции.
|
|
|
|
|
Nov 11 2012, 23:30
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-07-12
Пользователь №: 72 756

|
Цитата(ReAl @ Nov 12 2012, 02:30)  Странно. Обработчик-то определен в файле с расширением С, он должен вызываться, только до этого не должно дойти, должна быть ошибка линковки, если TimingDelay_Decrement(); определена в C++ файле. Или у него в режиме компиляции С++ все файлы компилируются в С++ режиме? Скорее всего для С++ компилятора расширения с и срр едины. Ну и соответственно компиляция должна быть в режиме С++. Цитата(Geniok @ Nov 12 2012, 02:48)  Вопрос еще возник такой, может кто знает, возможна ли своя замена файла stm32f4xx_it.с ? То есть возможно ли все обработчики прописать в файле "MyFile.cpp" и чтобы при вызове прерывания перенаправление было туда, а не к stm32f4xx_it.с ? Ответ уже нашел! Спасибо всем, кто отозвался! С Уважением!
Сообщение отредактировал Geniok - Nov 11 2012, 23:30
|
|
|
|
|
Nov 12 2012, 07:50
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Geniok @ Nov 12 2012, 01:30)  Скорее всего для С++ компилятора расширения с и срр едины. Ну и соответственно компиляция должна быть в режиме С++. Насколько помню, там в настройках было три варианта: 1)Программист лох, не смог правильно обозвать файлы, на самом деле они все С 2)Программист лох, не смог правильно обозвать файлы, на самом деле они все С++ 3)Компилить C/C++в зависимости от расширения файла. И если вы выбрали один из первых двух - кто злобный Буратина?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 22 2012, 18:25
|

Местный
  
Группа: Свой
Сообщений: 202
Регистрация: 30-10-10
Пользователь №: 60 535

|
Что бы не плодить лишних тем, рушил написать сюда. Итак компилятор IAR 6.40 чип stm32f100 часть проекта уже написана на С, и сейчас решил остальное дописать на С++ поэтому поставил в настройках галку Auto на вкладке С/С++ compiler
и написал простенький класс: Код // class.h #include "stm32f10x.h"
#define MAX_BUF_UART 10
class UART1 { protected : uint8_t buf [MAX_BUF_UART]; static uint8_t current, send_point; public : UART1(void) { current = 0; send_point = 0; } uint8_t cop_buf(uint8_t byte); void start_send(void); }; Код class.cpp #include "stm32f10x.h" #include "class_UART.h"
#define current this->current #define send_point this->send_point
uint8_t UART1::cop_buf(uint8_t byte) { ..... buf[current] = byte; current++; current %= MAX_BUF_UART; return 0; }
void UART1::start_send(void) { for(; send_point != current; send_point++) { USART1->DR = buf[send_point]; while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); send_point %= MAX_BUF_UART; }; }
void testcpp(void) { UART1 port; port.cop_buf('t'); ...... port.start_send(); } далее testcpp() вызываю в в ф-ции main и ругается линковщик Код Error[Li005]: no definition for "testcpp" [referenced from Z:\bla-...-bla-bla\Obj\main.o] хотя её объявление перед main присутствует; и еще почему то не удается сделать UART1 port глобальным объектом (вынести перед void testcpp(void)) в этом случае добавляются такие error : Код Error[Li005]: no definition for "UART1::current" [referenced from Z:\bla-...-bla-bla\Obj\class_UART.o] Error[Li005]: no definition for "UART1::send_point" [referenced from Z:\bla-...-bla-bla\Obj\class_UART.o] что здесь не так? плюсы знаю не очень, как это подружить с IAR? есть какие-нибудь примеры под него? гугл ничего не дал
|
|
|
|
|
Nov 22 2012, 20:23
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Интересно, в чём смысл этих макросов: Цитата(MK2 @ Nov 22 2012, 20:25)  #define current this->current #define send_point this->send_point ? Цитата(MK2 @ Nov 22 2012, 20:25)  и еще почему то не удается сделать UART1 port глобальным объектом (вынести перед void testcpp(void)) в этом случае добавляются такие error : Код Error[Li005]: no definition for "UART1::current" [referenced from Z:\bla-...-bla-bla\Obj\class_UART.o] Error[Li005]: no definition for "UART1::send_point" [referenced from Z:\bla-...-bla-bla\Obj\class_UART.o] что здесь не так? плюсы знаю не очень, как это подружить с IAR? есть какие-нибудь примеры под него? гугл ничего не дал Видимо надо объчвить переменные send_point и пт. Код uint8_t UART1::send_point;
|
|
|
|
|
Nov 22 2012, 20:26
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (MK2 @ Nov 22 2012, 20:25)  далее testcpp() вызываю в в ф-ции main и ругается линковщик CODE Error[Li005]: no definition for "testcpp" [referenced from Z:\bla-...-bla-bla\Obj\main.o] хотя её объявление перед main присутствует; А main() находится в .c или .cpp? Если в .c, то в определении функции в файле class.cpp вы должны указать ей спецификатор extern "C": CODE extern "C" void testcpp(void) { ..... } QUOTE (MK2 @ Nov 22 2012, 20:25)  и еще почему то не удается сделать UART1 port глобальным объектом Так вы же эти две переменные указали статическими. Зачем - непонятно (буфер у вас нестатический), но раз уж вы их так объявили, то должны и определить их в глобальной области видимости: CODE uint8_t UART1::current = 0, UART1::send_point = 0; UART1 port;
extern "C" void testcpp(void) { ..... } А то, что ошибки не было когда вы объявляли объект локально объясняется очень просто: ваша функция testcpp() не прилинковывалась и упомянутый в ней объект линкер не использовал.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 22 2012, 21:14
|

Местный
  
Группа: Свой
Сообщений: 202
Регистрация: 30-10-10
Пользователь №: 60 535

|
Цитата(_Артём_ @ Nov 22 2012, 23:23)  Интересно, в чём смысл этих макросов: я поначалу думал что ошибки с переменными идут от того что надо к ним обращаться через указатель this, поэтому что бы не исправлять написал такой макрос Цитата(Сергей Борщ @ Nov 22 2012, 23:26)  А main() находится в .c или .cpp? Если в .c, то в определении функции в файле class.cpp вы должны указать ей спецификатор extern "C": Да, main в .с файле. extern тоже применял, но только наверно к main ф-ции, сегодня попробую так. Цитата(Сергей Борщ @ Nov 22 2012, 23:26)  Так вы же эти две переменные указали статическими. Зачем - непонятно (буфер у вас нестатический), это мой косяк - буфер должен быть статическим. Цитата(Сергей Борщ @ Nov 22 2012, 23:26)  но раз уж вы их так объявили, то должны и определить их в глобальной области видимости: [code]uint8_t UART1::current = 0, UART1::send_point = 0; UART1 port; я их специально в protected объявил, что бы они не были доступны из вне, а теперь они получаются будут глобальными переменными? Или все-таки в пределах модуля, но тогда поидеи перед ними static требуется
|
|
|
|
|
Nov 22 2012, 21:33
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(MK2 @ Nov 22 2012, 23:14)  Да, main в .с файле. extern тоже применял, но только наверно к main ф-ции, сегодня попробую так. Мне так кажется, что ИАРу фиолетово - с или cpp. По крайней мере иногда... Цитата(MK2 @ Nov 22 2012, 23:14)  я их специально в protected объявил, что бы они не были доступны из вне, а теперь они получаются будут глобальными переменными? Глобальными они будут, но доступны будут тольке тем, кому положено. Цитата(MK2 @ Nov 22 2012, 23:14)  но тогда поидеи перед ними static требуется У вас же не Си, и смысл static другой - статическая переменная будет одна на все экземпляры одного типа.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|