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.

Using McBSP bitfield definitions causes unpredicable behavior

I'm working with a c6711dsk board and have created some bitfield definitions to access the McBSP registers (see below). Whenever I write to a register using the bitfield definitions, unpredictable values get written to all bitfields in the register (not just what I'm writing too). As an example, when I execute:

mcbspRegisters.SRGR.bit.CLKGDV = 0xFF

the entire SRGR register gets set to 0xFFFFFFFF. When I execute:

mcbspRegisters.SRGR.bit.CLKSM = 1;

the entire SRGR register gets set to 0x30303030. However, if I assign a bitmask to the entire register, I get the expected behavior. Also, if I let the linker map the struct into RAM instead of to the register, the above code works fine.

Any ideas?

 

I'm using CCS v3.3 Platinum with the 6.1.8 code gen tools and DSP/BIOS 5.33.03.

Here is the linker command file:

MEMORY
{
   MCBSP1      : origin = 0x1900000,   len = 0x28
}
SECTIONS
{
    McbspRegistersFile > MCBSP1
}

Here is the declaration of the register:

#ifdef __cplusplus
#pragma DATA_SECTION("McbspRegistersFile");
#else
#pragma DATA_SECTION(mcbspRegisters,"McbspRegistersFile");
#endif
volatile struct McBSP_REGS mcbspRegisters;

Here is the bitfield definition:

struct McBSP_REGS
{
    Uint32 DRR;

    Uint32 DXR;

    union
    {
        Uint32 all;
        struct
        {
            Uint32 RRST:1;
            Uint32 RRDY:1;
            Uint32 RFUL:1;
            Uint32 RSYNCERR:1;
            Uint32 RINTM:2;
            Uint32 rsvd1:1;
            Uint32 DXENA:1;
            Uint32 rsvd2:3;
            Uint32 CLKSTP:2;
            Uint32 RJUST:2;
            Uint32 DLB:1;
            Uint32 XRST:1;
            Uint32 XRDY:1;
            Uint32 XEMPTY:1;
            Uint32 XSYNCERR:1;
            Uint32 XINTM:2;
            Uint32 GRST:1;
            Uint32 FRST:1;
            Uint32 SOFT:1;
            Uint32 FREE:1;
            Uint32 rsvd3:6;
        } bit;
    } SPCR;

    union
    {
        Uint32 all;
        struct
        {
            Uint32 rsvd1:4;
            Uint32 RWDREVRS:1;
            Uint32 RWDLEN1:3;
            Uint32 RFRLEN1:7;
            Uint32 rsvd2:1;
            Uint32 RDATDLY:2;
            Uint32 RFIG:1;
            Uint32 RCOMPAND:2;
            Uint32 RWDLEN2:3;
            Uint32 RFRLEN2:7;
            Uint32 RPHASE:1;
        } bit;
    } RCR;

    union
    {
        Uint32 all;
        struct
        {
            Uint32 rsvd1:4;
            Uint32 XWDREVRS:1;
            Uint32 XWDLEN1:3;
            Uint32 XFRLEN1:7;
            Uint32 rsvd2:1;
            Uint32 XDATDLY:2;
            Uint32 XFIG:1;
            Uint32 XCOMPAND:2;
            Uint32 XWDLEN2:3;
            Uint32 XFRLEN2:7;
            Uint32 XPHASE:1;
        } bit;
    } XCR;
   
    union
    {
        Uint32 all;
        struct SRGR_BITS
        {
            Uint32 CLKGDV:8;
            Uint32 FWID:8;
            Uint32 FPER:12;
            Uint32 FSGM:1;
            Uint32 CLKSM:1;
            Uint32 CLKSP:1;
            Uint32 GSYNC:1;
        } bit;
    } SRGR;

    union
    {
        Uint32 all;
       
        struct
        {
            Uint32 RMCM:1;
            Uint32 rsvd1:1;
            Uint32 RCBLK:3;
            Uint32 RPABLK:2;
            Uint32 RPBBLK:2;
            Uint32 RMCME:1;
            Uint32 rsvd2:6;
            Uint32 XMCM:2;
            Uint32 XCBLK:3;
            Uint32 XPABLK:2;
            Uint32 XPBBLK:2;
            Uint32 XMCME:1;
            Uint32 rsvd3:6;
        } bit;
    } MCR;

    Uint32 RCER;

    Uint32 XCER;

    union
    {
        Uint32 all;
        struct
        {
            Uint32 CLKRP:1;
            Uint32 CLKXP:1;
            Uint32 FSRP:1;
            Uint32 FSXP:1;
            Uint32 SRSTAT:1;
            Uint32 DXSTAT:1;
            Uint32 CLKSSTAT:1;
            Uint32 rsvd1:1;
            Uint32 CLKRM:1;
            Uint32 CLKXM:1;
            Uint32 FSRM:1;
            Uint32 FSXM:1;
            Uint32 RIOEN:1;
            Uint32 XIOEN:1;
            Uint32 rsvd2:18;
        } bit;
    } PCR;
};

 

 

  • You could also use the HAL macros from the CSL instead of defining all registers by yourself. It would look like this (not tested):

    MCBSP_FSETH(mcbspHandle,SRGR,CLKGDV,0xFF);
    or
    MCBSP_FSETSH(mcbspHandle,SRGR,CLKSM,INTERNAL);

    where mcbspHandle is a handle you get from MCBSP_open.

    There are also macros which don't need a handle (MCBSP_FSET, MCBSP_FSETS, ...), for example MCBSP_FSET(SRGR0,CLKGDV,0xFF).

    See csl_mcbsphal.h and SPRU401J (chapter 28) for more information.

    Robert

  • Here's from page 12 of the McBSP Reference Guide (spru580g):

    "The C6000 CPU communicates with the McBSP
    by reading or writing to its 32-bit-wide control registers. Non-32-bit write accesses to control registers can
    result in corrupting the control register value. This is because undefined values are written to non-enabled
    bytes. However, non-32-bit read accesses return the correct value."

    When writing to the bit-fields the compiler is likely generating non-32-bit accesses.  That's why you're getting the wrong data in the register, but when writing to normal RAM it works.

    You're probably better off using the CSL macros since you'll always get 32-bit accesses that way.

    Brad

  • Thank you both for your help, I got it working now using your suggested methods.

  • We had the same issue on the DM355 for the same reason. If it could access a field by fetching & working on a byte it would do even when the register was 32 bit. But is very useful to be able to use bit fields on hardware registers. Just looking through the C6000 Compiler UG V7.0 section 7.2.2.2 it says with EABI, bit fields declared voliatile are accessed according to the declared type. Does this mean we can force 32 bit accesses? If so then bit fields should work on hardware registers. I am understanding this correctly? Maybe there are downsides to using EABI at this time?

    Roger

  • I don't know all the bitfield details you're asking, but I do know that you will only be able to link code that has also been built with EABI.  Except for the RTS library shipped with the compiler, no TI libraries have been built with EABI compiler.  So if you use EABI you cannot use BIOS, dsplib, etc.

  • Thanks for your reply. Looks like it might be difficult to use EABI at present then, even if it would do what I want. It would be a very useful enhancement to the compiler if there could be a pragma or something to force 32 bit access (or 16, or 8) on selected variables Then we could use bit fields which are really useful when fiddling with hardware registers.

    Roger