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.

Porting BIOSPSP audioSample for LCDK6748 and TLV320AIC34

Other Parts Discussed in Thread: SYSBIOS

Hello Community,

I am not very familiar with SYS/BIOS for C674x DSP's so my question might be obvious for experienced users. Anyway a good answer might help others lost in space, as well.

My questions apply to audioSample which is present in examples from BIOSPSP 03.00.01.00 dedicated for EVM6748. The package was fetched from TI as a part of executable package dedicated for LCDK6748 board which I purchased quite recently.

As far as I understand there is no specific port of this example for LCDK6748. So I tailored audioSample for LCDK6748. I run modified example for dedicated on-board codec aic3106 without excessive problems (only mcasp serializers needed to be remapped). It seems to work almost flawlessly except for popcorn noise introduced by XDS510 and continuous communication between DSP target and JTAG interface. I created CCS project with audioSample and ported sources of BIOSPSP to have possibility to recompile library on demand. I created new platform lcdk6748 with full configuration similar to this present for evm6748. Simply I followed C6748 BIOSPSP User Guide 03.00.01.00. to configure environment.

Next step of my exercise was to connect an external audio codec from TLV320AIC34EVM board. It has AIC34 codec which consists in fact two aic33 codecs in single chip - configurable by i2c and two consecutive addresses (0x18/0x19 or 0x1A/0x1B). So I assumed I can use aic31 driver and all related IOM software to drive aic34.

I am able to configure single codec from aic34 chip - it runs as it is expected - without surprise. But I need to drive both codecs in TDM mode, so I modified source and below I present only modified parts of source files that seem to me relevant to the context:

I modified of Aic31Local.h:

#if defined(CHIP_C6748) || defined (CHIP_OMAPL138)
#define AIC31_NUM_INSTANCES 2
/**< Num of instances */
#define AIC31_INST0_ADDRESS 0x1A
/**< Address of first instance */
#endif

and Aic31.c

Void Aic31_init(Void)
{
Int i;

for (i = 0; i < AIC31_NUM_INSTANCES; i++)
{
/* have to initialize statically */
Aic31_module.inUse[i] = FALSE;
memset((Void *)&Aic31_Instances[i], 0x0, sizeof(Aic31_Object));

Aic31_deviceInstInfo[i].deviceAddress = (Uint32)AIC31_INST0_ADDRESS + i;
}
}

Then I modified audioSample_main.c

void audioUserAic33Init_0()
{
	Aic31_init();
	audioAic33Params_0 = Aic31_PARAMS;
	audioAic33Params_0.acType = ICodec_CodecType_AIC33;
	audioAic33Params_0.acCtrlBusName = "/i2c0";
}


void audioUserAic33Init_1()
{
	Aic31_init();
	audioAic33Params_1 = Aic31_PARAMS;
	audioAic33Params_1.acType = ICodec_CodecType_AIC33;
	audioAic33Params_1.acCtrlBusName = "/i2c0";
	audioAic33Params_1.acOpMode = ICodec_OpMode_SLAVE;
}


/*
 * Mcasp init function called when creating the driver.
 */
void audioUserMcaspInit() {
	Mcasp_init();
	audioMcaspParams = Mcasp_PARAMS;
	audioMcaspParams.hwiNumber = 8;
}

/*
 * Audio init function called when creating the driver.
 */
void audioUserAudioInit() {
	Audio_init();
	audioParams = Audio_PARAMS;
	audioParams.adDevType = Audio_DeviceType_McASP;
	audioParams.adDevName = "/mcasp0";
	audioParams.acNumCodecs = 2;
	audioParams.acDevName[0] = "/aic34_0";
	audioParams.acDevName[1] = "/aic34_1";
}

and audioSample_io.c

