121 Востаннє редагувалося taburyak (19.10.2018 11:30:58)

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

А буфера точно вистачає?

з головою. якщо після %f ще додати "volt",

char bufStr[64];
sprintf(bufStr, "WARNING voltage %s %f volt", voltageStruct->name, voltageStruct->voltage);
logerUART(bufStr);

то "volt" пишеться в терміналі все ок. А от значення напруги voltageStruct->voltage - немає. Я не розумію в чому справа.

122

Re: STM32, Atolic TrueStudio, CubeMX

Гм...
https://stackoverflow.com/questions/276 … formatting

Due to some performance reasons %f is not included in the Arduino's implementation of sprintf(). A better option would be to use dtostrf()

Подякували: leofun01, taburyak2

123

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

Гм...
https://stackoverflow.com/questions/276 … formatting

Due to some performance reasons %f is not included in the Arduino's implementation of sprintf(). A better option would be to use dtostrf()

В мене не arduin'ка, але таки мабуть sprintf урізаний для МК. І шо тепер робить?

124

Re: STM32, Atolic TrueStudio, CubeMX

Гм. Так там же написано.

125 Востаннє редагувалося ReAl (19.10.2018 13:59:36)

Re: STM32, Atolic TrueStudio, CubeMX

Я надовго був пропав, бо справи. Але ж сповіщення у пошту падають, то тут мушу таки зайти.

koala написав:

Гм. Так там же написано.

Про dtostrf? Так його нема в newlib (чи в newlib-nano, забув) для stm32.

Доберуся додому, згадаю, що тут треба зробити.

Подякували: taburyak, koala2

126

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

Гм. Так там же написано.

Я ж написав - в мене не ардуіна.

Подякували: koala1

127 Востаннє редагувалося ReAl (20.10.2018 08:44:12)

Re: STM32, Atolic TrueStudio, CubeMX

Спочатку коротко про функції «на цю тему».

З ascii to binary легше — strto[dfl], ato[ilf] є у стандарті, в glibc, в avr-libc і в newlib в arm-none-eabi

А от навпаки — binary to ascii — біда. Вони нестандартні і де є одне, де інше. itoa є для avr і arm-none-eabi, але нема у «великій» libc, dtostr* є з цих лише для avr, стара добра fcvt зовсім стара (застаріла, рекомендують використовувати s[n]printf, хоча у зовсім старі часи *printf працювали через неї) є у glibc і newlib, але нема для avr.

До речі, сам avr-libc має три рівня *printf — зовсім простий (ширини полів на зразок %8d ігноруються), стандартний (практично повний функціонал, здається, нема лише змінної ширини поля %*d, ну і без floating) і повний, з floating. Керується на рівні команд лінкеру, просто в arduino вирішили зекономити.

arm-none-aebi — аналогічно, підтримку floating point потрібно увімкнути на рівні лінкера (scanf ен згадувати, якщо не потрібен).
У мене в Makefile так

    LD_FLAGS    += --specs=nano.specs -Wl,-u,_printf_float,-u,_scanf_float

Все самописне, TrueStudio ніяк не поставлю (з літа я по кісточки — головою вниз — у ядрі лінукса, не до мікроконтролерів).

Подякували: NaharD, leofun01, taburyak3

128 Востаннє редагувалося taburyak (20.10.2018 19:11:35)

Re: STM32, Atolic TrueStudio, CubeMX

ReAl написав:

arm-none-aebi — аналогічно, підтримку floating point потрібно увімкнути на рівні лінкера (scanf ен згадувати, якщо не потрібен).
У мене в Makefile так

    LD_FLAGS    += --specs=nano.specs -Wl,-u,_printf_float,-u,_scanf_float

Все самописне, TrueStudio ніяк не поставлю (з літа я по кісточки — головою вниз — у ядрі лінукса, не до мікроконтролерів).

Дякую за науку. Таки так, перемкнувся з NewLib -nano на NewLib -standart і все запрацювало. Щоправда бінарник потовстішав, але не критично, все має влізти.

129 Востаннє редагувалося taburyak (20.10.2018 21:17:09)

Re: STM32, Atolic TrueStudio, CubeMX

Хлопці!
Хто в темі по FATFS для мікроконтролерів?
Писати текстові рядки вже вмію. Роблю так:

static FRESULT logerSD(const char string[])
{
    char bufferStr[64];
    char filename[14];
    int len;
    RTC_DateTypeDef sDate;
    RTC_TimeTypeDef sTime;
    mRTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
    mRTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
    sprintf(filename,"%.2d%.2d%.2d.log", (2000 + sDate.Year), sDate.Month, sDate.Date);
    len = sprintf(bufferStr, "%.2d:%.2d:%.2d - %s\r\n", sTime.Hours, sTime.Minutes, sTime.Seconds, string);    //generate some string
    static FATFS g_sFatFs;
    FRESULT fresult;
    FIL file;
    UINT bytes_written;

    fresult = f_mount(&g_sFatFs, "0:", 0);                            //mount SD card
    fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);    //open file on SD card
    fresult = f_lseek(&file, file.fsize);                            //go to the end of the file
    fresult = f_write(&file, bufferStr, len, &bytes_written);        //write data to the file
    fresult = f_close(&file);
    return fresult;
}

