Не запускается WDT

kutukvpavel

New member
Приветствую!
Начал разбираться с Амуром (на отладке NUKE v0.3 от Теллура). Не могу почему-то запустить сторожевой таймер, код прилагается, но он практически идентичен примерам на гитхабе. HAL_WDT_Start() всегда возвращает HAL_TIMEOUT. Такое ощущение, что то ли Power Domain где-то не включен, то ли тактирование, но ведь соответствующая инициализация PCC присутствует в коде. В целом программа работает, так что CLK32M и CLK32K присутствуют. Кто-то ещё сталкивался с таким?

Пробовал все Clock Source для WDT из HAL_WDT_Clocks, пробовал увеличивать таймаут, безрезультатно.

C:
static WDT_HandleTypeDef hwdt = {};

static PCC_ConfigErrorsTypeDef SystemClock_Config(void)
{
    PCC_InitTypeDef PCC_OscInit = {0};

    PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
    PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
    PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
    PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
    PCC_OscInit.AHBDivider = 0;
    PCC_OscInit.APBMDivider = 0;
    PCC_OscInit.APBPDivider = 0;
    PCC_OscInit.HSI32MCalibrationValue = 128;
    PCC_OscInit.LSI32KCalibrationValue = 128;
    PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
    PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
    return HAL_PCC_Config(&PCC_OscInit);
}

static HAL_StatusTypeDef WDT_Init()
{
    HAL_StatusTypeDef ret;

    hwdt.Instance = WDT;
    hwdt.Init.Clock = HAL_WDT_OSC32M;
    hwdt.Init.ReloadMs = 500;
    ret = HAL_WDT_Init(&hwdt, WDT_TIMEOUT_DEFAULT);
    if (ret != HAL_OK) return ret;
    return HAL_WDT_Start(&hwdt, WDT_TIMEOUT_DEFAULT); // <--- Здесь всегда позвращает 3 (HAL_TIMEOUT)
}

HAL_StatusTypeDef my_hal_init(void)
{
    HAL_StatusTypeDef ret = HAL_OK;

    HAL_Init();
    __HAL_PCC_PM_CLK_ENABLE();
    SystemClock_Config();
    __HAL_PCC_EPIC_CLK_ENABLE();
    CHECK_ERROR(WDT_Init(), "WDT init failed");
    xputs("WDT init finished\n");

    return ret;
}

int main()
{
    HAL_StatusTypeDef init_result = my_hal_init();
    if (init_result != HAL_OK) while (1);
    while (1)
    {
        <...>
    }
}
 
Последнее редактирование:

ejsanyo

Active member
У меня код практически идентичен, но всё работает. Разница с моим кодом разве что здесь:
C:
PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_LSI32K;

PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_LSI32K;
PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_LSI32K;
Не думаю, однако, что разница критична.
Правда я у себя и коды возврата не проверял. :whistle: А вот по факту у вас собака отрабатывает сброс после инициализации или нет?
Таймаут, судя по исходнику, там может вернуть только HAL_WDT_Stop() Я бы в этом месте дебуггером и побегал.
PS Ещё мысль такая: а кварц 32 МГц у вас точно работает, или ядро сваливается снова на RC-тактирование? Тогда собака точно работать не будет.
 
Последнее редактирование:

kutukvpavel

New member
По факту не отрабатывает. В случае ошибки инициализации (моей, добавил этот момент в пост выше) я делаю бесконечный цикл, собака должна сделать ресет, соответственно. Но этого не происходит.

Возвращает таймаут именно HAL_WDT_Start, это я отладкой выяснил, инициализация возвращает HAL_OK.

Вот исходник, просто бит ENABLED никогда не поднимается. Уже складывается впечатление, что это баг железа...

C:
/**
* @brief Запустить таймер WDT.
* @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит
*                  информацию о конфигурации для модуля WDT.
* @param timeout продолжительность тайм-аута.
* @return Статус HAL.
*/
HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout)
{
    hwdt->Instance->KEY = WDT_KEY_UNLOCK;
    hwdt->Instance->KEY = WDT_KEY_START;

    while (timeout--)
    {
        if (hwdt->Instance->STA & WDT_STA_ENABLED_M)
        {
            return HAL_OK;
        }
    }

    return HAL_TIMEOUT;
}

