porting nRF52 project from IAR to ARMGCC

Hi. I have a working IAR project based on the nrf52 SDK \nordic\examples\ble_peripheral\ble_app_uart. i am attempting to port the project to ARMGCC using VSCode. I am at a stage in the port where all the files compile and link and I am at the main() stepping in and out of functions using the GDB. i come across a function "localtime" and have a HARDFAULT. I verified the input parameters are valid.

thanks in advance.

Barry

  • i attached two files with Chat

    #include <string.h>  // for strcmp
    #include <stdio.h>   // for snprintf
    #include "time_utils.h"
    
    static struct my_tm _tm_result;
    
    static const int days_in_month[] = {
        31, 28, 31, 30, 31, 30,
        31, 31, 30, 31, 30, 31
    };
    
    static int is_leap(int year) {
        year += 1900;
        return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
    }
    
    time_t my_mktime(const struct my_tm *t) {
        time_t days = 0;
        for (int y = 70; y < t->tm_year; y++) {
            days += (is_leap(y) ? 366 : 365);
        }
    
        for (int m = 0; m < t->tm_mon; m++) {
            days += days_in_month[m];
            if (m == 1 && is_leap(t->tm_year)) {
                days += 1; // Leap year February
            }
        }
    
        days += t->tm_mday - 1;
    
        return ((days * 24 + t->tm_hour) * 60 + t->tm_min) * 60 + t->tm_sec;
    }
    
    struct my_tm *my_localtime(const time_t *timep) {
        time_t seconds = *timep;
        int days = seconds / 86400;
        int rem = seconds % 86400;
    
        _tm_result.tm_hour = rem / 3600;
        rem %= 3600;
        _tm_result.tm_min = rem / 60;
        _tm_result.tm_sec = rem % 60;
    
        int year = 70;
        while (1) {
            int ydays = is_leap(year) ? 366 : 365;
            if (days >= ydays) {
                days -= ydays;
                year++;
            } else break;
        }
        _tm_result.tm_year = year;
    
        _tm_result.tm_yday = days;
    
        int month;
        for (month = 0; month < 12; month++) {
            int dim = days_in_month[month];
            if (month == 1 && is_leap(year)) dim += 1;
            if (days >= dim) {
                days -= dim;
            } else break;
        }
        _tm_result.tm_mon = month;
        _tm_result.tm_mday = days + 1;
    
        // Optional: you can calculate tm_wday here if needed
        _tm_result.tm_isdst = 0;
    
        return &_tm_result;
    }
    
    int my_strftime(char *buf, size_t max, const char *fmt, const struct my_tm *t)
    {
        // Only supports this format: " %d/%m/%y %H:%M:%S"
        // Adjust accordingly if needed.
        if (strcmp(fmt, " %d/%m/%y %H:%M:%S") != 0 || max < 20)
            return 0; // unsupported format or buffer too small
    
        return snprintf(buf, max, " %02d/%02d/%02d %02d:%02d:%02d",
                        t->tm_mday,
                        t->tm_mon + 1,
                        (t->tm_year + 1900) % 100,
                        t->tm_hour,
                        t->tm_min,
                        t->tm_sec);
    }
    
    time_utils.h that implement the missing meat in the ARMGCC library.

    thanks,

  • I used your code in nrf5sdk v17 in uart peripheral sample and it works fine without any crash or hardfault.

    Attaching my project just for your reference.

    8468.uart.zip

    Compiler version details here

  • Hi I'm back after a while. I am trying to retain some data structure in RAM in my c file, I define 

    #if defined(__ICCARM__)  // IAR Compiler
    #pragma location = HITLESS_START_ADDRESS
    __no_init volatile HITLESS_STRUCTURE hitless_struct; 
     #elif defined(__GNUC__)  // GCC Compiler
    /**
     * @brief Fixed-location hitless structure (retains values across soft reset).
     */
    __attribute__((section(".persistent")))
    __attribute__((used))
    volatile HITLESS_STRUCTURE hitless_struct;
     #else

    in my linker file I define:

    SECTIONS
    {
      . = 0x20003324;
      hitless_struct = .;
      .persistent (NOLOAD) :
      {
        KEEP(*(.persistent))
      } > RAM
    }

    When debugging, the address is set as designated; however, after a soft reset, the data is not retained.

    I appreciate any help you can provide.

    Barry

  • You are manually setting location counter to 0x20003324 just before defining the .persistent section. This might place .persistent at 0x20003324. Also this section can be silently overridden by a startup code zeroing out the .bss sections if .persistent overlaps it.

    I suggest use simpler declaration in C code like below

    __attribute__((section(".noinit")))
    volatile HITLESS_STRUCTURE hitless_struct;
    

    Also this in your linker script to tell the startup code to skip initialization on this section.

    .noinit (NOLOAD) :
    {
      . = ALIGN(4);
      KEEP(*(.noinit))
    } > RAM
    

Related