Post Go back to editing

Using SHARC cores independently

Category: Hardware
Product Number: SC-589

Hi all,

I'm using the SC-589 on some custom hardware, with the bare metal framework. The hardware is organised such that there are two ADCs (both the same device, same settings), and I would like to feed each on into its own SHARC core for processing. ADC1 and SHARC core 1 are working fine using elements of the bare metal framework with custom initialisation code for the ADC. There is not audio out for the application, so I'm calculating the RMS of each channel and feeding this out on the UART once per second. As per the bare metal framework, I'm using I2S data into SPORT0 on SHARC core 1.

For SHARC core 2, the code functionality requirement is identical, the only changes are that SPORT 4, connected via DAI1 is used instead of SPORT0 on DAI0.

The code for SHARC core 1 has been duplicated for core 2, with the exceptions of:

  • Changes to the SRU to connect the relevant DAI1 pins to SPORT4.
  • Use of DMA11 interrupt for SPORT4B data reception
  • Using a different TPU interrupt for the audio callback handler. 

Whilst the code on SHARC core 1 works fine in terms of representative RMS values visible on the serial port, the values from the channels on SHARC core 2 are always 0. I've traced all the core 2 framework code through - both the dma handler and audio callback handler are working properly (checked with toggling pins on callback), and no samples are being dropped. Following the code back, and inserting known values into the buffers, it seems the issue is with the start of the dma routine - this seems to pull in only 0's to the input channels buffer:

    // Artificially fill buffers:
    for (i = 0; i < AUDIO_CHANNELS * AUDIO_BLOCK_SIZE; i++) {

        ADC2_audiochannels_in[i] = 1;
    }


    // This is where we're getting stuck - sport4_dma_rx_0_buffer or sport4_dma_rx_1_buffer seems to be pulling in 0's

    if (    (uint32_t)sport_dma_cfg->dma_descriptor_rx_0_list.Next_Desc !=
            (*sport_dma_cfg->pREG_DMA_RX_DSCPTR_NXT)
            )  {

        audioflow_float_to_fixed(ADC2_audiochannels_out, sport4_dma_tx_0_buffer, AUDIO_CHANNELS * AUDIO_BLOCK_SIZE);
        audioflow_fixed_to_float(sport4_dma_rx_0_buffer, ADC2_audiochannels_in,  AUDIO_CHANNELS * AUDIO_BLOCK_SIZE);



    }
    else
    {
        audioflow_float_to_fixed(ADC2_audiochannels_out, sport4_dma_tx_1_buffer, AUDIO_CHANNELS * AUDIO_BLOCK_SIZE);
        audioflow_fixed_to_float(sport4_dma_rx_1_buffer, ADC2_audiochannels_in,  AUDIO_CHANNELS * AUDIO_BLOCK_SIZE);


    }

Artificially filling the buffers with known values after this point results in the RMS value jumping as expected.

So it would seem that the issue would be to do with the SRU, however I've double checked this with the graphical Signal Routing Unit configuration, and using the code below:

    // Set up DAI pins as inputs and outputs for ADC 1
    SRU(LOW,  DAI0_PBEN16_I);        // ADC1 BCLK is an input
    SRU(LOW,  DAI0_PBEN17_I);        // ADC1 DAT is an input
    SRU(LOW,  DAI0_PBEN18_I);        // ADC1 WS Out is an input

    // Route BCLK and FS to SPORT 0 (which connects to DAI0)
    SRU(DAI0_PB16_O, SPT0_ACLK_I);     // route ADC1 BCLK pin to SPORT0A clock input
    SRU(DAI0_PB16_O, SPT0_BCLK_I);     // route ADC1 BCLK pin to SPORT0B clock input
    SRU(DAI0_PB18_O, SPT0_AFS_I);         // route ADC1 FS pin to SPORT0A frame sync
    SRU(DAI0_PB18_O, SPT0_BFS_I);         // route ADC1 FS pin to SPORT0B frame sync
    // Route data signals
    SRU(DAI0_PB17_O, SPT0_BD0_I);        // route ADC1 SDATA Out pin to SPORT0B-D0 input

//    SRU(HIGH,  DAI0_PBEN01_I);        // Loopback BCLK is an output
//    SRU(HIGH,  DAI0_PBEN02_I);        // Loopback DAT is an output
//    SRU(HIGH,  DAI0_PBEN03_I);        // Loopback WS Out is an output