P.S. Не заметил постскриптум, надо будет проверить. Вроде фирменная отладка, да и код верные тайминги имеет, так что не заподозрил проблемы с кварцем. Я правильно понял, что ядро автоматически может переключить клок, если кварц не раскачивается?
 
Последнее редактирование:

ejsanyo

Active member
Я правильно понял, что ядро автоматически может переключить клок, если кварц не раскачивается?
По крайней мере так было на STM32 и "ex-STM32". Посмотрите хотя бы, что там ваш SystemClock_Config() возвращает.
Я бы проверил у себя, но пока не на чем. Поделку уже отдал в цех.:whistle:
 

kutukvpavel

New member
SystemClock_Config() возвращает 4 HAL_OK.

Попробовал запустить Микроновский пример, прямо из репозитория mik32_examples, думал может с использованием SPIFI у меня как-то связано. И тоже не заработал. Но!

Изменил пример на это (добавлен вывод сообщений в зависимости от результата HAL_WDT_Start и HAL_WDT_Refresh, в оригинальном примере возвращаемые значения игнорировались):
C:
#include "mik32_hal_pcc.h"
#include "mik32_hal_wdt.h"
#include "uart_lib.h"
#include "xprintf.h"


WDT_HandleTypeDef hwdt;

void SystemClock_Config(void);
void WDT_Init(void);

/*
* В данном примере демонстрируется работа сторожевого таймера WDT.
* В начале программа инициализирует такие периферии как UART и WDT. Затем по UART отправляется строка "Start", что говорит о успешном старте программы.
* После этого запускается таймер WDT, который отсчитывает 1000 мс. Затем значение счетчика таймера сбрасывает функцией HAL_WDT_Refresh. После этого
* программа заходит в бесконечный цикл, в котором таймер досчитывает до конца и формирует сигнал сброса.
**/

int main()
{
    SystemClock_Config();

    UART_Init(UART_1, 3333, UART_CONTROL1_TE_M | UART_CONTROL1_M_8BIT_M, 0, 0);
    WDT_Init();
    xprintf("Start\n");

    /* Запуск таймера WDT */
    if (HAL_WDT_Start(&hwdt, WDT_TIMEOUT_DEFAULT) != HAL_OK) xputs("WDT start\n");

    /* Сбросить значение WDT */
    if (HAL_WDT_Refresh(&hwdt, WDT_TIMEOUT_DEFAULT) != HAL_OK) xputs("WDT refresh");
    xprintf("Refresh\n\n");

    while (1)
    {
        /* Бесконечный цикл для сброса контроллера по WDT */
    }
}

void SystemClock_Config(void)
{
    PCC_InitTypeDef PCC_OscInit = {0};

    PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
    PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
    PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
    PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
    PCC_OscInit.AHBDivider = 0;
    PCC_OscInit.APBMDivider = 0;
    PCC_OscInit.APBPDivider = 0;
    PCC_OscInit.HSI32MCalibrationValue = 128;
    PCC_OscInit.LSI32KCalibrationValue = 128;
    PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
    PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
    HAL_PCC_Config(&PCC_OscInit);
}

void WDT_Init()
{
    hwdt.Instance = WDT;

    hwdt.Init.Clock = HAL_WDT_OSC32K;
    hwdt.Init.ReloadMs = 1000;
    if (HAL_WDT_Init(&hwdt, WDT_TIMEOUT_DEFAULT) != HAL_OK)
    {
        xprintf("hAL_WDT_Init\n");
    }
}

void xputc(char c)
{
    UART_WriteByte(UART_1, c);
    UART_WaitTransmission(UART_1);
}

