[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: How does clk gated work?



Hi,

Anders and I have discussed this matter off-line. Below follows
a summary of the discussion:

1. Gated clock should be used when frame_rate != 0 to tell
   the receiver when data is valid.
2. The synchronous serial port is designed to run 
   continously and is not intended to send data once in a
   while. Most synchronous serial port have an "idle" or
   "nop" command that can be sent when no useful data
   is available. The synchronous serial port clock in
   ETRAX is always running even if there is no data
   available for transmission (underflow).

There are two possible solutions:
1. Enable the tr_ready interrupt and disable the 
   synchronous serial port transmitter in the
   interrupt handler.
2. Busy-wait for the transmission to finish and
   then disable the port. Note that it takes
   a lot of time to send a byte if the tranmit
   clock freequency is low.

/Mikael

-----Original Message-----
From: owner-dev-etrax@xxxxxxx.com]On">mailto:owner-dev-etrax@xxxxxxx.com]On
Behalf Of Anders Hasselqvist
Sent: Thursday, April 25, 2002 4:22 PM
To: Mikael Starvik
Cc: dev-etrax
Subject: RE: How does clk gated work?


Hi,

We made the changes you suggested but it still doesn't work as we think it
should. We want the clock to run only when we have written data to the
transmit register (a 32 bit transfer)

Here is the source to give you a better understanding:
--------------------
#define VS1001K_MAJOR 240
#define DEFAULT_FRAME_RATE 0
#define DEFAULT_WORD_RATE 31

static int __init vs1001k_init(void)
{
        if (register_chrdev(VS1001K_MAJOR,"vs1001k mp3 decoder", &vs1001k_fops) <0 )
        {
                printk("unable to get major for vs1001k driver\n");
                return -EBUSY;
        }
        /* deselect sync ports */
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, ser3, select);
        *R_GEN_CONFIG_II = gen_config_ii_shadow;

        SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra);
        *R_PORT_PB_I2C = port_pb_i2c_shadow;
        SETS(port_pb_dir_shadow, R_PORT_PB_DIR, dir7, output);
        SETS(port_pb_dir_shadow, R_PORT_PB_DIR, dir6, output);
        SETS(port_pb_dir_shadow, R_PORT_PB_DIR, dir5, input);
        *R_PORT_PB_DIR = port_pb_dir_shadow;

        *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = (
          IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec)         |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec)         |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4)           |
          IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal)         |
          IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, DEFAULT_FRAME_RATE)|
          IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE));

        *R_SYNC_SERIAL1_CTRL = sync_ctrl_data_shadow =
          IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz)      |
          IO_STATE(R_SYNC_SERIAL1_CTRL, dma_enable, off)        |
          IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, error, normal)          |
          IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal)     |
          IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, bit)        |

          IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on)             |
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, gated)        |
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped)      |
          IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb)          |
          IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable)     |
          IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8)       |
          IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8)        |
          IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled)    |
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg)      |
          IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal) |
          IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, normal)|
          IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, inverted)   |
          IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal)   |
          IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)  |
          IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, low);


        /* select sync ports */
        SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
        *R_GEN_CONFIG_II = gen_config_ii_shadow;
        printk("vs1001k driver\n");
        return 0;
}

static int vs1001k_open(struct inode *inode, struct file *file)
{
        if (vs1001k.in_use == 1)
        {
                DEBUG(printk("Device is busy.. \n"));
                return -EBUSY;
        }
        vs1001k.in_use = 1;

        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, enable);

        *R_SYNC_SERIAL1_CTRL = sync_ctrl_data_shadow;

        return 0;
}

static int vs1001k_release(struct inode *inode, struct file *file)
{
        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, stopped);
        SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, disable);
        //SETS(sync_ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, disable);
        *R_SYNC_SERIAL1_CTRL = sync_ctrl_data_shadow;
        vs1001k.in_use = 0;
        return 0;
}

static ssize_t vs1001k_write(struct file * file, const char * buf,
                                 size_t count, loff_t *ppos)
{
        unsigned dummy;

        copy_from_user(vs1001k.out_buffer, buf, count);

        dummy = *R_SYNC_SERIAL1_STATUS;

        *R_SYNC_SERIAL1_TR_DATA = (unsigned)0xa0ff00b0;

        udelay(100);
        return count;
}

module_init(vs1001k_init);
----------------------



Thanks for your fast replies!

We hope you will find something seriously wrong with what we are doing ;-)

Regards,
Anders & Björn

On Thu, 25 Apr 2002, Mikael Starvik wrote:
> I think that the problem is that you set error to ignore. With
> error set to igonre the synchronous serial port continues to
> tranmsit data even if there is no data available for transmission.
>