/* McBsp channel parameters                                  */
Mcasp_ChanParams  mcasp_chanparam[Audio_NUM_CHANS]=
{
    {
        0x0001,                    /* number of serialisers      */
#ifdef TLV320AIC34EVM
        {Mcasp_SerializerNum_15, }, /* serialiser index           */
        //{Mcasp_SerializerNum_7, }, /* serialiser index           */
#else
        {Mcasp_SerializerNum_14, }, /* serialiser index           */
#endif
        &mcaspRcvSetup,
        TRUE,
        Mcasp_OpMode_TDM,          /* Mode (TDM/DIT)             */
        Mcasp_WordLength_32,
        NULL,
        0,
        NULL,
        NULL,
        2,                        /* number of TDM channels      */
        Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,
        TRUE,
        TRUE
    },
    {
        0x0001,                   /* number of serialisers       */
#ifdef TLV320AIC34EVM
        {Mcasp_SerializerNum_7,},
        //{Mcasp_SerializerNum_15,},
#else
        {Mcasp_SerializerNum_13,},
#endif
        &mcaspXmtSetup,
        TRUE,
        Mcasp_OpMode_TDM,
        Mcasp_WordLength_32,      /* word width                  */
        NULL,
        0,
        NULL,
        NULL,
        2,                        /* number of TDM channels      */
        Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,
        TRUE,
        TRUE
    }
};

Audio_ChannelConfig audioChanParamsIN =
{
    /*  channel 0 (RX)                         */
    (Ptr)&mcasp_chanparam[0], 
    {   /* codec [0]                           */
        {
            32000,//44100,  /* sampling rate for codec */
              50,  /* gain (%) for codec      */
             0x00,
             0x00
        }
    }
};

Audio_ChannelConfig audioChanParamsOUT =
{        
    /*  channel 1 (TX)                         */
    (Ptr)&mcasp_chanparam[1],      
    {
        /* codec [1]                           */
        {
            32000, //44100,  /* sampling rate           */
              100,  /* gain (%) for codec      */
             0x00,
             0x00
        }
    }
};

In configuration audiosample.cfg I added section for next codec so there is 5 entries calling statically GIO.addDeviceMeta() function (however as I understand this function is deprecated).

var iomFxns = "I2c_IOMFXNS";
var initFxn = "audioUserI2cInit";
var deviceParams = "audioI2cParams";
var deviceId = 0;
GIO.addDeviceMeta("/i2c0", iomFxns, initFxn, deviceId, deviceParams);

var iomFxns = "Aic31_IOMFXNS";
var initFxn = "audioUserAic33Init_0";
var deviceParams = "audioAic33Params_0";
var deviceId = 0;
GIO.addDeviceMeta("/aic34_0", iomFxns, initFxn, deviceId, deviceParams);

var iomFxns = "Aic31_IOMFXNS";
var initFxn = "audioUserAic33Init_1";
var deviceParams = "audioAic33Params_1";
var deviceId = 1;
GIO.addDeviceMeta("/aic34_1", iomFxns, initFxn, deviceId, deviceParams);

var iomFxns = "Mcasp_IOMFXNS";
var initFxn = "audioUserMcaspInit";
var deviceParams = "audioMcaspParams";
var deviceId = 0;
GIO.addDeviceMeta("/mcasp0", iomFxns, initFxn, deviceId, deviceParams);

var iomFxns = "Audio_IOMFXNS";
var initFxn = "audioUserAudioInit";
var deviceParams = "audioParams";
var deviceId = 0;
GIO.addDeviceMeta("/audio0", iomFxns, initFxn, deviceId, deviceParams);

 

When I run this code I get exception in audioSample_io.c in createStreams()

in line where GIO_create() is called:

 inStream = GIO_create("/audio0", GIO_INPUT, &ioParams, &eb);

 

here is dump:

EDMA driver initialization PASS.
A0=0x1 A1=0x0
A2=0x1 A3=0x0
A4=0x0 A5=0x0
A6=0xc00753bc A7=0x0
A8=0xc003e87c A9=0xc002c0cc
A10=0xc002c098 A11=0x1
A12=0xc002c098 A13=0x3
A14=0xc003ca2c A15=0x0
A16=0x0 A17=0x0
A18=0xc002c0d8 A19=0x0
A20=0x0 A21=0x0
A22=0x20ff1d2c A23=0x0
A24=0x11633049 A25=0x73f51086
A26=0x6bfd6f9 A27=0xc003e67c
A28=0xc0035188 A29=0x0
A30=0xc003e8cc A31=0x0
B0=0x1 B1=0x1
B2=0x7 B3=0xc0050908
B4=0xc003e854 B5=0x0
B6=0xc003ed00 B7=0x0
B8=0xc0066c80 B9=0x0
B10=0xc003c9c4 B11=0xc0075e20
B12=0x0 B13=0xc0067308
B14=0xc007a2c8 B15=0xc003c918
B16=0x0 B17=0xc0075a78
B18=0xa B19=0x78
B20=0x8 B21=0x69
B22=0xffffffff B23=0x0
B24=0x0 B25=0x0
B26=0x554e1bbd B27=0x0
B28=0x2e4 B29=0x14c
B30=0xc00787b4 B31=0x0
NTSR=0x1000f
ITSR=0xf
IRP=0xc0060692
SSR=0x0
AMR=0x0
RILC=0x0
ILC=0x0
Exception at 0x0
EFR=0x2 NRP=0x0
Internal exception: IERR=0x1
Instruction fetch exception
ti.sysbios.family.c64p.Exception: line 255: E_exceptionMin: pc = 0x00000000, sp = 0xc003c918.
To see more exception detail, use ROV or set 'ti.sysbios.family.c64p.Exception.enablePrint = true;'
xdc.runtime.Error.raise: terminating execution

Questions:

1. What is missing in configuration?

2. What else should I modify or add to run and configure both codecs existing at two addresses 0x1A (master) and 0x1B (slave)?

3. How should I configure inStream/outStream to have safe start?

Any help is valuable as I am climbing along "learning curve" and trying to understand the ideas behind IOM drivers.

Regards,