И заработало. Дальше интереснее. Вырезал весь UART, смотрю работоспособность только по морганию светодиодов на отладке при ресете. Перестало работать. Ага, подумал я, или где-то volatile забыто и оптимизация шалит, или где-то race-condition во время инициализации, а медленный UART 9600 в примере спасал положение. Добавил задержки:

C:
#include "mik32_hal_pcc.h"
#include "mik32_hal_wdt.h"

WDT_HandleTypeDef hwdt;

void SystemClock_Config(void);
void WDT_Init(void);

/*
* В данном примере демонстрируется работа сторожевого таймера WDT.
* В начале программа инициализирует такие периферии как UART и WDT. Затем по UART отправляется строка "Start", что говорит о успешном старте программы.
* После этого запускается таймер WDT, который отсчитывает 1000 мс. Затем значение счетчика таймера сбрасывает функцией HAL_WDT_Refresh. После этого
* программа заходит в бесконечный цикл, в котором таймер досчитывает до конца и формирует сигнал сброса.
**/

int main()
{
    SystemClock_Config();

    WDT_Init();

    /* Запуск таймера WDT */
    if (HAL_WDT_Start(&hwdt, WDT_TIMEOUT_DEFAULT) != HAL_OK)
        for (volatile int i = 0; i < 1000; i++);

    /* Сбросить значение WDT */
    if (HAL_WDT_Refresh(&hwdt, WDT_TIMEOUT_DEFAULT) != HAL_OK)
        for (volatile int i = 0; i < 1000; i++);

    while (1)
    {
        /* Бесконечный цикл для сброса контроллера по WDT */
    }
}

void SystemClock_Config(void)
{
    PCC_InitTypeDef PCC_OscInit = {0};

    PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
    PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
    PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
    PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
    PCC_OscInit.AHBDivider = 0;
    PCC_OscInit.APBMDivider = 0;
    PCC_OscInit.APBPDivider = 0;
    PCC_OscInit.HSI32MCalibrationValue = 128;
    PCC_OscInit.LSI32KCalibrationValue = 128;
    PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
    PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
    HAL_PCC_Config(&PCC_OscInit);
}

void WDT_Init()
{
    hwdt.Instance = WDT;

    hwdt.Init.Clock = HAL_WDT_OSC32K;
    hwdt.Init.ReloadMs = 1000;
    if (HAL_WDT_Init(&hwdt, WDT_TIMEOUT_DEFAULT)) for (volatile int i = 0; i < 10000; i++);
}

Пришлось поиграться с задержкой в циклах, но в итоге заработало, МК устойчиво ресетится собакой. Получается, что где-то в API HAL для WDT есть race-condition. Плохо, что про последовательность инициализации в доках ничего не сказано, пойду к первоисточнику (синтакору) искать информацию...

P.S. Не, хрень какая-то, эти задержки условные же. Всё-таки похоже больше на влияние оптимизации. Но тут ещё страннее, не работает с: O0, Os; работает с: Og, O1, O2 (разные тайминги собаки получаются, Og, O1 - как надо, O2 - ресет сразу, без задержки)...

PPS. Чёрт, вся структура WDT_TypeDef сделана на union.
 
Последнее редактирование:

ejsanyo

Active member
Я по жизни, если место в памяти позволяет, ставлю -Ofast. А с SPI флешкой на такой платформе, понятное дело, места с избытком есть всегда. :whistle:
Ещё могу сказать такой момент, что HAL_WDT_Start() я делал далеко не сразу после настройки. У меня там ещё заставка на экран выводится, контрольная сумма. А уже потом запуск собаки и основной цикл. Так что, благодаря этому всему, возможно, я проблему просто не увидел.
Глупое предположение, но...а что будет, если вначале сделать HAL_WDT_Refresh(), а потом уже HAL_WDT_Start()?
пойду к первоисточнику (синтакору) искать информацию
А разве для данного чипа Syntacore делал не только ядро? Вроде же внеядерная периферия это уже чьё-то стороннее творчество?
 

kutukvpavel