//    Route out to exposed pads for debug
//    SRU(DAI0_PB16_O, DAI0_PB01_I);
//    SRU(DAI0_PB17_O, DAI0_PB02_I);
//    SRU(DAI0_PB18_O, DAI0_PB03_I);


    // Set up DAI pins as inputs and outputs for ADC 2
    SRU2(LOW,  DAI1_PBEN16_I);        // ADC2 BCLK is an input
    SRU2(LOW,  DAI1_PBEN17_I);        // ADC2 DAT is an input
    SRU2(LOW,  DAI1_PBEN18_I);        // ADC2 WS Out is an input



    // Route BCLK and FS to SPORT 4 (which connects to DAI1)
    SRU2(DAI1_PB16_O, SPT4_ACLK_I);     // route ADC2 BCLK pin to SPORT4A clock input
    SRU2(DAI1_PB16_O, SPT4_BCLK_I);     // route ADC2 BCLK pin to SPORT4B clock input
    SRU2(DAI1_PB18_O, SPT4_AFS_I);         // route ADC2 FS pin to SPORT4A frame sync
    SRU2(DAI1_PB18_O, SPT4_BFS_I);         // route ADC2 FS pin to SPORT4B frame sync
    // Route data signals
    SRU2(DAI1_PB17_O, SPT4_BD0_I);        // route ADC2 SDATA Out pin to SPORT4B-D0 input

//    SRU2(HIGH,  DAI1_PBEN01_I);        // Loopback BCLK is an output
//    SRU2(HIGH,  DAI1_PBEN02_I);        // Loopback DAT is an output
//    SRU2(HIGH,  DAI1_PBEN03_I);        // Loopback WS Out is an output

// 	  Route out to exposed pads for debug
//    SRU2(DAI1_PB16_O, DAI1_PB01_I);
//    SRU2(DAI1_PB17_O, DAI1_PB02_I);
//    SRU2(DAI1_PB18_O, DAI1_PB03_I);

Scoping test points show all the correct I2S signals are present on the right pins, and I can route the I2S data back out onto a spare test point on another DAI1 pin, which would seem to indicate the routing works, so I'm at a bit of a loss as to where the issue is. Any insight would be greatly appreciated! 

  • Hi  ,

    Can you share a screenshot of your settings for your port input enable control registers for DAI0 and DAI1? (Code or register values from CCES would suffice). 

  • Sure:
    *pREG_PADS0_DAI0_IE = (unsigned int)0x001FFFFE;
    *pREG_PADS0_DAI1_IE = (unsigned int)0x001FFFFE;

    I did have a look for these both within the header files and the hardware reference, but I couldn't find an explanation of their function and / or how to modify. 

  • Hi  , 

    The PADS0_DAIn_IE are used for enabling the input control of the DAI. You can find this description in the hardware reference manual. However, what you have there looks correct to me. If you are seeing your TDM callbacks firing that seems like a good indication that your SRU clock routing is correct.

    To confirm, are you also able to see some activity on ADC2 SDATA (DAI1_PIN17) - not just a flat line? 

    What does your Sport 4 configuration look like? Are your Sport buffers in aligned, uncached memory? (A screenshot would be helpful). 

  • Hi  thanks for your help again!

    Yep - test point on DAI1-17 is showing what looks like a pretty reasonable I2S data signal, correct logic levels and timing about right etc. 

    Floating point buffers below:

    And Sport4 config below: 

    The Sport4 config is the same (except sport no. and DMA buffers) as that for Sport0, which is working fine with ADC1, so I don't think that would be the source of any issues.

    Will try routing to a different data pin and an alternative SPORT today to see how that goes. 

  • Update:
    Changing the D0 input pin for SPORT4 using spare pins and test points doesn't help, neither does configuring a different SPORT (7).

    Interestingly, if I port out D0 from SPORTx_A to a spare test point, I appear to get valid I2S data from both cases (ADC1 / Core 1 / SPORT0, ADC2 / Core2 / SPORT4), however if I use the audiocallbacks to set all output data to 0,  all action ceases on the pin for Core 1, however data is still observed for the Core 2 case. 

  • Hi  ,

    Thank you for the detailed analysis! Let me try to set up and reproduce your issue on my end to see if I can figure out what is going on. 

    In the meanwhile, a couple of additional questions: 

    1. Where are your Sport and DMA buffers initialized? Are you initializing them on one core? If so, which core? 

    2. When your sport callback on SHARC1 (second SHARC core) fires, can you view in the debugger, the address of the DMA buffer that is passed in? Does this address match the address that the compiler set up for the buffer? In the debugger, you can add sport4_dma_rx_0_buffer to the watch window and to get the address, you take the address: &sport4_dma_rx_0_buffer. Do this for all four buffers. At least one of these addresses should match the address passed into your TDM callback. 

    3. If you move all of the Sport 4 setup/callbacks, etc. to SHARC0 instead (alongside) ADC1, do you get proper data in your callback? 

  • No prob, thanks again for sticking with this!

    Sport and DMA buffers are initialised in the relevant SHARC core (i.e. Sport 0 and associated DMA buffers for ADC1 initialised in SHARC0, Sport 4 & DMA for ADC2 in SHARC1). 

    I seem to be struggling to do this - adding them to the watched expressions list see's them flagged up as 'Unknown variable or symbol', despite adding by highlighting them in the code, right click -> add to watch expression. This might be my lack of familiarity with CCES, so I'll keep trying!

    I've moved everything from SHARC1 into SHARC0, operating two DMA callbacks and 2 audio processing callbacks. This actually seems to work, and measured signal levels look about right for all 4 channels across both ADCs with an applied stimulus.