Але це з буфером char. А от потрібно мені читати і зберігати налаштування девайсу типу таких:

typedef struct {
    bool triggerControlVoltage; // true - йде перевірка виходу за межі напруги, false - такої перевірки немає (міняється в налаштуваннях)
    uint16_t periodWarning;        // час в мілісеках на аналіз виходу за межі
    uint32_t SALT;  // просто якесь число для тесту
}settingDeviceTypeDef;

settingDeviceTypeDef settingDevice = {false, PERIOD_WARNING, 12345678};

Хотілось щось типу такого: - Ось я заповнив структуру дефолтними значенями. І читаю файл з налаштуваннями на SD-CARD, як файлу немає такого, то створюємо його  і в нього пишемо значення за замовчуванням. А як прочитався файл, то заповнюємо структуру з налаштуваннями, прочитаними даними з файлу.

Як це взагалі робиться? Новачок в цій темі. Якось туплю, в ступорі.

130

Re: STM32, Atolic TrueStudio, CubeMX

Поспав, відволікся і ступор минув.
Зробив так:

static FRESULT settingLoadSave(bool mode, const char filename[], void* settings, uint32_t size)
{
    settingDeviceTypeDef* setting = (settingDeviceTypeDef*) settings;

    static FATFS g_sFatFs;
    FRESULT fresult;
    FIL file;
    UINT bytes;

    fresult = f_mount(&g_sFatFs, "0:", 0);                            //mount SD card

    if(fresult == FR_OK)
    {
        if(mode == LOAD)
        {
            fresult = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);    //open file on SD card
        }
        else if(mode == SAVE)
        {
            fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);    //open file on SD card
        }

        if(fresult == FR_OK)
        {
            if(mode == LOAD)
            {
                fresult = f_read(&file, setting, size, &bytes);        //read data from a file
            }
            else if(mode == SAVE)
            {
                fresult = f_write(&file, setting, size, &bytes);    //write data to the file
            }

            if(fresult != FR_OK)
            {
                return fresult;
            }
        }
        else
        {
            return fresult;
        }

        fresult = f_close(&file);
    }

    return fresult;
}

Ну і на виході аналізую чи є файл. Як немає, заповнюю значеннями за замовчуванням і зберігаю. Як є файл налаштувань, то його читаю. Все чудово працює.

131

Re: STM32, Atolic TrueStudio, CubeMX

Маленька порада по стилю. Так, структурне програмування вимагає конструкцій на кшталт

result = action1();
if(result==OK) {
  result = action2();
  if(result==OK) {
    result = action3();
  }
}
return result;

Але на практиці значно краще читається код

result = action1();
if(result!=OK) {
  return result;
}
result = action2();
if(result!=OK) {
  return result;
}
result = action3();
return result;

Тут очевидно, що код є лінійним з "аварійними" виходами, щойно щось станеться не так.
Іноді навіть роблять

do{
...
}while(false);

щоб можна було робити break у некоректних ситуаціях.
І ще я не дуже певен, що у вас правильно закривається файл.

Подякували: taburyak1

132 Востаннє редагувалося taburyak (23.10.2018 15:10:21)

Re: STM32, Atolic TrueStudio, CubeMX

Дякую за поради. Переробив так:

static FRESULT settingLoadSave(bool mode, const char filename[], void* settings, uint32_t size)
{
    settingDeviceTypeDef* setting = (settingDeviceTypeDef*) settings;

    static FATFS g_sFatFs;
    FRESULT fresult;
    FIL file;
    UINT bytes;

    fresult = f_mount(&g_sFatFs, "0:", 0);                            //mount SD card

    if(fresult != FR_OK)
    {
        return fresult;
    }

    if(mode == LOAD)
    {
        fresult = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);    //open file on SD card
    }
    else if(mode == SAVE)
    {
        fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);    //open file on SD card
    }

    if(fresult != FR_OK)
    {
        return fresult;
    }

    if(mode == LOAD)
    {
        fresult = f_read(&file, setting, size, &bytes);        //read data from a file
    }
    else if(mode == SAVE)
    {
        fresult = f_write(&file, setting, size, &bytes);    //write data to the file
    }

    if(fresult != FR_OK)
    {
        return fresult;
    }

    fresult = f_close(&file);

    return fresult;
}

І не зрозумів що не так з close?

133

Re: STM32, Atolic TrueStudio, CubeMX