New member
Со скоростью доступа к внешней флеш-памяти в 4 раза меньшей скорости работы процессора лучше бы делать оптимизацию на уменьшение размера кода, а не наоборот. Тогда коды быстрее будут попадать в кэш и обрабатываться процессором. Кто-нибудь сделайте уже объективные тесты быстродействия с различными опциями, включая случайное чтение данных из внешней флеш-памяти блоками различной длины, от байта и до нескольких килобайт. При этом пробовать менять настройки верхней границы кеширования, а также с включением и с выключением опции кэширования данных. Заодно ещё и продемонстрировать быстродействие в различных режимах SPIFI: Single, Dual, Quad Data Output (QSPI), Quad Input/Output (QSPI) и Full Quad (QPI), а также Quad Input/Output (QSPI) + XIP и Full Quad (QPI) + XIP, то есть без отправки в запросах команд.
К слову, посмотрел ELF-ку с Os и O1. Кусок инициализации WDT, например. Оба листинга делают одно и то же: записывают два значения в два регистра WDT, одно 0x1E (immediate), другое - предварительно посчитанное, хранится в регистре (O1) или в RAM (Os).

-O1:
Код:
    *(volatile uint8_t*)(WDT_BASE_ADDRESS + 0x9C) = WDT_KEY_UNLOCK;
80000678:    000817b7              lui    a5,0x81
8000067c:    4779                    li    a4,30
8000067e:    08e78e23              sb    a4,156(a5) # 8109c <STACK_SIZE+0x80c9c>
    *(volatile uint32_t*)(WDT_BASE_ADDRESS + 0x84) = conValue;
80000682:    08a7a223              sw    a0,132(a5)

-Os:
Код:
    *(volatile uint8_t*)(WDT_BASE_ADDRESS + 0x9C) = WDT_KEY_UNLOCK;
8000098a:    000817b7              lui    a5,0x81
8000098e:    09c78793              addi    a5,a5,156 # 8109c <STACK_SIZE+0x80c9c>
80000992:    4779                    li    a4,30
80000994:    00e78023              sb    a4,0(a5)
    *(volatile uint32_t*)(WDT_BASE_ADDRESS + 0x84) = conValue;
80000998:    000817b7              lui    a5,0x81
8000099c:    08478793              addi    a5,a5,132 # 81084 <STACK_SIZE+0x80c84>
800009a0:    fec42703              lw    a4,-20(s0)
800009a4:    c398                    sw    a4,0(a5)

На мой взгляд, результат не особо соответствует ожиданиям. Бросается в глаза, что Os считает адрес два раза. Конечно, выводы по производительности тут делать трудно, я не нашёл у SCR-1 информации по числу циклов на инструкцию (только на некоторые, и в этой таблице нет псевдо-инструкций).

Возвращаясь к вопросу о WDT, сдаётся мне, что не работает именно более длинный листинг не случайно, а из-за автоблокировки регистров WDT через 15 тактов после UNLOCK. Возможно поэтому ejsanyo и не заметил проблем на Ofast (я, кстати, заметил, но ожидаемые - ReloadMs не соблюдается, что-то там O3 оптимизирует...). Попробую сделать инициализацию WDT на ассемблере, и посмотреть, исправит ли это ситуацию.

PS. Это я поменял в исходниках hwdt->Instance->KEY = WDT_KEY_UNLOCK на *(volatile uint8_t*)(WDT_BASE_ADDRESS + 0x9C) = WDT_KEY_UNLOCK; т.к. не хотел разбираться есть ли где-то UB с union-ом. Ничего не поменялось, значит union не виноват.
 
Последнее редактирование:

ejsanyo

Active member
Кто-нибудь сделайте уже объективные тесты быстродействия с различными опциями
Ну кое-что, смотрю, написали даже в местной Wiki. Не очень понятно, правда, насколько оно объективно, но вроде как -Ofast получился в большинстве случаев слегка быстрее.
 

kutukvpavel

