• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Embedded Software » Linux » Linux forum » Question Regarding linux McBSP driver on OMAP3530
Share
Linux
  • Forum
Options
  • Subscribe via RSS

Forums

Question Regarding linux McBSP driver on OMAP3530

This question is answered
Joshua Cassity
Posted by Joshua Cassity
on Jan 23 2011 13:01 PM
Prodigy100 points

Hello!

I am attempting to write a linux driver to interface with the TI ADS1278 analog to digital converter using McBSP3 with SDMA.  To do this, I need the McBSP to supply both clock and frame-sync signals.  Since I am using McBSP3, it is necessary for these signals to come from FSX and CLKX as FSR and CLKR are connected internally to FSX and CLKX.

The problem is that transmit appears to be functional but nothing is being received.  I have successfully configured FSX and CLKX to provide the necessary signals, and can see them clearly on the scope along with the data from the ADS1278, but the RBUFFSTAT register remains zero at all times and no SDMA requests are being issued.  It is almost like the receiver is not using FSX and CLKX properly like it should, but I simply cannot see where I am misconfiguring the registers.

I am curious about the omap_mcbsp_set_io_type() function.  Since I am using SDMA, I do not want the CPU to poll for data completion nor do I want an interrupt to be requested until the SDMA issues a callback.  So I am not sure which option I should choose.  I went with OMAP_MCBSP_POLL_IO but that may not be the correct choice.

Any help would be appreciated!  Thanks!

I am using linux 2.6.32 built by openembedded.

Here is my McBSP initialization code:

#define MCBSP_ID 3

....

    // Initialize McBSP
    status = omap_mcbsp_set_io_type(MCBSP_ID, OMAP_MCBSP_POLL_IO);
    if(status)
    {
        printk(KERN_ERR "Error: Could not configure McBSP3.  Error Code: %d.\n", status);
        return -1;
    }
    status = omap_mcbsp_request(MCBSP_ID);
    if(status)
    {
        printk(KERN_ERR "Error: Could not request McBSP3.  Error Code: %d.\n", status);
        return -1;
    }
    // Register configuration.
    memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); // Set all register values to zero before configuration.
    mcbsp_cfg.rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_24);
    mcbsp_cfg.rcr1 |= RFRLEN1(0); // Set frame length to 1 word.  For more channels, this number will increase
    mcbsp_cfg.pcr0 |= CLKRP; // Sample data on rising edge of clk
    mcbsp_cfg.pcr0 |= FSXM;
    mcbsp_cfg.pcr0 |= CLKXM;
    mcbsp_cfg.pcr0 |= CLKXP;
    mcbsp_cfg.srgr1 |= FWID(0);
    mcbsp_cfg.srgr1 |= CLKGDV(48); // 96 MHz / 48 = 2 MHz clock
    mcbsp_cfg.srgr2 |= FPER(160);
    mcbsp_cfg.srgr2 |= FSGM;
    mcbsp_cfg.srgr2 |= CLKSP;
    mcbsp_cfg.spcr2 |= FRST;
    mcbsp_cfg.spcr2 |= FREE;
    mcbsp_cfg.rccr |= RDMAEN; // Enable DMA receive requests
    mcbsp_cfg.rcerc = 0x1;

    omap_mcbsp_enable_clks(MCBSP_ID);

    omap_mcbsp_config(MCBSP_ID, &mcbsp_cfg); // Configures the McBSP registers

    // Ensure that the necessary clock is enabled.
    DEVCONF1 = (u32 *) ioremap(OMAP3530_GENERAL_BASE+OMAP3530_CONTROL_DEVCONF1, 4);
    reg = *DEVCONF1;
    reg &= 0xFFFFFFFE;
    *DEVCONF1 = reg;
    iounmap((void *) DEVCONF1);

    omap_mcbsp_set_rx_threshold(MCBSP_ID, 100);

    mcbsp_physbuff = (dma_addr_t) kmalloc(150*4, GFP_KERNEL | GFP_DMA);

    /* Some non-mcbsp, non-DMA stuff */

    ads1278_dma_setup();
    omap_mcbsp_start(MCBSP_ID, 1, 1);

And my DMA configuration code is as follows:

int ads1278_dma_setup(void)
{
    if(!omap_mcbsp_check_valid_id(MCBSP_ID))
    {
        printk(KERN_ERR "Error: Invalid McBSP id(%d) specified in DMA setup.\n", MCBSP_ID);
        return -1;
    }
    mcbsp = id_to_mcbsp_ptr(MCBSP_ID);

    if(omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX", ads1278_mcbsp_dma_callback, mcbsp, &dma_rx_ch))
    {
        printk(KERN_ERR "Error: Unable to request DMA channel for McBSP #%d RX.\n", MCBSP_ID);
        return -1;
    }

    mcbsp->dma_rx_lch = dma_rx_ch;

    printk(KERN_INFO "McBSP%d RX DMA(%d) on channel %d\n", mcbsp->id, mcbsp->dma_rx_sync, dma_rx_ch);

    sync_dev = mcbsp->dma_rx_sync;

    omap_enable_dma_irq(mcbsp->dma_rx_lch, 0x01);

    omap_set_dma_transfer_params(mcbsp->dma_rx_lch,
                                                             OMAP_DMA_DATA_TYPE_S32,
                                                             100, 1,
                                                             OMAP_DMA_SYNC_ELEMENT,
                                                             sync_dev, 1);

    omap_set_dma_src_params(mcbsp->dma_rx_lch,
                                                    src_port,
                                                    OMAP_DMA_AMODE_CONSTANT,
                                                    mcbsp->phys_base + OMAP_MCBSP_REG_DRR1,
                                                    0, 0);

    omap_set_dma_dest_params(mcbsp->dma_rx_lch,
                                                     dest_port,
                                                     OMAP_DMA_AMODE_CONSTANT,
                                                     mcbsp_physbuff,
                                                     0, 0);

    omap_start_dma(mcbsp->dma_rx_lch);

    return 0;
}

I relied pretty heavily on omap_mcbsp_recv_buffer in mcbsp.c when writing my DMA setup function.  When I try to run omap_mcbsp_recv_buffer directly, it waits forever for completion.

My DMA callback function is pretty simple at present:

static void ads1278_mcbsp_dma_callback(int lch, u16 ch_status, void *data)
{
    callback_timer++;
}

I can ping callback_timer whenever I want, which is how I know that the callback is never being called.

Linux omap3530 McBSP sdma
Report Abuse
  • Reply
You have posted to a forum that requires a moderator to approve posts before they are publicly available.
All Replies
  • Vincent Ajit
    Posted by Vincent Ajit
    on Sep 12 2011 06:06 AM
    Prodigy120 points

    Hi David,

    Thanks a lot. I have one doubt. How did you manage to call  the macro,

    mcbsp = (struct omap_mcbsp *)id_to_mcbsp_ptr(MCBSP_ID);

    from your loadable module. Or have u added your fns inside  the plat-omap/mcbsp.c itself?

    Also if possible could u shed some light on the driver read() part with us.

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
  • Vincent Ajit
    Posted by Vincent Ajit
    on Sep 12 2011 06:42 AM
    Prodigy120 points

    Hi,

    Can u try setting the buffer as max_thresh where,

    max_thresh = omap_mcbsp_get_max_rx_threshold(busid)

    omap_mcbsp_set_rx_threshold(MCBSP_ID, max_thresh);

    Then, does it work?

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
  • Vincent Ajit
    Posted by Vincent Ajit
    on Sep 12 2011 06:45 AM
    Prodigy120 points

    Hi, Can u try setting the buffer as max_thresh where, max_thresh = omap_mcbsp_get_max_rx_threshold(busid) omap_mcbsp_set_rx_threshold(MCBSP_ID, max_thresh); Then, does it work?

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
  • Ramgopal Kota
    Posted by Ramgopal Kota
    on Apr 04 2012 00:28 AM
    Prodigy20 points

    Hi Tom,

    Are you able to communicate using McBSP ?

    I am also writing a McBSP driver to communicate using McBSP1 to AD7266 chip. I am not seeing dma_callback

    Can you share your kernel module so that I can use that as an example to accomplish my task ?

    Thanks in advance,

    Ramgopal Kota

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
  • Jon Silver
    Posted by Jon Silver
    on Jul 26 2012 08:36 AM
    Prodigy10 points

    I am trying do the same and your driver is very cool! I was trying a lot of configures mcbsp, but dma callback doesn't calling.( When i set rx treshold to 0 and dma_block_size to 1,  callback works, but it calls in random time and returns the same data many times.

    The last config was:

    mcbsp_config.rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_24);
    //Recive frame length: 0 == 1 word, For more channels, this number will increase
     mcbsp_config.rcr1 |= RFRLEN1(0);

    //New
    mcbsp_config.rcr1 |= RDATDLY(1);

    //mcbsp_config.rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_24);
     //mcbsp_config.rcr2 |= RDATDLY(1);

    //Pin control
    //Recive flow polarity, Sample data on rising edge of clk
    mcbsp_config.pcr0 |= CLKRP;
    //Transmit frame sync
    mcbsp_config.pcr0 |= FSXM;
    //Transmit clock mode (Internal)
    mcbsp_config.pcr0 |= CLKXM;
    //Transmit flow polarity
    mcbsp_config.pcr0 |= CLKXP;

    //Recive frame sync
    //mcbsp_config.pcr0 |= FSRM;
    //Recive clock mode (Internal)
    //mcbsp_config.pcr0 |= CLKRM;

    //Sample rate generator 1
    //Frame width
    mcbsp_config.srgr1 |= FWID(0);
    //Clock divider 96 MHz Default, 48 div = 2MHz
    mcbsp_config.srgr1 |= CLKGDV(48);

    //New
    mcbsp_config.srgr1 |= CLKSM;
    mcbsp_config.srgr1 |= CLKSP;

    //Sample rate generator 2
    //Frame period
     mcbsp_config.srgr2 |= FPER(511);
    //Sample rate generator
    mcbsp_config.srgr2 |= FSGM;

    //Serial port control 1
    //Recive interrupt mode RSyncErr
    mcbsp_config.spcr1 |=RINTM(3);

    //New
    //mcbsp_config.spcr1 |= RJUST(1);


    //Serial port control 2
    //mcbsp_config.srgr2 |= CLKSP;
    //mcbsp_config.spcr2 |= FRST;
    mcbsp_config.spcr2 |= FREE;

    //mcbsp_config.spcr1 |= ALB;

    //Recive conf control
    //Recive DNA bit
    mcbsp_config.rccr |= RDMAEN; // Enable DMA receive requests
    //mcbsp_config.rccr |= RFULL_CYCLE;


    //Recive channel
    //mcbsp_config.rcera = 0x3;

    //Transmit control 1
    //mcbsp_config.xcr1 |= XFRLEN1(OMAP_MCBSP_WORD_16);
    //mcbsp_config.xcr1 |= XWDLEN1(0);

    //Transmit conf control
    //Loopback
    //mcbsp_config.xccr |= DLB;
    //Dma enable bit
    //mcbsp_config.xccr |= XDMAEN;

    //Transmit channel
     //mcbsp_config.xcerc = 0x1;

     

     

     

    I also try to read data through recv and pool, but nothing works:

    //Read thread
    static int readF(void *data)
    {
    int j = 0;

    int pg = 0;
    pg=get_order(dma_size * 4);

    rx_data.data = kzalloc(dma_size * 4, GFP_KERNEL | GFP_DMA);
    memset(rx_data.data, 0xFF, dma_size * 4);

    if (!rx_data.data)
    return -ENOMEM;

    //rx_data.dma_handle = dma_map_single(ads1274_dev.dev, rx_data.data, dma_size * 4,DMA_FROM_DEVICE);
    rx_data.dma_handle = (dma_addr_t)dma_alloc_coherent(NULL,(size_t)(PAGE_SIZE<<pg), rx_data.data,0);
    if (!rx_data.dma_handle)
    return -ENOMEM;

    for (j = 0; j < 100; j++) {
    u32 buf = 1;
    //buf = omap_mcbsp_recv_word(MCBSP_ID);
    //if (omap_mcbsp_pollread(MCBSP_ID, &buf)) {
    //buf = omap_mcbsp_recv_word(MCBSP_ID);
    //if (buf == 0) {

    //if (omap_mcbsp_recv_buffer(MCBSP_ID, rx_data.dma_handle, 1)){
    if (omap_mcbsp_spi_master_recv_word_poll(MCBSP_ID, &buf)) {
    printk(KERN_INFO "Read Err\n");

    continue;
    }

    //int dat = 0;
    //memcpy(&dat, rx_data.data, 4);
     printk(KERN_INFO "Read OK Buf 0x%04x\n", buf);
    //printk(KERN_INFO "Read OK HANDLE 0x%04x\n", rx_data.dma_handle);
    //printk(KERN_INFO "Read OK DATA 0x%04x\n", *(u32 *)rx_data.data);
    }

    return 0;
    }

     

    If anybody has any suggestions please write!

    Thank you.

    Alex 

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
12
TI E2E™ Community
  • Support Forums
  • Blogs
  • Videos
  • Groups
  • Site Support & Feedback
  • Settings
TI E2E™ Community Groups
  • TI University Program
  • Make the Switch
  • Microcontroller Projects
  • Motor Drive & Control
Other Communities
  • Deyisupport
  • Designsomething.org
  • beagleboard.org
  • TI on Element 14
  • TI on TechXchangeSM
Other Technical & Support Resources
  • WEBENCH® Design Center
  • Product Information Centers
  • Technical Documents
  • TI Design Network
  • TI Technical Articles
  • TI Training

All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
embedded processors, along with software, tools and the industry’s largest sales/support staff.

© Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy Policy | Terms of Use