Tomasz Wojtaszek

  • Tomasz,

    I have moved this thread over to the device forum in hopes that it will get a faster response there from someone familiar with the device and even the PSP driver.

  • Hi Tomasz,

    Thanks for your post.

    In my guess, it wouldn't have got the proper GIO handle for one or more instances when it tries to open a communication channel and there are constraints when using GIO API's to create multiple instances. Do you have multiple tasks configured to run both codecs and in my opinion, a single GIO instance can be used by a single task. If GIO_create returns a GIO_Handle on successful instance which in turn pass to many other GIO APIs to send or receive data .

    Important: A GIO_Handle cannot be used by more than one Task simultaneously. One Task must finish a GIO_read() or GIO_write() or GIO_issue()/GIO_reclaim() before another Task can use the same GIO_Handle. It is safer for only one Task to use each GIO_Handle.

    Please see section 9.3 for the GIO API usage from the SysBios user guide as below:

    http://www.ti.com/lit/ug/spruex3m/spruex3m.pdf

    To know more details on exception module, please refer the below:

    http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/bios/sysbios/6_35_02_45/exports/bios_6_35_02_45/docs/cdoc/index.html

    To get started quickly, you have a collection of all SysBios resources from creating a  SysBios project, configuring & building  SysBios application, debugging  SysBios application thru. system analyzer, RTA tools, ROV etc. In addition,  SysBios training videos, user guide, getting started guide, API reference etc. - all are available at singe place as shown below:

    http://processors.wiki.ti.com/index.php/Category:SYSBIOS#Get_started_quickly_and_learn_as_you_go

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------
    Please click the Verify Answer button on this post if it answers your question.
    -------------------------------------------------------------------------------------------------------
  • Hello Sivaraj,

    Thank you very much for your response. 

    I think it is good opportunity to specify problem I am facing with.

    Because I am still struggling with aic31 configuration I would like to ask you if configuration presented below is reasonable.

    Lets consider "academic problem".

    I use aic31.h interface driver (which inherits ICodec.h interface). By means of the driver I need to have 2 instances to drive two codecs aic33.

    Both codecs are connected to two serializers of mcasp0 (RX = Mcasp_SerializerNum_15, TX = Mcasp_SerializerNum_7). It forces me to use TDM mode.

    Question: Which format data should I pick to force TDM mode: ICodec_DataType_TDM or ICodec_DataType_DSP?

    Question: Which structure/function of the public interface aic31.h informs a codec about number of TDM slot that is occupied for specific instance?

    What I suggested for my static configurations (in file audioSample_main.c) is:

    /*
     * Aic33 init function called when creating the driver.
     */
    void audioUserAic33Init()
    {
    	Aic31_init();
    	audioAic33Params = Aic31_PARAMS;
    	audioAic33Params.acType = ICodec_CodecType_AIC33;
    	audioAic33Params.acCtrlBusName = "/i2c0";
    	audioAic33Params.acSlotWidth = ICodec_SlotWidth_16;
    	audioAic33Params.acSerialDataType = ICodec_DataType_TDM;
    }
    
    void audioUserAic33Init_2()
    {
    	audioAic33Params_2 = Aic31_PARAMS;
    	audioAic33Params_2.acType = ICodec_CodecType_AIC33;
            audioAic33Params_2.acOpMode = ICodec_OpMode_SLAVE;
    	audioAic33Params_2.acCtrlBusName = "/i2c0";
    	audioAic33Params_2.acSlotWidth = ICodec_SlotWidth_16;
    	audioAic33Params_2.acSerialDataType = ICodec_DataType_TDM;
    }
    

    audioUserAic33Init() is called first, the audioUserAic33Init_2 as second during application startup.
    Assuming proper physical i2c addresses for codecs I should have set first codec as MASTER, second as SLAVE ().
    For test purposes I run only single instance - with success. I did it for both i2c addresses separately. I tried to configure single instance as MASTERS and SLAVES - with success as well. But when comes to sequent configuration of both resources - nothing happens. I have no proper bit clocks, sync clocks and no data at DOUTs of the codecs.
    Where is the problem?

    Best wishes,
    Tomasz Wojtaszek

     

     

  • Hi,

    I am currently addressing a very similar problem myself.  My configuration is: C6748, BIOS 6.33.1.25, BIOSPSP 3.0.1.0, UART driver.  In interrupt mode it causes an exception.

    After tracing through the code, I see that there's a problem in the GIO read/write module with respect to the way BIOSPSP 3 is implemented.  Specifically, the IOMPacket reference passed from GIO_submit into the driver is located on the stack (in GIO_submit), but subsequently used and modified by the UART driver in the context of the tasklet at a later time.  That's a recipe for disaster.

    So, a quick solution to our problems may be to use the issue/reclaim model instead of read/write. 

    Fundamentally, the packet passed down by GIO_submit should be one that was allocated in the packets queue for the issue/reclaim model use, or at least located in the instance state.

    How do I file a bug report for this?

  • Hi Tomasz,

    Thanks for your update.

    To address your questions, please find answers below:

    Question: Which format data should I pick to force TDM mode: ICodec_DataType_TDM or ICodec_DataType_DSP?

    It should be ICodec_DataType_TDM

    Question: Which structure/function of the public interface aic31.h informs a codec about number of TDM slot that is occupied for specific instance?

    typedef struct ICodec_ChannelConfig {
        Uint32 samplingRate;                        /**< Audio data sampling rate                       */
        Uint32 chanGain;                              /**< The intial gain for the channel                */
        Uint32 bitClockFreq;                         /**< Bit Clock speed                                */
        Uint32 numSlots;                             /**< Number of slots                                */
    }ICodec_ChannelConfig;

    The above structure ICodec_ChannelConfig in ICodec.h, in which numSlots informs a codec about number of TDM slots for a single instance.

    Thanks & regards,
    Sivaraj K

    -------------------------------------------------------------------------------------------------------
    Please click the Verify Answer button on this post if it answers your question.
    -------------------------------------------------------------------------------------------------------

  • There's more to this story...

    The bug occurs only if a non "BIOS_WAIT_FOREVER" timeout was specified in the creation of the GIO_Handle for the Tx channel.  The GIO_submit() function times out and returns, AND THEN the UART driver's SWI TX handler has a go at the packet buffer.  If the timeout is forever, the transmission completes successfully and then the Sem is posted and the Submit() returns. 

    I won't post any more about GIO/BIOSPSP  3 drivers here, since the problem of this thread does not appear to be associated with GIO.

     

     

  • Hello Tomasz Wojtaszek,

    I am new to codec programming. I have a da vinci devm6446 board based on TMSC320DM6446.Ihave am using the CODE COMPOSER STUDIO 5.I am unable to get any examples for the dm6446 (mainly DSP examples).I want to run a simple audio loopback for the C64+ DSP AND THE AIC33 codec chip, .it would be helpful if you can please send some c code/link for the code for the above purpose.

    thanks and regards

    akash