У меня очень странная проблема. Мне кажется, что это известная проблема, но я не могу найти никаких реальных решений или каких-либо твердых объяснений этого.
Вот моя установка:
Ведущий: ПК Win7, много оперативной памяти.
Цель: STM32F303RE Cortex M4 @ 64 МГц, на плате Nucleo32 со встроенным ST-LINK 2.1
Toolchain: uVision V5.16
Символы препроцессора: USE_STDPERIPH_DRIVER, STM32F303xE, __ CPLUSPLUS__FPU_PRESENT, __ FPU_USED
Разное Управление: —C99 —cpp
Все хорошо строит. Все оптимизации отключены.
Проблема во время выполнения. Процессор оказывается в обработчике hardfault после нескольких экземпляров объекта C ++. Где именно? Я отметил это, разделив мой фрагмент кода. Теперь я немного знаком с деталями и внутренними принципами C ++, но, похоже, у меня та же проблема, что и у этого парня: Ошибка сегментации, вызванная / устраненная путем изменения порядка файлов исходного кода в Makefile
Но также, неясное решение объясняется. Возможно, это не экземпляр C ++ по вине. Хотя решения не найдено. Вот суть моей программы, которая демонстрирует проблему: этот первый раздел кода «кажется» работает хорошо, пока блок раздела, который я выделил для вашего внимания.
#include "main.h" #include "stm32f30x.h" #include "stdint.h" #include "stdio.h" #include "string.h" #include "math.h" #include "usart.h" # include "can.h" #include "utils.h" #include "led.h" #include "i2c.h" #include "sabertooth.h" #include "FuzzyRule.h" #include "FuzzyComposition.h" #include "Fuzzy.h" #include "FuzzyRuleConfter.h" #include "FuzzyOutput.h" #include "FuzzyInput.h" #include "FuzzyIO.h" # include "FuzzySet.h" #include "FuzzyRuleAntecedent.h" Нечеткий * нечеткий = новый Нечеткий (); int main (void) { / ************************************* * Вход 1 ************************************ / // Два набора "пересечения рампы" для rowWidth, т.е. "допуск" строки FuzzyInput * rowWidth = new FuzzyInput (1); FuzzySet * lowTolerance = новый FuzzySet (0.0f, 0.0f, 0.0f, 120.0f); rowWidth-> addFuzzySet (lowTolerance); FuzzySet * highTolerance = новый FuzzySet (0.0f, 120.0f, 120.0f, 120.0f); rowWidth-> addFuzzySet (highTolerance); Нечетко-> addFuzzyInput (rowWidth); USART1_puts ("ширина строки добавлена как нечеткий ввод .."); / ************************************* * Вход 2 ************************************ / // Пять наборов для "разницы между расстояниями R и L" FuzzyInput * distDiff = new FuzzyInput (2); FuzzySet * tooFarRight = новый FuzzySet (-60.0f, -60.0f, -54.0f, -30.0f); distDiff-> addFuzzySet (tooFarRight); FuzzySet * right = новый FuzzySet (-54.0f, -30.0f, -30.0f, 0.0f); distDiff-> addFuzzySet (справа); FuzzySet * центрированный = новый FuzzySet (-30,0f, 0,0f, 0,0f, 30,0f); distDiff-> addFuzzySet (по центру); FuzzySet * left = новый FuzzySet (0.0f, 30.0f, 30.0f, 54.0f); distDiff-> addFuzzySet (слева); FuzzySet * tooFarLeft = новый FuzzySet (30.0f, 54.0f, 60.0f, 60.0f); distDiff-> addFuzzySet (tooFarLeft); Нечетко-> addFuzzyInput (distDiff); USART1_puts («центрирование dist добавлено как нечеткий вход ...»); / ************************************* * Выход 1 ************************************ / FuzzyOutput * motorSpeedDiff = new FuzzyOutput (1); // Семь комплектов для режимов рулевого управления (закрыть узкие, дальние - шире) FuzzySet * hardRight = новый FuzzySet (-30.0f, -30.0f, -30.0f, -15.0f); motorSpeedDiff-> addFuzzySet (hardRight); USART1_puts ( "\ thardRight"); FuzzySet * lightRight = новый FuzzySet (-15.0f, -5.0f, -5.0f, 0.0f); motorSpeedDiff-> addFuzzySet (lightRight); USART1_puts ( "\ tlightRight");
Это последнее последовательное сообщение, которое я вижу в терминале «lightRight». При следующем вызове нового FuzzySet () ниже этой строки возникает серьезная ошибка.
FuzzySet * nomRight = новый FuzzySet (-30.0f, -15.0f, -15.0f, -5.0f); motorSpeedDiff-> addFuzzySet (nomRight); USART1_puts ( "\ tnomRight"); FuzzySet * lightLeft = новый FuzzySet (0.0f, 5.0f, 5.0f, 15.0f); motorSpeedDiff-> addFuzzySet (lightLeft); USART1_puts ( "\ tlightLeft"); FuzzySet * goStraight = новый FuzzySet (-5,0f, 0,0f, 0,0f, 5,0f); motorSpeedDiff-> addFuzzySet (goStraight); USART1_puts ( "\ tgoStraight"); FuzzySet * nomLeft = новый FuzzySet (5.0f, 15.0f, 15.0f, 30.0f); motorSpeedDiff-> addFuzzySet (nomLeft); USART1_puts ( "\ tnomLeft"); FuzzySet * hardLeft = новый FuzzySet (15.0f, 30.0f, 30.0f, 30.0f); motorSpeedDiff-> addFuzzySet (hardLeft); USART1_puts ( "\ thardLeft"); Нечетко-> addFuzzyOutput (motorSpeedDiff); USART1_puts («рулевое управление двигателем добавлено как нечеткий выход»); lotsMoreSetupCode (); в то время как (1) { USART1_puts ( "Готово!"); остановки (1); // Мерцание светодиода навсегда } }
Ясно, что я просто делаю кучу этих нечетких наборов, каждый из которых представляет собой набор из 4-х чисел, но где-то летит указатель le-wild?
Вот конструктор, найденный в FuzzySet.cpp: (Часть библиотеки нечеткой логики, которую я не писал). Эта ЖЕ программа работает на Arduino, но не на этом процессоре. Разница с компилятором?
[/ NOEDIT]
FuzzySet::FuzzySet(){ } FuzzySet::FuzzySet(float a, float b, float c, float d){ this->a = a; this->b = b; this->c = c; this->d = d; this->pertinence = 0.0; }
Это звучит как что-то, связанное со статическими переменными, доступ к которым имеют другие статически объявленные функции в других контекстах.
Но я ничего не объявил статичным.
Кто-то в ссылке на обмен стека говорит, что это может быть ошибка компоновщика. Ты согласен? Как это починить?
Есть идеи о том, что на самом деле происходит?
Я установил хороший обработчик сложных ошибок, который печатает информацию о регистре, но, очевидно, ошибка происходит еще до main (). Поэтому переход к ассемблерному коду, когда все перемешано, не кажется полезным.
Как это сделать? Спасибо за ваш опыт C ++!
Попробуйте изменить кучу и размер стека вашего кода в соответствии с микроконтроллером, который вы используете из файла startup_stm32fxxx.s
вот пример
;******************** (C) COPYRIGHT 2016 STMicroelectronics ********************
;* File Name : startup_stm32f407xx.s
;* Author : MCD Application Team
;* Version : V2.4.3
;* Date : 22-January-2016
;* Description : STM32F407xx devices vector table for MDK-ARM toolchain.
;* This module performs:
;* - Set the initial SP
;* - Set the initial PC == Reset_Handler
;* - Set the vector table entries with the exceptions ISR address
;* - Branches to __main in the C library (which eventually
;* calls main()).
;* After Reset the CortexM4 processor is in Thread mode,
;* priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>
;*******************************************************************************
;
;* Redistribution and use in source and binary forms, with or without modification,
;* are permitted provided that the following conditions are met:
;* 1. Redistributions of source code must retain the above copyright notice,
;* this list of conditions and the following disclaimer.
;* 2. Redistributions in binary form must reproduce the above copyright notice,
;* this list of conditions and the following disclaimer in the documentation
;* and/or other materials provided with the distribution.
;* 3. Neither the name of STMicroelectronics nor the names of its contributors
;* may be used to endorse or promote products derived from this software
;* without specific prior written permission.
;*
;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS";* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
;*******************************************************************************
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x200 ; <your stack size>
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x400 ; <your heap size>
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
Значение стека устанавливается этой строкой
Stack_Size EQU 0x200 ; <your stack size>
и куча
Heap_Size EQU 0x400 ; <your heap size>
В Keil uVision у вас также есть 2 вкладки в левом нижнем углу, где вы можете переключаться между «Текстовым редактором» и «Мастером настройки», чтобы изменить кучу кода и размеры стека.
Других решений пока нет ...