Я не знаю особливостей роботи на цій системі, але якщо f_read/f_write повертають помилку (наприклад, ), f_close не викликається.
До речі, ще ви не перевіряєте bytes - а раптом повернеться FR_OK, але по факту щось недоробиться?

Подякували: taburyak, leofun012

134

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

Я не знаю особливостей роботи на цій системі, але якщо f_read/f_write повертають помилку (наприклад, ), f_close не викликається.
До речі, ще ви не перевіряєте bytes - а раптом повернеться FR_OK, але по факту щось недоробиться?

Ну наскільки я розумію, як буде помилка відкриття файлу, то він і не відкриється? Тоді і закривати нічого не треба. Але це так, здогадки.
bytes перевіряє сам драйвер FATFS. От хай і перевіряє :)

135

Re: STM32, Atolic TrueStudio, CubeMX

Після f_open - так. А от після f_read файл лишається відкритим.

Подякували: leofun01, taburyak2

136

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

Після f_open - так. А от після f_read файл лишається відкритим.

Зрозумів. Дякую.

137

Re: STM32, Atolic TrueStudio, CubeMX

З файлами наче розібралися, додам ще трохи своєї точки зору по стилю.

static FRESULT settingLoadSave(bool mode, const char filename[], void* settings, uint32_t size)
{
    // ...
    if(mode == LOAD)
    {
        fresult = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);    //open file on SD card
    }
    else if(mode == SAVE)
    {
        fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);    //open file on SD card
    }
    // ...
}

bool mode може приймати всього два значення.
Але через те, що використовуються слова LOAD і SAVE, виписано конструкцію if ... else if.
Але через те, що значень всього два, хвостового else нема і око тут же чіпляється за це — «а якщо не LOAD і не SAVE, тоді ж „ОЙ“, а програма спокійно піде далі». Такий чужий код (а свій код стає чужим через двійко-трійко місяців по тому, як востаннє його редагував) читати дуже важко.
Тому я б порадив або

static FRESULT settingLoadSave(bool save, const char filename[], void* settings, uint32_t size)
{
    // ...
    if (save) {
        fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);
    } else {
        fresult = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
    }

або вже тоді

enum setting_op { setting_save, setting_load}; // TODO: setting_check, setting_backup

static FRESULT settingLoadSave(enum setting_op mode, const char filename[], void* settings, uint32_t size)
{
    // ...
    switch (mode) {
    case setting_save:
        fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);
        break;
    case setting_load:
        fresult = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
        break;
    default:
        return FR_INVAL; // ну якусь тут помилку
    }
    // ...
Подякували: koala, taburyak2

138 Востаннє редагувалося koala (24.10.2018 11:56:08)

Re: STM32, Atolic TrueStudio, CubeMX

А мені ще муляє очі, що треба два рази робити розгалуження по LOAD/SAVE. Звісно, якщо його робити один раз, то доводиться дублювати перевірку f_open; це, загалом, не найгірший варіант

    switch (mode) {
    case setting_save:
        fresult = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);
        if( fresult != FR_OK ){
            return fresult ;
        }
        fresult = f_write(&file, setting, size, &bytes);        //read data from a file        
        break;
    case setting_load:
        fresult = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
        if( fresult != FR_OK ){
            return fresult;
        }
        fresult = f_read(&file, setting, size, &bytes);    //write data to the file      
        break;
    default:
        return FR_INVAL;
    }

Можу запропонувати ще такий підхід без розгалужень:

enum setting_op { setting_save, setting_load}; // TODO: setting_check, setting_backup
BYTE setting_modes[] = {/*setting_save*/ FA_OPEN_ALWAYS | FA_WRITE, /*settings_load*/ FA_OPEN_EXISTING | FA_READ);
typedef FRESULT (*Read_write_func)( FIL*, void*, UINT, UINT* );
Read_write_func setting_funcs[] = {/*setting_save*/&f_write, /*settings_load*/&f_read};
...
        fresult = f_open(&file, filename, setting_modes[mode]);
        if( fresult != FR_OK ){
            return;
        }
        fresult = (setting_funcs[mode])(&file, setting, size, &bytes);       

Але тоді розширення функціоналу потребуватиме написання функцій-обгорток із таким самим інтерфейсом.

Подякували: taburyak1

139

Re: STM32, Atolic TrueStudio, CubeMX

Дякую хлопці. "Накидали" повне відро :) Я вас зрозумів.

140 Востаннє редагувалося taburyak (16.03.2019 18:15:40)

Re: STM32, Atolic TrueStudio, CubeMX

Переробляю одну бібліотечку для дисплею з контролером на ST7735 з ардуінки на С++. Є такий код:

// Swap any type
template <typename T> static inline void
tftswap(T& a, T& b) { T t = a; a = b; b = t; }

Це якось можна переробити на Cі? Бо я не розумію що там відбувається.

update: здається це аналогічно?

#define SWAP_INT16_T(a, b) { int16_t t = a; a = b; b = t; }