New member
Заменил везде в HAL доступ к WDT_TypeDef на ассемблерные вставки, завёрнутые в функции.
C:
void Write_Word_To_CON(WDT_HandleTypeDef* hwdt, uint32_t conValue)
{
    intptr_t ptr = (intptr_t)(hwdt->Instance);
    asm volatile(
        "li a0,0x1E\n\t" //Store unlock byte somewhere
        "sb a0,0x9C(%0)\n\t" //Write UNLOCK byte into WDT KEY register
        "sw %1,0x84(%0)\n\t" //Write
        :
        : "r" (ptr), "r" (conValue)
        : "a0"
    );
}
void Write_Byte_To_KEY(WDT_HandleTypeDef* hwdt, uint8_t key)
{
    intptr_t ptr = (intptr_t)(hwdt->Instance);
    asm volatile(
        "li a0,0x1E\n\t" //Store unlock byte somewhere
        "sb a0,0x9C(%0)\n\t" //Write UNLOCK byte into WDT KEY register
        "sb %1,0x9C(%0)\n\t" //Write
        :
        : "r" (ptr), "r" (key)
        : "a0"
    );
}

Уровень оптимизации перестал влиять на работоспособность WDT. Убрал все задержки из примера, по прежнему работает:
C:
#include "mik32_hal_pcc.h"
#include "mik32_hal_wdt.h"

WDT_HandleTypeDef hwdt;

void SystemClock_Config(void);
void WDT_Init(void);

/*
* В данном примере демонстрируется работа сторожевого таймера WDT.
* В начале программа инициализирует такие периферии как UART и WDT. Затем по UART отправляется строка "Start", что говорит о успешном старте программы.
* После этого запускается таймер WDT, который отсчитывает 1000 мс. Затем значение счетчика таймера сбрасывает функцией HAL_WDT_Refresh. После этого
* программа заходит в бесконечный цикл, в котором таймер досчитывает до конца и формирует сигнал сброса.
**/

int main()
{
    SystemClock_Config();

    WDT_Init();

    /* Запуск таймера WDT */
    HAL_WDT_Start(&hwdt, WDT_TIMEOUT_DEFAULT);

    /* Сбросить значение WDT */
    HAL_WDT_Refresh(&hwdt, WDT_TIMEOUT_DEFAULT);

    while (1)
    {
        /* Бесконечный цикл для сброса контроллера по WDT */
    }
}

void SystemClock_Config(void)
{
    PCC_InitTypeDef PCC_OscInit = {0};

    PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
    PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
    PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
    PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
    PCC_OscInit.AHBDivider = 0;
    PCC_OscInit.APBMDivider = 0;
    PCC_OscInit.APBPDivider = 0;
    PCC_OscInit.HSI32MCalibrationValue = 128;
    PCC_OscInit.LSI32KCalibrationValue = 128;
    PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
    PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
    HAL_PCC_Config(&PCC_OscInit);
}

void WDT_Init()
{
    hwdt.Instance = WDT;

    hwdt.Init.Clock = HAL_WDT_OSC32K;
    hwdt.Init.ReloadMs = 1500;
    if (HAL_WDT_Init(&hwdt, WDT_TIMEOUT_DEFAULT) != HAL_OK);
}

Пойду открою pull-request, что ли.
 

kutukvpavel

New member
И ещё кое-что, для программ, выполняемых через SPIFI, время доступа к памяти выше, а cache miss так и вовсе может всё испортить. Поэтому в случае использования флешки, нужно функции записи в WDT поместить в RAM:
C:
static void __attribute__( ( noinline, section(".data") ) ) HAL_WDT_Write_Word_To_CON(WDT_HandleTypeDef* hwdt, uint32_t conValue);
static void __attribute__( ( noinline, section(".data") ) ) HAL_WDT_Write_Byte_To_KEY(WDT_HandleTypeDef* hwdt, uint8_t key);
Наконец, у меня работает WDT в моей прошивке, исполняемой с флешки.
 

ejsanyo

