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.

DM8148 McASP write to GBLCTL fails

I am running into an intermittent issue when writing to the McASP GBLCTL register.

8 times out of 10 everything works as expected and McASP and EDMA start up correctly.

I am doing readback of GBCTL to confirm write has completed as expected. I follow the McASP setup sequence from the technical reference manual.

In the failing case writes of 0 (reset), XHCLKRST = ACTIVE then XCLKRST = ACTIVE all succeed. The write to set RSRCLR and XSRCLR ACTIVE fails. So do subsequent writes to set RSMRST and XSMRST ACTIVE and after that the write to set RFRST and XFRST ACTIVE. Any idea why 3 writes would succeed and then 3 writes fail? Also, why does the failure only happen sometimes?


Thanks, Andrew

  • McASP is a fairly fussy thing in my experience, especially the process of taking it out of reset.

    It sounds to me like you're merely reading back GBLCTL and expecting it should immediate have the right value.  This is not the case: GBLCTL doesn't necessarily read back the correct value right away.  You need to keep polling it until it does.  It may be wise to have some timeout on this (although I don't have one, and haven't run into trouble with that yet), but there's no point in continuing with the initialization procedure if a step fails.

  • Good points all. I am reading back GBLCTL in a polling loop and the loop has a timeout. I guess I wasn't 100% clear in my earlier post - it is the timeout that is triggering exit from the loop without GBLCTL being set correctly. I've tried increasing the timeout to 1,000,000, without effect.

  • Hmm, the main difference is that all but the first two reset bits are synchronized to the audio clock, while the first two are responsible for generating the audio clock so obviously can't be synchronized to it.  This suggests something is going wrong with the audio clock, but I'm not sure what.

    I've examined my own McASP initialization code again (it's been a while), and I have a rather different procedure than what the TRM outlines.  Mine is as follows, with McASP 1 internally-generated AHCLKX being used as audio system clock (XREF 1) also for other McASPs.  I will focus on just McASP 0.

    1. Set up audio PLL and clock muxes. Enable McASP modules.
    2. Configure McASP 1 AHCLKX and release it from reset.  Set AHCLKX output enable and configure the pinmux. Audio system clock is now available to all components.
    3. Configure McASP 0 receive section:
      1. config AHCLKR to input (muxed to XREF 1) and release from reset.
      2. config ACLKR divider and release from reset.
      3. configure clock-checking circuit (optional).
      4. configure format, framing, serializers, etc etc.
      5. set relevant output-enables and configure pinmux.
      6. release deserializers from reset
      7. release state machine from reset
      8. release frame sync from reset
    4. Configure McASP 0 transmit section, steps a-e similar to above, but NOT steps f-h.

    At this time the DSP app isn't running yet:  the receive-section will overflow but that's not really a problem, data is simply discarded.  An underflow in the transmit section however is a fatal error, which is why it's not released from reset yet.  From this point on all audio clocks are running and they are never put back into reset.

    The DSP app does not use DMA or the receive FIFO, it is synchronized to the receive section and processes each incoming set of samples at is becomes available.  The transmit FIFO is used to allow a few sets of samples of buffering.  IRQs are only used for errors, currently considered fatal.  Obviously changes will be needed for scenarios that are different from the straightforward "pipeline" we have, but maybe this info will give you ideas on how to tame the McASP.

    When our DSP app starts (or restarts), its procedure is:

    1. Put transmit section (except clocks) and transmit fifo into reset if it isn't already (in case of restart): as mentioned above, if the transmit section isn't serviced it will go into a fatal failure state, reset is needed for recovery.
    2. Clear and enable TX error IRQs on McASP and then clear and enable corresponding DSP irq.  Be sure to read back the last McASP register written (irq-enable in this case) as barrier before performing the clear/enable of the DSP irq, otherwise the clear/enable writes to the McASP might still be in-flight when the clear/enable writes reach the local IRQ controller, potentially resulting in an unintended error interrupt.
    3. Configure and enable TX fifo.  Read back register as barrier (probably not needed here, but better safe than sorry).
    4. Prepare receive section:
      1. If for whatever reason the rx section indicates a DMA error (which is fatal), put it into reset (except clocks), clear status bits and release the section from reset again (deserializers, then state machine, then frame sync).
      2. Otherwise (only overflow occurred, or no error at all), wait until data is available (it probably already is, but just to be sure), read and discard it, clear status bits, wait until data is available again, read and discard it.
      Either way it'll now take about 1 sample time before data becomes available again so you have plenty of time for the remaining initialization.
    5. Enable rx section error IRQs, read back as barrier, clear and enable corresponding DSP irq.

    Now the DSP algorithm starts pre-running: it receives audio but discards output to let the filters stabilize.  After a while it will start writing output into the transmit section fifo.  When the desired amount of buffering has been achieved, the transmit section is released from reset, and shortly thereafter the DAC is instructed to unmute.

    The reads done as barrier are not needed when doing this from the cortex-A8 when the relevant memory is mapped as "strongly ordered", but otherwise writes will be "posted" (buffered) and a readback is necessary to ensure the writes have arrived at the target peripheral, typically used when ordering between transactions to different peripherals is required.  (I've seen drivers refer to reads of this nature as "OCP barriers", probably referring to the memory transaction ordering constraints defined by the Open Core Protocol typically used to interface with the on-chip interconnects.)

  • Andrew,

    Could you provide us more details. Like what is your software, is it EZSDK 5.05.02.00 or DRV RDK or IPNC RDK or else?

    Are you observing this issue on the DM814x EVM or on a DM814x custom board? If custom board, can you try to reproduce this issue on the DM814x EVM?

    Regards,
    Pavel

  • Andrew,

    I am working with the EZSDK 5.05.02.00 / PSP 04.04.00.01 and we have McASP2 support in the linux kernel, files:

    /arch/arm/plat-omap/include/plat/asp.h
    /arch/arm/mach-omap2/board-ti8148evm.c
    /arch/arm/mach-omap2/devices.c
    /sound/soc/davinci/davinci-mcasp.c

    In the McASP linux driver (davinci-mcasp.c), the TX and RX aliases of the GBLCTL register are used (RGBLCTL and XGBLCTL), there is no direct access (read/write) of the GBLCTL register. Can you try the same at your side, do you have any improvement? Below is some code snippet:

    #define DAVINCI_MCASP_GBLCTL_REG    0x44

    #define DAVINCI_MCASP_GBLCTLR_REG    0x60

    #define DAVINCI_MCASP_GBLCTLX_REG    0xa0

    /*
     * DAVINCI_MCASP_GBLCTL_REG -  Global Control Register Bits
     */
    #define RXCLKRST    BIT(0)    /* Receiver Clock Divider Reset */
    #define RXHCLKRST    BIT(1)    /* Receiver High Frequency Clock Divider */
    #define RXSERCLR    BIT(2)    /* Receiver Serializer Clear */
    #define RXSMRST        BIT(3)    /* Receiver State Machine Reset */
    #define RXFSRST        BIT(4)    /* Frame Sync Generator Reset */
    #define TXCLKRST    BIT(8)    /* Transmitter Clock Divider Reset */
    #define TXHCLKRST    BIT(9)    /* Transmitter High Frequency Clock Divider*/
    #define TXSERCLR    BIT(10)    /* Transmit Serializer Clear */
    #define TXSMRST        BIT(11)    /* Transmitter State Machine Reset */
    #define TXFSRST        BIT(12)    /* Frame Sync Generator Reset */

    static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
    {
        int i = 0;

        mcasp_set_bits(regs, val);

        /* programming GBLCTL needs to read back from GBLCTL and verfiy */
        /* loop count is to avoid the lock-up */
        for (i = 0; i < 1000; i++) {
            if ((mcasp_get_reg(regs) & val) == val)
                break;
        }

        if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
            printk(KERN_ERR "GBLCTL write error\n");
    }

    static void mcasp_start_rx(struct davinci_audio_dev *dev)
    {
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);

        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);

        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
    }

    static void mcasp_start_tx(struct davinci_audio_dev *dev)
    {
        u8 offset = 0, i;
        u32 cnt;

        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);

        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
        for (i = 0; i < dev->num_serializer; i++) {
            if (dev->serial_dir[i] == TX_MODE) {
                offset = i;
                break;
            }
        }

        /* wait for TX ready */
        cnt = 0;
        while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
             TXSTATE) && (cnt < 100000))
            cnt++;

        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
    }

    static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
    {
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
            if (dev->txnumevt)    /* enable FIFO */
                mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
                                    FIFO_ENABLE);
            mcasp_start_tx(dev);
        } else {
            if (dev->rxnumevt)    /* enable FIFO */
                mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
                                    FIFO_ENABLE);
            mcasp_start_rx(dev);
        }
    }

    static void mcasp_stop_rx(struct davinci_audio_dev *dev)
    {
        mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
    }

    static void mcasp_stop_tx(struct davinci_audio_dev *dev)
    {
        mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
    }

    static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
    {
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
            if (dev->txnumevt)    /* disable FIFO */
                mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
                                    FIFO_ENABLE);
            mcasp_stop_tx(dev);
        } else {
            if (dev->rxnumevt)    /* disable FIFO */
                mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
                                    FIFO_ENABLE);
            mcasp_stop_rx(dev);
        }
    }

    On some similar e2e threads, possible root cause for that issue is bad HW design for the McASP clock signals or bad SW settings for the MCASP clock signals. Please have a look in the below e2e threads:

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/717/p/246455/863086.aspx#863086

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/99/p/94889/332180.aspx#332180

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/99/p/97610/354584.aspx#354584

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/t/300657.aspx

    http://e2e.ti.com/support/embedded/tirtos/f/355/t/252075.aspx

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/t/150951.aspx

    Regards,
    Pavel

  • It's the "else" case. We write directly to the McASP registers from our DSP code. We have similar code running on other DM814x devices without issue.


    It is our own custom board. We haven't tried to reproduce on an EVM and I don't think it would be possible to do so. I really want to understand under what conditions a write to GBLCTL would fail to complete. I would have thought clocks would have to be missing?

  • Andrew,

    Andrew Elder said:

    We have similar code running on other DM814x devices without issue.


    It is our own custom board.

    When one code run fine in one HW and the same code does not run fine in other HW, this is usually indication of a HW malfunction. Can you double check the HW design and PCB layout of the failing custom board.

    Andrew Elder said:
    I really want to understand under what conditions a write to GBLCTL would fail to complete. I would have thought clocks would have to be missing?

    I think write to GBLCTL register can fail if clocks are missing, slow or synchronization between clocks failed. Below is some extract from the DM814x McASP TRM:

    16.2.9.1 Software Reset Considerations
    The transmitter and receiver portions of the McASP may be put in reset through the global control register (GBLCTL). Note that a valid serial clock must be supplied to the desired portion of the McASP (transmit and/or receive) in order to assert the software reset bits in GBLCTL.

    16.2.10.4 Importance of Reading Back GBLCTL
    In Section 16.2.10.2, steps 3b, 4b, 6c, 8b, and 9b state that GBLCTL should be read back until the bits that were written are successfully latched. This is important, because the transmitter and receiver state machines run off of the respective bit clocks, which are typically about tens to hundreds of times slower than the processor's internal bus clock. Therefore, it takes many cycles between when the processor writes to GBLCTL (or RGBLCTL and XGBLCTL), and when the McASP actually recognizes the write operation.

    Therefore, the logic in McASP has been implemented such that once the processor writes GBLCTL, RGBLCTL, or XGBLCTL, the resulting write is not visible by reading back GBLCTL until the McASP has recognized the change. This typically requires two bit clocks plus two processor bus clocks to occur.

    Also, if the bit clocks can be completely stopped, any software that polls GBLCTL should be implemented
    with a time-out. If GBLCTL does not have a time-out, and the bit clock stops, the changes written to
    GBLCTL will not be reflected until the bit clock restarts.


    16.3.8 Global Control Register (GBLCTL)
    Before GBLCTL is programmed, you must ensure that serial clocks are running.
    If the corresponding external serial clocks, ACLKX and ACLKR, are not yet running, you should select the internal serial clock source in AHCLKXCTL, AHCLKRCTL, ACLKXCTL, and ACLKRCTL before GBLCTL is programmed.

    Can you try to reset the TX and RX blocks simultaneously, this can guarantee a phase relationship if both TX and RX clocks are generated internally.

    You can also explore the McASP code (which involves programming of all three registers: GBLCTL, RGBLCTL, XGBLCTL), from the Mistral web site:

    http://www.mistralsolutions.com/pes-support/support-downloads/tmdxevm8148.html#

    Software -> Diagnostic Software -> Base Board -> Rev D -> aic3106

    Best regards,
    Pavel

  • Andrew Elder said:
    It is our own custom board. We haven't tried to reproduce on an EVM and I don't think it would be possible to do so. I really want to understand under what conditions a write to GBLCTL would fail to complete. I would have thought clocks would have to be missing?

    That is what I'd expect too yes.

    In your initial post you mention XHCLKRST but not RHCLKRST... is RHCLK already out of reset at that point?

    What is the configuration you're using for the HCLKs?  (including relevant muxes)

  • Thanks for the comments. I'll try them out next week. I've also review the links to other e2e discussions and the only real difference between and what I do is the use of GBLCTL vs R/X GBLCTL. I'll see if that makes any difference.

  • Andrew Elder said:

    Thanks for the comments. I'll try them out next week. I've also review the links to other e2e discussions and the only real difference between and what I do is the use of GBLCTL vs R/X GBLCTL. I'll see if that makes any difference.

    I use writes to either of them in different places, as far as I know there's no difference besides the masking.  Beware however that you should always read GBLCTL, since R/X GBLCTL read the requested reset bits rather than the acknowledged reset bits.

    BTW, I regrettably have to report that McASP occasionally fails to come up properly for me as well.  I'm not sure when this problem started to occur, maybe it's been there all along (I don't reboot the board that often).  I haven't had time yet to investigate where it fails, so I don't know yet if it's similar to your problem or not.

  • Some info from the McASP team:

    In general, if you write to GBLCTL, then read back from GBLCTL (NOT XGBLCTL or RGBLCTL) before writing again, you should be OK.  The issue is that the registers run off of the SYSCLK, but the McASP logic runs off of the bit clock.  The alias registers (X* and RGBLCTL) will reflect the written value immediately, but GBLCTL will only reflect the written values once the clock domains have synced.

    Regards,
    Pavel


  • Thanks Pavel. I am doing the GBLCTL readback step. That is how I know the write to GBLCTL fails. I have a timeout in the readback loop.


    Question for McASP team - is there a status bit that I can read to confirm the clock domains have synced? Are the two domains in question the SYSCLK and the bit clock?

    Thanks,

    Andrew

  • This code is incorrect, right?

    static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
    {
        int i = 0;

        mcasp_set_bits(regs, val);

        /* programming GBLCTL needs to read back from GBLCTL and verfiy */
        /* loop count is to avoid the lock-up */
        for (i = 0; i < 1000; i++) {
            if ((mcasp_get_reg(regs) & val) == val)
                break;
        }

        if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
            printk(KERN_ERR "GBLCTL write error\n");
    }

    mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);

    Above code writes to GBLCTLX and reads back GBLCTLX, whereas it should read back GBLCTL. It's a bug right?

     

    Thanks,

    Andrew

  • Andrew,

    Andrew Elder said:
    Question for McASP team - is there a status bit that I can read to confirm the clock domains have synced? Are the two domains in question the SYSCLK and the bit clock?

    McASP team:

    There is no status bit, but reading back GBLCTL and confirming that you can read back what you just wrote IS the confirmation.  Yes, those are the two domains. Usually when you’re writing to the bits in GBLCTL, you’re doing so after a McASP reset (clearing GBLCTL bits).  Is this happening during your init sequence, or during operation?

     

     

  • Andrew,

    Andrew Elder said:
    Above code writes to GBLCTLX and reads back GBLCTLX, whereas it should read back GBLCTL. It's a bug right?

    Yes, this seems to be incorrect.

    McASP team:

    Always read back from GBLCTL.

    XGBLCTL is just there so that you can write 0x00000000 to XGBLCTL and you only end up resetting the TX of McASP.  It just saves you the trouble of having to write to GBLCTL and take care not to accidentally write to the Rx control bits.  That’s all.  You’re still always writing to GBLCTL, in the end.

  • Pavel Botev said:

    Andrew,

    Question for McASP team - is there a status bit that I can read to confirm the clock domains have synced? Are the two domains in question the SYSCLK and the bit clock?

    McASP team:

    There is no status bit, but reading back GBLCTL and confirming that you can read back what you just wrote IS the confirmation.  Yes, those are the two domains. Usually when you’re writing to the bits in GBLCTL, you’re doing so after a McASP reset (clearing GBLCTL bits).  Is this happening during your init sequence, or during operation?

     

    [/quote]

    It is happening during init - have never seen an issue during operation. I decided to switch from external bit clock to internal bit clock and when I do that, I don't see the issue. In my mind that points to something related to the external 256xFS bit clock coming in to the DM814x. The weird thing is that 8 times out of 10 everything works ok, which made me think the issue was related to software timing somehow.

  • Andrew,

    Andrew Elder said:

    This code is incorrect, right?

    static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
    {
        int i = 0;

        mcasp_set_bits(regs, val);

        /* programming GBLCTL needs to read back from GBLCTL and verfiy */
        /* loop count is to avoid the lock-up */
        for (i = 0; i < 1000; i++) {
            if ((mcasp_get_reg(regs) & val) == val)
                break;
        }

        if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
            printk(KERN_ERR "GBLCTL write error\n");
    }

    mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);

    Above code writes to GBLCTLX and reads back GBLCTLX, whereas it should read back GBLCTL. It's a bug right?

    I have check this code with the DM814x EVM and the aplay (the transmit part of the McASP).

    1. I check the value of the GBLCTL register in the below place in the code:

    /* programming GBLCTL needs to read back from GBLCTL and verfiy */
        /* loop count is to avoid the lock-up */
        for (i = 0; i < 1000; i++) {
            if ((mcasp_get_reg(regs) & val) == val)
                break;
        }

      printk("GBLCTL = %x\n",__raw_readl(base + 0x44));

    And the GBLCTL value reflects what we have just write into the GBLCTLX.

    2. I replace GBLCTLX with GBLCTL:

    static void mcasp_start_tx(struct davinci_audio_dev *dev)
    {
        u8 offset = 0, i;
        u32 cnt;

    /*mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);*/


        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTL_REG, TXHCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTL_REG, TXCLKRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTL_REG, TXSERCLR);

    mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);

        /*mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);*/


        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTL_REG, TXSMRST);
        mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTL_REG, TXFSRST);

        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
        for (i = 0; i < dev->num_serializer; i++) {
            if (dev->serial_dir[i] == TX_MODE) {
                offset = i;
                break;
            }
        }

        /* wait for TX ready */
        cnt = 0;
        while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
             TXSTATE) && (cnt < 100000))
            cnt++;

        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
    }

    static void mcasp_stop_tx(struct davinci_audio_dev *dev)
    {
        //mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTL_REG, 0);
        mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
    }

    The McASP TX operation is successful (checked with aplay), the GBLCTL is read-back successfully.

    Best regards,
    Pavel

  • Andrew,

    Andrew Elder said:
    It is happening during init - have never seen an issue during operation. I decided to switch from external bit clock to internal bit clock and when I do that, I don't see the issue. In my mind that points to something related to the external 256xFS bit clock coming in to the DM814x. The weird thing is that 8 times out of 10 everything works ok, which made me think the issue was related to software timing somehow.

    After you switch clocks, are you resetting the whole McASP module?  Usually when you take a clock away and then bring it back, you have to reset the whole module.

     

  • Pavel Botev said:

    Andrew,

    It is happening during init - have never seen an issue during operation. I decided to switch from external bit clock to internal bit clock and when I do that, I don't see the issue. In my mind that points to something related to the external 256xFS bit clock coming in to the DM814x. The weird thing is that 8 times out of 10 everything works ok, which made me think the issue was related to software timing somehow.

    After you switch clocks, are you resetting the whole McASP module?  Usually when you take a clock away and then bring it back, you have to reset the whole module.

     

    [/quote]

    Switch was probably the wrong word. After I change my code to use internal bit clock instead of external bit clock would be a better way to state what I did. I then re-compile the .out file and restart the whole system (reset is pulled low).

  • Andrew,

    Andrew Elder said:
    Switch was probably the wrong word. After I change my code to use internal bit clock instead of external bit clock would be a better way to state what I did. I then re-compile the .out file and restart the whole system (reset is pulled low).

    Sure, but that is still changing clock source.  There’s going to be a discontinuity there.

     

  • Pavel

    Can you tell us which SYSCLK the McASP registers are clocked from?.  The DM814x has many "SYSCLKs"

    thanks

    Steve

  • Stephen,

    The registers of a module are clocked by the interface clock (x_ick). The McASP0/1/2 interface clock is derived from sysclk6 and McASP3/4/5 interface clock is derived from sysclk5.

    ./osc0_clkin_ck/l3_dpll_clkin_ck/l3_dpll_ck/sysclk4_ck/sysclk6_ck/mcasp1_ick

    ./osc0_clkin_ck/l3_dpll_clkin_ck/l3_dpll_ck/sysclk4_ck/sysclk6_ck/mcasp2_ick

    ./osc0_clkin_ck/l3_dpll_clkin_ck/l3_dpll_ck/sysclk4_ck/sysclk6_ck/mcasp3_ick

    ./osc0_clkin_ck/l3_dpll_clkin_ck/l3_dpll_ck/sysclk4_ck/sysclk5_ck/mcasp4_ick

    ./osc0_clkin_ck/l3_dpll_clkin_ck/l3_dpll_ck/sysclk4_ck/sysclk5_ck/mcasp5_ick

    ./osc0_clkin_ck/l3_dpll_clkin_ck/l3_dpll_ck/sysclk4_ck/sysclk5_ck/mcasp6_ick

    Regards,
    Pavel

  • better known as the L3S/L4LS (default 100 MHz) and L3M/L4HS (default 200 MHz) clocks respectively, i.e. those of the interconnect the register block is located on, unsurprisingly.

    PS beware that in linux (from where those clock paths were quoted), annoyingly, the McASPs and various (but not all) other peripherals are renumbered to be 1-based rather than 0-based.

  • Is there a way of powering down the McASP0?.  We know how to stop/start clocks to McASP0:

        /* Enable McASP0, CM_ALWON_MCASP0_CLKCTRL = 0x2 */
        HWREG(    CSL_PRCM_0_REGS +
                CM_ALWON_BASE +
                CM_ALWON_CLKCTRL_BASE +
                CM_ALWON_MCASP0_CLKCTRL) = 0x2;

    The TRM says the McASPs are in the ALWAYS_ON power domain - so maybe the answer is no?.

    -steve

  • Steve,

    As the McASP0 is in the always-on power domain, McASP0 can be clock gated only, McASP0 can not be voltage/power gated.

    Regards,
    Pavel