This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem with the lwip port from AM335x sysbios industrial SDK

Other Parts Discussed in Thread: SYSBIOS, AM3354

Hello.

I've got a strange issue in lwip port from industrial  sysbios  sdk: 

ti.sysbios.knl.Semaphore: line 289: assertion failure: A_badContext: bad calling context. Must be called from a Task.
xdc.runtime.Error.raise: terminating execution

Assertion fails because of call Semaphore_pend function call from sys_arch_sem_wait function called from mem_free function called  from transmit interrupt handler.

Stack trace is shown on attached picture.

The file with sys_arch_sem_wait function is file with system-dependent interface for lwip. I got it from enetLwip_sysbios example. 

Are there any ways to get rid of this problem?

Maybe there is new file with system-dependent interface for lwip (current file from SDK was written in 2012)?

  • Hi,

    Which SDK version is this?
  • SDK version is 01.01.01.01
    I also downloaded version 1.1.0.10 but I couldn't find any lwip example with sysbios, only bare metal examples.
  • I have asked the Industrial team to look at this.
  • Hi,

    The issue is quite obvious here, i.e., a semaphore_pend shouldn't be used in an ISR context. I quickly looked at the implementation of mem_free

    void
    mem_free(void *rmem)
    {
      struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
    
      LWIP_ASSERT("rmem != NULL", (rmem != NULL));
      LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
    
      /* get the original struct memp_malloc_helper */
      hmem--;
    
      LWIP_ASSERT("hmem != NULL", (hmem != NULL));
      LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
      LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
    
      /* and put it in the pool we saved earlier */
      memp_free(hmem->poolnr, hmem);
    }

    But there seems to be no calls to sem_pend here?

    Also, in what scenario do you get this?

    Regards,
    Vinesh

  • Which SDK version do you use?

    In SDK  01.01.01.01 mem_free function, located in C:\ti\am335x_sysbios_ind_sdk_01.01.01.01\starterware\third_party\lwip-1.4.0\src\core\mem.c,

    looks like

    /**
     * Put a struct mem back on the heap
     *
     * @param rmem is the data portion of a struct mem as returned by a previous
     *             call to mem_malloc()
     */
    void
    mem_free(void *rmem)
    {
      struct mem *mem;
      LWIP_MEM_FREE_DECL_PROTECT();
    
      if (rmem == NULL) {
        LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
        return;
      }
      LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
    
      LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
        (u8_t *)rmem < (u8_t *)ram_end);
    
      if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
        SYS_ARCH_DECL_PROTECT(lev);
        LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
        /* protect mem stats from concurrent access */
        SYS_ARCH_PROTECT(lev);
        MEM_STATS_INC(illegal);
        SYS_ARCH_UNPROTECT(lev);
        return;
      }
      /* protect the heap from concurrent access */
      LWIP_MEM_FREE_PROTECT();
      /* Get the corresponding struct mem ... */
      mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
      /* ... which has to be in a used state ... */
      LWIP_ASSERT("mem_free: mem->used", mem->used);
      /* ... and is now unused. */
      mem->used = 0;
    
      if (mem < lfree) {
        /* the newly freed struct is now the lowest */
        lfree = mem;
      }
    
      MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
    
      /* finally, see if prev or next are free also */
      plug_holes(mem);
    #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
      mem_free_count = 1;
    #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
      LWIP_MEM_FREE_UNPROTECT();
    }

    and macro LWIP_MEM_FREE_PROTECT is defined like

    #define LWIP_MEM_FREE_PROTECT()    sys_mutex_lock(&mem_mutex)

  • Hi.

    I downloaded SDK 1.1.0.10 and got the code you listed above.

    But there is another issue: I got data abort error in function ip_input:

    [CortxA8]  0x8107a47c  R8  = 0xffffffff
    R1 = 0x000000ab  R9  = 0xffffffff
    R2 = 0x00000014  R10 = 0xffffffff
    R3 = 0x8107ab00  R11 = 0xffffffff
    R4 = 0xffffffff  R12 = 0x8104e61e
    R5 = 0xffffffff  SP(R13) = 0x8001dbcc
    R6 = 0xffffffff  LR(R14) = 0x81072bcc
    R7 = 0xffffffff  PC(R15) = 0x8001dbcc
    PSR = 0xffffffff
    DFSR = 0x00000001  IFSR = 0x00000000
    DFAR = 0x8104e62e  IFAR = 0x00000000
    ti.sysbios.family.arm.exc.Exception: line 205: E_dataAbort: pc = 0x8001dbcc, lr = 0x81072bcc.
    xdc.runtime.Error.raise: terminating execution
    

    The exception occurs on macro   

    ip_addr_copy(current_iphdr_dest, iphdr->dest);

    What can be the reason of such behaviour and how can  I solve this issue?

  • Hi,

    My bad, mem_free has multiple definitions based on a macro.

    There has been no update for lwip app for a while, in what scenario are you getting this error? Can you share the RTSC tool versions, platform, etc. ?

    Regards,
    Vinesh
  • Hello.

    My xcd_tool version is 3.31.0.24_core, SYSBIOS 6.45.0.20

    App.cf is listed below:

    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Error = xdc.useModule('xdc.runtime.Error');
    var Log = xdc.useModule('xdc.runtime.Log');
    var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
    var Main = xdc.useModule('xdc.runtime.Main');
    var Memory = xdc.useModule('xdc.runtime.Memory')
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');
    
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var MailBox = xdc.useModule('ti.sysbios.knl.Mailbox');
    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var GateMutex = xdc.useModule('ti.sysbios.gates.GateMutex');
    var GateHwi = xdc.useModule('ti.sysbios.gates.GateHwi');
    var Cache = xdc.useModule('ti.sysbios.hal.Cache');
    var ti_sysbios_family_arm_a8_Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    /* 
     * Program.argSize sets the size of the .args section. 
     * The examples don't use command line args so argSize is set to 0.
     */
    Program.argSize = 0x0;
    
    /*
     * Uncomment this line to globally disable Asserts.
     * All modules inherit the default from the 'Defaults' module.  You
     * can override these defaults on a per-module basis using Module.common$. 
     * Disabling Asserts will save code space and improve runtime performance.
    Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
     */
    //Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
    /*
     * Uncomment this line to keep module names from being loaded on the target.
     * The module name strings are placed in the .const section. Setting this
     * parameter to false will save space in the .const section.  Error and
     * Assert messages will contain an "unknown module" prefix instead
     * of the actual module name.
    Defaults.common$.namedModule = false;
     */
    
    /*
     * Minimize exit handler array in System.  The System module includes
     * an array of functions that are registered with System_atexit() to be
     * called by System_exit().
     */
    System.maxAtexitHandlers = 4;       
    
    /* 
     * Uncomment this line to disable the Error print function.  
     * We lose error information when this is disabled since the errors are
     * not printed.  Disabling the raiseHook will save some code space if
     * your app is not using System_printf() since the Error_print() function
     * calls System_printf().
    Error.raiseHook = null;
     */
    
    /* 
     * Uncomment this line to keep Error, Assert, and Log strings from being
     * loaded on the target.  These strings are placed in the .const section.
     * Setting this parameter to false will save space in the .const section.
     * Error, Assert and Log message will print raw ids and args instead of
     * a formatted message.
    Text.isLoaded = false;
     */
    
    /*
     * Uncomment this line to disable the output of characters by SysMin
     * when the program exits.  SysMin writes characters to a circular buffer.
     * This buffer can be viewed using the SysMin Output view in ROV.
    SysMin.flushAtExit = false;
     */
    
    /*
     * The BIOS module will create the default heap for the system.
     * Specify the size of this default heap.
     */
    BIOS.heapSize = 0x4000;
    
    /* System stack size (used by ISRs and Swis) */
    Program.stack = 0x4000;
    
    /* Circular buffer size for System_printf() */
    SysMin.bufSize = 0x200;
    
    /* 
     * Create and install logger for the whole system
     */
    var loggerBufParams = new LoggerBuf.Params();
    loggerBufParams.numEntries = 16;
    var logger0 = LoggerBuf.create(loggerBufParams);
    Defaults.common$.logger = logger0;
    Main.common$.diags_INFO = Diags.ALWAYS_ON;
    
    System.SupportProxy = SysMin;
    
    Program.sectionsExclude = "^\\.bss|^\\.neardata|^\\.rodata";
    BIOS.libType = BIOS.LibType_Custom;
    BIOS.logsEnabled = false;
    BIOS.assertsEnabled = true;
    
    
    var Timer = xdc.useModule('ti.sysbios.timers.dmtimer.Timer');
    Timer.intFreq.lo = 20000000;   // 20MHz
    Timer.intFreq.hi = 0;
    
    BIOS.cpuFreq.lo = 400000000;
    
    
    //************ CACHE DEFINITION ************
    
    
    var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
    
    
    
    var peripheralAttrs = {
    type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
    	bufferable : false, // bufferable
    	cacheable : false, // cacheable
    	shareable : false
    };
    
    
    /*
    Mmu from example
    */
    Mmu.setFirstLevelDescMeta(0x4A100000, 0x4A100000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x48300000, 0x48300000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x48200000, 0x48200000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x48100000, 0x48100000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x48000000, 0x48000000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x44E00000, 0x44E00000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x4A300000, 0x4A300000, peripheralAttrs);
    Mmu.setFirstLevelDescMeta(0x4A100000, 0x4A100000, peripheralAttrs);
    
    var memAttrs = {
    type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
    	bufferable : false, // bufferable
    	cacheable : true, // cacheable
    };
    
    
    
    Mmu.setFirstLevelDescMeta(0x81000000, 0x81000000, memAttrs);
    
    Mmu.enableMMU = true;
    
    // ************ END CACHE DEFINITIONS ************
    

    As fas as I unterstand the reason of error is data misalignment  (because of DFSR = 0x00000001), but I enabled generation unalignment loads and stores --unaligned_access=on in  project and lwip library/

  • Hi,

    Are you able to run the pre-built binaries?

    Ilya Sokolov1 said:
    My xcd_tool version is 3.31.0.24_core, SYSBIOS 6.45.0.20


    These don't look like the recommended setup - 

    Regards,
    Vinesh

  • Hi,

    I tried with recomended settings:SYSBIOS 6.41.04.54 and XDC 3.30.06.67

    Result is the same.

    [CortxA8]  0x8107a47c  R8  = 0xffffffff
    R1 = 0x000000ab  R9  = 0xffffffff
    R2 = 0x00000014  R10 = 0xffffffff
    R3 = 0x8107ab00  R11 = 0xffffffff
    R4 = 0xffffffff  R12 = 0x8104e61e
    R5 = 0xffffffff  SP(R13) = 0x8001c34c
    R6 = 0xffffffff  LR(R14) = 0x81072bcc
    R7 = 0xffffffff  PC(R15) = 0x8001c34c
    PSR = 0xffffffff
    DFSR = 0x00000001  IFSR = 0x00000000
    DFAR = 0x8104e62e  IFAR = 0x00000000
    ti.sysbios.family.arm.exc.Exception: line 205: E_dataAbort: pc = 0x8001c34c, lr = 0x81072bcc.
    xdc.runtime.Error.raise: terminating execution
    

    What binaries do you mean?

  • Hi,

    software-dl.ti.com/.../am335x_sysbios_ind_sdk_prebuilt_01_01_01_01.zip . These binaries are expected to work on AM335x ICEv2. Can you please try this?

    Regards,
    Vinesh
  • Hi.
    I don't think I can run these binaries because I use custom am3354 board - MTAX-SOM-AM335 (axonim.by/.../am3359-module-preview-en)
    But I think I can run *.out files with CCS.
  • Hi
    I think the main problem is in unaligned access to memory - compiler doesn't generate it for strucrures ip_addr_t and ip_addr_packed.
    Are there any way to force compiler geterate unaligned access inctructions?

  • Hi

    I've found the same problem: 

    I tried to do like described in the link:

    added section memp in my .cmd file

    SECTIONS
    {                            
    	.init: { boot*(.text)} > 0x80000000 /* make sure we can boot!            */
        GROUP: load > 0x81000000
        {
            .bss:
            .neardata:
            .rodata:
        }
    	.memp          >  OCMC_SRAM
    }
    

    then I declared in main.c extern variables:

    extern u8_t __attribute__((section(".memp"))) memp_memory_UDP_PCB_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_TCP_PCB_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_TCP_PCB_LISTEN_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_TCP_SEG_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_REASSDATA_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_FRAG_PBUF_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_SYS_TIMEOUT_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_PBUF_base[];
    extern u8_t __attribute__((section(".memp"))) memp_memory_PBUF_POOL_base[];

    but it doesn't worked.

    What is the reason of such behaviour?