Active member
C:
Код:
static void __attribute__( ( noinline, section(".data") ) ) HAL_WDT_Write_Word_To_CON(WDT_HandleTypeDef* hwdt, uint32_t conValue);
static void __attribute__( ( noinline, section(".data") ) ) HAL_WDT_Write_Byte_To_KEY(WDT_HandleTypeDef* hwdt, uint8_t key);
Ага, так вот каким заклинанием в местных сях код помещается в оперативу!:unsure:
 

ejsanyo

Active member
Добрался наконец до очередной самоделки и попробовал на ней собаку, но с той разницей, что у меня в данном случае кварцев нет. И...собака на RC-генераторах у меня не завелась вообще ни в какую. Попробовал прикрутить процедуры записи в регистры от kutukvpavel с теми самыми атрибутами: компилятор выдаёт кучу сообщений про них Warning: dwarf line number information for .data ignored, что бы это ни значило. 🤨 Хотя как-то всё равно компиляет. Ну а собака...всё равно не работает. В общем, она только с кварцем 32 МГц у меня заработала пока что. Остаётся предполагать, что это какие-то аппаратные проблемы, баги.
 
Последнее редактирование:

khristolyubov

New member
Команда форума
Ага, так вот каким заклинанием в местных сях код помещается в оперативу!:unsure:
А ещё можно в секцию .data перенести нужные функции на этапе линковки.
Подсмотрел вот здесь:
https://community.infineon.com/t5/DAVE/Specify-location-of-functions-from-libgcc/td-p/307093#.
https://community.nxp.com/t5/S32-De...-from-RAM-memory-using-GNU-build/ta-p/1106568

Ниже ld скрипт для SPIFI, в котором на пробу переношу некоторые функции gcclib в ram. Работает.

Код:
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
OUTPUT_ARCH(riscv)


ENTRY(_start)


MEMORY {
  rom (RX): ORIGIN = 0x80000000, LENGTH = 256M
  ram (RWX): ORIGIN = 0x02000000, LENGTH = 16K
}


STACK_SIZE = 1024;


CL_SIZE = 16;


SECTIONS {


    /DISCARD/ : {
        *(.debug_info)
        *(.debug_abbrev)
        *(.debug_loc)
        *(.debug_aranges)
        *(.debug_line)
        *(.debug_str)
        *(.debug_ranges)
        *(.debug_macro)
        *(.debug_frame)
        *(.eh_frame .eh_frame.*)
    }


    .text ORIGIN(rom) : {
        PROVIDE(__TEXT_START__ = .);
        *crt0.o(.text .text.*)
        *(.text.smallsysteminit)
        *(.text.SmallSystemInit)
        . = 0xC0;
        KEEP(*crt0.o(.trap_text))


        /* Exclude from .text */
        *(EXCLUDE_FILE(*libgcc.a:*_lshrdi3.o *_ashldi3.o *_clzsi2.o *_divdi3.o *_moddi3.o *_udivdi3.o *_umoddi3.o *_clz.o) .text .text.* .gnu.linkonce.s.*)




        *(.rodata)
        *(.rodata.*)    
        . = ALIGN(CL_SIZE);
        PROVIDE(__TEXT_END__ = .);
    } >rom


    .data :
    AT( __TEXT_END__ ) {
        PROVIDE(__DATA_START__ = .);
        _gp = .;
        *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
        *(.sdata .sdata.* .gnu.linkonce.s.*)
        *(.data .data.*)


        /* Include in .data */
        *libgcc.a:*_lshrdi3.o *_ashldi3.o *_clzsi2.o *_divdi3.o *_moddi3.o *_udivdi3.o *_umoddi3.o *_clz.o(.text .text.* .gnu.linkonce.s.*)


        . = ALIGN(CL_SIZE);
    } >ram
   
    __DATA_IMAGE_START__ = LOADADDR(.data);
    __DATA_IMAGE_END__ = LOADADDR(.data) + SIZEOF(.data);
    ASSERT(__DATA_IMAGE_END__ < ORIGIN(rom) + LENGTH(rom), "Data image overflows rom section")


    /* thread-local data segment */
    .tdata : {
        PROVIDE(_tls_data = .);
        PROVIDE(_tdata_begin = .);
        *(.tdata .tdata.*)
        PROVIDE(_tdata_end = .);
        . = ALIGN(CL_SIZE);
    } >ram


    .tbss : {
        PROVIDE(__BSS_START__ = .);
        *(.tbss .tbss.*)
        . = ALIGN(CL_SIZE);
        PROVIDE(_tbss_end = .);
    } >ram


    /* bss segment */
    .sbss : {
        *(.sbss .sbss.* .gnu.linkonce.sb.*)
        *(.scommon)
    } >ram


    .bss : {
        *(.bss .bss.*)
        . = ALIGN(CL_SIZE);
        PROVIDE(__BSS_END__ = .);
    } >ram


    _end = .;
    PROVIDE(__end = .);


    /* End of uninitalized data segement */


    .stack ORIGIN(ram) + LENGTH(ram) - STACK_SIZE : {
        FILL(0);
        PROVIDE(__STACK_START__ = .);
        . += STACK_SIZE;
        PROVIDE(__C_STACK_TOP__ = .);
        PROVIDE(__STACK_END__ = .);
    } >ram
}
 
