C COMPILER

Since the TMS320C32 has internally a 32 bit architecture, the C Compiler’s data types remain 32 bits. However, the C Compiler’s Run Time Support Library include pragma directives and new dynamic allocation routines (malloc, realloc, calloc, bmalloc, free, etc.) that support the creation of data sections that serve as memory pools (or heaps) to store 16 and 8 bit data size values. Note that these sections can reside in 8, 16, or 32 bit wide memory. The programmer must make sure that the appropriate Strobe Control Register is loaded with the correct data size and memory width. According to the settings of the Strobe Control register, the TMS320C32 memory interface will truncate, pack, or unpack the data appropriately. The following table illustrates the data sizes supported by the different sections (blocks of code or data) created by the C Compiler.

Section Type Data Size
32-bit 16-bit 8-bit

Initialized

.text
.cinit
.const
.user_section

.user_section

.user_section

Uninitialized

.bss
.stack
.sysmem
.user_section

.sysm16

.user_section

.sysm8

.user_section

These sections contain:

  • .text: executable code and/or string literals
  • .cinit: tables for variable and constant initialization
  • .const: string literals and switch tables
  • .bss: global variables and statically allocated variables
  • .stack: system stack that is used to pass arguments to functions and allocate local function variables
  • .sysmem: memory pool for dynamic allocation of 32 bit data size
  • .sysm16: memory pool for dynamic allocation of 16 bit data size
  • .sysm8: memory pool for dynamic allocation of 8 bit data size
  • .user_section: a section created using the #pragma DATA_SECTION directive
  • The following sections describes the preprocessor pragma and two files added to the Run Time Support Library that support these 8 bit and 16 bit memory pools. Note that 32 bit memory pools are handled through the standard minit(), malloc(), calloc(), realloc(), and free() routines that operate on the “.sysmem” section.

    DATA_SECTION Pragma Directive

    To support additional memory pools, the C Compiler utilizes a data section pragma directive. This pragma directive instructs the C Compiler to allocate space for symbol_name in the section specified by section_name of size symbol_size. It’s syntax is as follows:

  • #pragma DATA_SECTION ( symbol_name, section_name )
    type symbol_name;
  • For example, to define a new section called “.mydata” as an array of 1024 integer values use:

  • #pragma DATA_SECTION ( dataBuf, .mydata )
    int dataBuf[1024];
  • MEMORY8.C

    The MEMORY8.C module contains functions that implement dynamic memory management routines for the TMS320C32’s 8 bit data sizes. It consist of the following: pragma directive that defines a “.sysm8” section. The size of this memory pool in words (system memory or heap) is set at link time by using the -heap8 option. If the -heap8 option is not used, the compiler does not allocate 8 bit system memory area. If no arguments is given to this switch, the size of the 8 bit system memory area defaults to 1024, 8 bit words.

    • minit8() function that initializes and resets the 8 bit dynamic memory management system. This function is analogous to the minit() function, except that operates in the 8 bit “.sysm8” section.
    • malloc8() function that allocates 8 bit words from the 8 bit memory pool and returns a pointer to the allocated space. This function is analogous to the malloc() function, except that operates in the 8 bit “.sysm8” section.
    • calloc8() function that allocates 8 bit words from the 8 bit memory pool, clears these locations, and returns a pointer to the allocated space. This function is analogous to the calloc() function, except that operates in the 8 bit “.sysm8” section.
    • realloc8() function that reallocates a different space of 8 bit words from previously allocated space in the 8 bit memory pool and returns a pointer to the allocated space. This function is analogous to the realloc() function, except that operates in the 8 bit “.sysm8” section.
    • free8() function that frees previously allocated space from the 8 bit memory pool. This function is analogous to the free() function, except that operates in the 8 bit “.sysm8” section.
    • bmalloc8() function that allocates 8 bit words from the 8 bit memory pool aligned to a boundary suitable for the TMS320C32Õs circular and bit-reversed buffers and returns a pointer to the allocated space. This function is analogous to the bmalloc() function, except that operates in the 8 bit “.sysm8” section.
    • _SYSMEM8_SIZE is an external label that holds the size in words of the 8 bit system memory pool.

    MEMORY16.C

    The MEMORY16.C module contains functions that implement dynamic memory management routines for the TMS320C32’s 16 bit data sizes. It consists of the following:

    • pragma directive that defines a Ò.sysm16” section. The size of this memory pool in words (system memory or heap) is set at link time by using the -heap16 option. If the &endashheap16 option is not used, the compiler does not allocate 16 bit system memory area. If no arguments is given to his switch, the size of the 16 bit system memory area defaults to 1024, 16 bit words.
    • minit16() function that initializes and resets the 16 bit dynamic memory management system. This function is analogous to the minit() function, except that operates in the 16 bit “.sysm16” section.
    • malloc16() function that allocates 16 bit words from the 16 bit memory pool and returns a pointer to the allocated space. This function is analogous to the malloc() function, except that operates in the 16 bit “.sysm16” section.
    • calloc16() function that allocates 16 bit words from the 16 bit memory pool, clears these locations, and returns a pointer to the allocated space. This function is analogous to the calloc() function, except that operates in the 16 bit “.sysm16” section.
    • realloc16() function that reallocates a different space of 16 bit words from previously allocated space in the 16 bit memory pool and returns a pointer to the allocated space. This function is analogous to the realloc() function, except that operates in the 16 bit “.sysm16” section.
    • free16() function that frees previously allocated space from the 16 bit memory pool. This function is analogous to the free() function, except that operates in the 16 bit “.sysm16” section.
    • bmalloc16() function that allocates 16 bit words from the 16 bit memory pool aligned to a boundary suitable for the TMS320C32Õs circular and bit-reversed buffers and returns a pointer to the allocated space. This function is analogous to the bmalloc() function, except that operates in the 16 bit “.sysm16” section.
    • _SYSMEM16_SIZE is an external label that holds the size in words of the 16 bit system memory pool.

    Caution

    The TMS320C32 has only three strobes: STRB0, STRB1, and IOSTRB. Therefore, the programmer cannot have more than three memory pools, one memory pool assigned to each strobe. Note that IOSTRB can only hold 32 bit data and can only accommodate the 32 bit memory pool: .sysmem. On the other hand, STRB0 and STRB1 can hold 8/16/32 bit data and can accommodate the 8, 16, or 32 bit memory pools: .sysm8, .sysm16, and .sysmem.

    All pointers and constants must be stored in memory configured to hold 32 bit data. Hence, .bss, .stack, .cinit, and .const sections must reside in memory configured to 32 bit data size.


    LINKER

    To support the TMS320C32Õs 8 and 16 bit memory pools, the linker utilizes the following switches: &endashheap8, &endashheap16, and &endashheap that set the size in words of the respective 8, 16, and 32 bit memory system areas (.sysm8, .sysm16, and .sysmem). The user must link these sections into the appropriate addresses, activating strobes that will be configured to access either 8, 16, or 32 bit data sizes.

    For example, to specify the size of 8 bit memory pool at link time to 256K words, use:

  • lnk30 -heap8 0x4000
  • The linker creates these memory system areas only if there exists the respective .sysmem, .sysm8, and .sysm16 sections in an input file.

    The linker also creates the global symbols _SYSMEM_SIZE, _SYSMEM8_SIZE, and _SYSMEM16_SIZE and assigns it a value equal to the size of the respective heap, heap8, and heap16. The default size for each memory system area is 1K words.


    DEBUGGER

    For the debugger to properly disassemble and read/write external memory, the user must configure the Strobe Control Registers before loading and executing his code. Since the TMS320C32 supports code execution from 16 or 32 bit memory, the debugger might need to temporarily set the Strobe Control Register to 32 bit data size in order to write an instruction (either by loading code or patching code) or read an instruction in order to disassemble a range of program memory. To support this, the Memory Map Add command includes a new type parameter that directs the debugger to treat “.text” sections as 32 bit data. While reading or writing “.text” sections, the debugger temporarily stores the configuration of the appropriate Strobe Control Register, temporarily sets the data size to 32 bits, reads or writes the portion of the Ò.textÓ section, and restores the Strobe Control Register to its previous value. The syntax for the Memory Map Add Command is as follows:

  • ma address, length, type
  • address parameter defines the starting address of a range of memory
  • length parameter defines the length of the memory range
  • type parameter identifies the read/write characteristic of the memory range depending on one or more of the following keywords:
  • R read only
  • W write only
  • WR or RAM read/write
  • PROTECT no-access memory
  • TX memory that stores “.text” (code) section.

  • EXAMPLES

    Two External Memory Banks

    TMS320C32’s external memory interface allows the use of two zero wait state external memory banks with different widths without incurring in any access penalty and additional logic. This allows the programmer the flexibility in trading off performance versus system cost (amount of memory chips). For instance, the programmer could execute code from 32 bit wide memory while storing data in 8-bit memory, as shown in Figure 6. This would be an advantage to applications with large amounts of 8 bit data that require execution at the fastest speed of the device.

    Figure 6: Zero Wait State Interface for 32-bit and 8-bit SRAM Banks

    In this example, a bank of 32K by 3- bit is mapped to STRB0 while a bank of 32K by 8-bit is mapped to STRB1. For this configuration, the programmer must set the STRB0 Control Register Physical Memory Width to 32-bits, Data Type Size to 32-bits, and the STRB Config bit field to zero since the banks are separate memories (STRB0 Control Register = 000F0000h). Also, the programmer must set the STRB1 Control Register Physical Memory Width to 8-bits and the Data Type Size to 8-bits (STRB1 Control Register = 00000000h).

    This example maps the external memory address pins of the 32-bit wide bank, A14A13...A1A0, to the TMS320C32’s A14A13A12...A1A0. On the other hand, the 8-bit wide bank memory address pins, A14A13...A1A0, are mapped to the TMS320C32’s A21A13A12...A1A0A-1. Note that since STRB1 is configured for 8-bit memory width, the external address presented on TMS320C32’ s pins is shifted right by two bits. With this mapping, external memory accesses in the range 0h through 7FFFh read/write 32-bit data to the 32-bit wide bank (STRB0) while memory accesses in the range 900000h through 907FFFh read/write 8-bit data to the 8-bit wide bank (STRB1).

    Note that two banks of different memory widths should not be connected to the same STRB without external decode logic. Different memory widths require signals to be configured as address pins. These address pins are active for any external memory access (STRB0, STRB1, IOSTRB, and program fetches).

    C Code - Dynamic Memory Allocation

    The following C Code illustrates the allocation of two buffers (1K and 4K, 8-bit words) using the 8-bit dynamic memory allocation routines:

    void main()
    {
    int *buffer1;
    float *buffer2;
    /* STRB0 Control Register configured to 32 bit wide memory and 32 bit data size */
    *0x808064 = 0xF0000;
    /* STRB1 Control Register configured to 8 bit wide memory and 8 bit data size */
    *0x808068 = 0x00000;
    buffer1 = malloc8( 1024 * sizeof(int) ); /* allocate 1K 8 bit words in the 8 bit memory pool */
    buffer2 = malloc8( 4096 * sizeof(float) ); /* allocate 4K 8 bit floats in the 8 bit memory pool */
    callDSPoperation( buffer1, buffer2); /* process buffers */
    free8( buffer2 ); /* free buffers */
    free8( buffer1 );
    }

    Note that the TMS320 Floating Point C Compiler sizeof function returns 1 for both integers and floats data types.

    Linker Command File - Dynamic Memory Allocation

    The following linker command file allocates the sections of the code into the desired memory configuration:

    sample.obj /* Input filename */
    –heap8 32768 /* Set 8 bit memory pool size */
    –stack 8704 /* Set C system stack size */
    –o sample.out /* Specify output file */
    –m sample.map /* Specify map file */

    MEMORY
    {
    PRGRAM : org = 0x0000, len = 0x2000
    STRB0RAM : org = 0x2000, len = 0x6000
    ONCHIRAM : org = 0x87Fe00, len = 0x200
    STRB1RAM : org = 0x900000, len = 0x8000
    }
    SECTIONS
    {
    .text > PRGRAM /* 32 bit data section */
    .cinit > STRB0RAM /* 32 bit data section */
    .const > STRB0RAM /* 32 bit data section */
    .bss > STRB0RAM /* 32 bit data section */
    .stack > STRB0RAM /* 32 bit data section */
    .sysm8 > STRB1RAM /* 8 bit memory pool mapped to STRB1 */
    }

    Debugger Batch File

    The following debugger batch file executes initialization commands to configure the C Source Debugger to handle a TMS320C32 device in the memory configuration of Figure 6. Note that STRB0 and STRB1 Control Registers must be initialized prior to code download.

    mr
    sconfig init.clr
    ; Define memory configuration
    ma 0x0000, 0x2000, R|W|TX ; Inform debugger that this section holds code (.text )
    ma 0x2000, 0x6000, RAM ; No code here, STRB0
    ma 0x87FE00, 0x200, RAM ; On-chip
    ma 0x808000,0x10,RAM ; Peripheral Bus Control - DMA
    ma 0x808020,0x20,RAM ; Peripheral Bus Control - Timers
    ma 0x808040,0x10 ,RAM ; Peripheral Bus Control - Serial Port 0
    ma 0x808060,0x10,RAM ; Peripheral Bus Control - External Memory Interface
    ma 0x900000, 0x8000, RAM ; STRB1
    ;
    reset
    map on ; Make emulator aware of this memory configuration
    ;
    ?*0x808064 = 0xF0000 ; Set STRB0 Control Register to 32 bit memory width and 32 bit data size
    ?*0x808068 = 0x00000 ; Set STRB1 Control Register to 8 bit memory width and 8 bit data size
    ;
    load sample.out ; Need to configure STRB0 & STRB1 Control Registers before loading code

    C Code - Static Memory Allocation through User Section

    The following C Code and Linker Command File illustrate the static allocation of two buffers (1K and 4K, 8-bit words) by defining an user section called “.mydata8” that holds a structure consisting of two arrays of data values:

    #pragma DATA_SECTION ( buffer8, .mydata8 )
    struct bufferStruct {
    in[1024];
    out[4096];
    } buffer8;
    void main()
    {
    /* STRB0 Control Register configured to 32 bit wide memory and 32 bit data size */
    *0x808064 = 0xF0000;
    /* STRB1 Control Register configured to 8 bit wide memory and 8 bit data size */
    *0x808068 = 0x00000;
    callDSPoperation( buffer8.in, buffer8.out ); /* process buffers */
    }

    Linker Command File - Static Memory Allocation through User Section

    The following linker command file allocates the sections of the code into the desired memory configuration:

    sample.obj /* Input filename */
    –stack 8704 /* Set C system stack size */
    –o sample.out /* Specify output file */
    –m sample.map /* Specify map file */
    MEMORY
    {
    PRGRAM : org = 0x0000, len = 0x2000
    STRB0RAM : org = 0x2000, len = 0x6000
    ONCHIRAM : org = 0x87Fe00, len = 0x200
    STRB1RAM : org = 0x900000, len = 0x8000
    }
    SECTIONS
    {
    .text > PRGRAM /* 32 bit data section */
    .cinit > STRB0RAM /* 32 bit data section */
    .const > STRB0RAM /* 32 bit data section */
    .bss > STRB0RAM /* 32 bit data section */
    .stack > STRB0RAM /* 32 bit data section */
    .mydata8 > STRB1RAM /* 8 bit memory pool mapped to STRB1 */
    }

    Single External Memory Bank

    Consider the case of a typical audio compression application written in C language that requires a 32 bit data for system stack and 16 bit data for the audio buffers. In this case, the programmer might interface the TMS320C32 as shown in Figure 7. This examples assumes a 32K of 32-bit words external memory that contains 8.5K of 32-bit words of stack and 8K of 32-bit words of program (including constants, global, and static variables), both mapped to STRB0. Also, the external memory contains 32K of 16-bit words data buffers that are mapped into STRB1. Due to this mapping, the programmer must set the STRB0 Control Register Physical Memory Width to 32 bits, Data Type Size to 32 bits, and set the STRB Config bit field to 1 (STRB0 Control Register = 002F0000h). It also requires the programmer to set the STRB1 Control Register Physical Memory Width to 32 bits and the Data Type Size to 16 bits (STRB1 Control Register = 000D0000h). Moreover, the PRGW pin must be pulled low to indicate 32 bit program memory width.

    Figure 7: Zero-Wait State Interface for 32 bit SRAMs with 16 and 32 bit Data Accesses

    Note that the external memory address pins, A14A13...A1A0, are mapped to the TMS320C32’s A22A13A12...A1A0. This mapping was chosen to place the system stack following the TMS320C32’s internal RAM, thus improving performance by placing the top of the stack in internal RAM and allowing it to grow into external RAM. With this mapping, external memory accesses in the range 4000h through 7FFFh will read or write 16 bit data while memory accesses in the range 0h through 3FFFh reads or writes 32 bit data. The PRGW pin controls the program fetches.

    Figure 8 shows the contents of the external memory. Due to the address shift of the TMS320C32’s external memory interface, the memory map seen by the TMS320C32 CPU is slightly different. Figure 9 depicts this memory map.

     



    0h


    1FFFh

    System Stack Area
    (8K ¥ 32-bit)

    2000h

    program word 0

     

    program word 1

     

    .
    .
    .

    3FFFh

    program word 8191

    4000h

    data1

    data0

    4001h

    data3

    data2

     

    .
    .
    .

    .
    .
    .

    7FFFh

    data32767

    data32766

    Figure 8: External Memory Map

    0h

    .
    .
    .

    2000h

    3FFFh

    Program
    (8K ¥ 32-bit)

     

    .
    .
    .

    87FE00h

    87FFFFh

    Internal RAM (Stack)

    (512 ¥ 32-bit)

    880000h

    881FFFh

    System Stack

    (8K ¥ 32-bit)

     

    .
    .
    .

    900000h

    907FFFh

    Data Buffers

    (32K ¥ 16-bit)



    FFFFFFh

    .
    .
    .

    Figure 9: TMS320C32’s Memory Map

    C Code - Dynamic Allocation

    To allocate dynamically 2 buffers of 1K and 4K, 16 bit words, the user must use the 16-bit dynamic memory allocation routines provided by the Run Time Support Library as follows:

    void main()
    {
    int *buffer1;
    float *buffer2;
    /* STRB0 Control Register configured to STRB0 & STRB1 Overlay, 32 bit memory width,
    and 32 bit data size */
    /* If using the PRTS30 headers,
    BUS_ADDR->strb0_gcontrol = STRB0_1_CNFG | MEMW_32 | DATA_32; */
    *0x808064 = 0x2F0000;
    /* STRB1 Control Register configured to 32 bit memory width and 16 bit data size */
    /* If using the PRTS30 headers,
    BUS_ADDR->strb1_gcontrol = MEMW_32 | DATA_16; */
    *0x808068 = 0xD0000;
    buffer1 = malloc16( 1024 * sizeof(int) ); /* allocate 1K 16 bit words in the 16 bit memory pool */
    buffer2 = malloc16( 4096 * sizeof(float) );/* allocate 4K 16 bit floats in the 16 bit memory pool */
    callDSPoperation( buffer1, buffer2); /* process buffers */
    free16( buffer2 ); /* free buffers */
    free16( buffer1 );
    }

    Linker Command File

    The linker command file that allocates the sections of the code into the desired memory configuration of Figure 8 is shown below:

    sample.obj /* Input filename */
    –heap16 32768 /* Set 16 bit memory pool size */
    –stack 8704 /* Set C system stack size */
    –o sample.out /* Specify output file */
    –m sample.map /* Specify map file */
    MEMORY
    {
    STRB0RAM : org = 0x2000, len = 0x2000
    STACKRAM : org = 0x87Fe00, len = 0x2200
    STRB1RAM : org = 0x900000, len = 0x8000
    }
    SECTIONS
    {
    .text > STRB0RAM /* 32 bit data section */
    .cinit > STRB0RAM /* 32 bit data section */
    .const > STRB0RAM /* 32 bit data section */
    .bss > STRB0RAM /* 32 bit data section */
    .stack > STACKRAM /* 32 bit data section */
    .sysm16 > STRB1RAM /* 16 bit memory pool mapped to STRB1 */

    }

    Debugger Batch File

    The following debugger batch file executes initialization commands to configure the C Source Debugger to handle a TMS320C32 device in the memory configuration of Figure 8. Note that STRB0 and STRB1 Control Registers must be initialized prior to code download.

    mr
    sconfig init.clr
    ; Define memory configuration
    ma 0x2000, 0x2000, R|W|TX ; Inform debugger that this section might hold code (.text )
    ma 0x87FE00, 0x2000, RAM
    ma 0x900000, 0x8000, RAM
    map on ; Make emulator aware of this memory configuration
    ;
    ?*0x808064 = 0x2F0000 ; Set STRB0 Control Register to STRB0 & STRB1 overlay,
    ; 32 bit memory width, and 32 bit data size
    ?*0x808068 = 0xD0000 ; Set STRB1 Control Register 32 bit memory width and 16 bit data size
    ;
    load sample.out ; Need to configure STRB0 & STRB1 Control Registers before loading code


    Device: TMS320C3x
    Category: TI Tools
    Detail: General
    Title: 'C32 Tools Overview
    Source: Case from TMS320 Hotline
    Date: 8/1/97
    GenId: 0300010

    © Copyright 1998 Texas Instruments Incorporated. All rights reserved.
    Trademarks, Important Notice!