Последнее редактирование:

khristolyubov

New member
Команда форума
Да, видел такое. Приведу ниже, то что мне ответила на это нейросетка. Для себя понял, что влияет эта штука только на отладку и мне пока что оно не мешает. Как будет мешать буду разбираться подробнее.

Markdown (GitHub flavored):
The warning message **"DWARF line number information for .data ignored"** is related to the Debug With Arbitrary Record Formats (DWARF) debugging information format, commonly used in debugging information for programs. This format includes details like line numbers, variable names, and data types, which help debuggers map machine code back to the source code.

Here's what the warning means in context:

### 1. **DWARF Debug Information**
   - **DWARF** is a widely-used, standardized debugging data format that describes the relationship between the compiled machine code and the source code.
   - It is usually associated with the program's instructions (.text section) to allow debuggers to trace execution back to the corresponding line in the source code.

### 2. **.data Section**
   - The **.data** section of an executable contains initialized global and static variables.
   - Unlike the **.text** section, which contains the executable code, the **.data** section is for storing data values.

### 3. **Line Number Information**
   - Line number information typically refers to where in the source code a particular instruction or variable is defined.
   - For executable code (in the .text section), this information is crucial for debugging, as it allows a developer to see which line of code is being executed.

### 4. **The Warning Explanation**
   - The warning **"DWARF line number information for .data ignored"** means that the compiler or linker has encountered line number information that references the **.data** section.
   - However, line number information does not apply to data sections, as these sections contain variable values, not executable instructions.
   - As a result, this line number information is ignored since it is not useful or applicable for debugging.

### 5. **Impact on Your Program**
   - This warning does not indicate a problem with your code or the generated program.
   - It simply means that some debug information, which isn't applicable to the **.data** section, was discarded.
   - The generated executable should still run as expected, and the debugging of code (in the **.text** section) should work fine.

### 6. **Possible Causes**
   - This could occur due to a toolchain or compiler bug, or it might just be a benign artifact of how your code or its debugging information is structured.
   - It may also happen if the compiler generates some debug info related to static or global variables that it doesn't need.

### 7. **What You Can Do**
   - Generally, you can safely ignore this warning.
   - If it concerns you, consider checking for updates to your toolchain or reviewing the compilation and linking process to ensure nothing is being misconfigured.
   - If you are writing inline assembly or doing something non-standard, review how DWARF info is being generated.

This warning is generally not something to worry about unless you're seeing other issues in your debugging process or program execution.
 

kutukvpavel

New member
Может вы тогда ещё знаете, что это было за загадочное "dwarf line number information for .data ignored"? Что-то про..."гномиков"? 🧝‍♂️
В целом нейросетка права, DWARF это формат отладочной информации. Line Number - номер строки в файле исходного кода. Для этих функций при отладке не будет информации о том, где их исходный код, отладчик не сможет перейти автоматически к нужной строке. Всё.
 
Сверху