SPI error

Showing results for 
Search instead for 
Did you mean: 

SPI error

Contributor IV


I'm developping a driver for iMX28 to communicate with an external peripheral.

I use :

- iMX283

- Linux with freescale patch

- bus SPI between the 2 devices.

The external peripheral is xr20m1280 http://www.exar.com/connectivity/uart-and-bridging-solutions/i2c-spi-uarts/xr20m1280

the xr20m1280 have an internal fifo of 128bytes and I try to read this fifo. I write a driver with a read function :

int xr20m1280_read (struct char_interface_data *data, size_t len)


    struct xr20m1280_data_t *private = container_of(data,

        struct xr20m1280_data_t, char_interface_data);

    struct spi_device *spi = data->spi;

    unsigned char *p_buffer = data->buffer;

    unsigned char config_tab[] = {

        XR20M1280_REG_LINE_CTRL, 0xBF,

        XR20M1280_REG_FCTR, 0x70,



        XR20M1280_REG_LINE_CTRL, 0x03,

        //XR20M1280_REG_EMSR, 0x05,

        XR20M1280_REG_EMSR, 0x00,

        XR20M1280_REG_IRQ_ENABLE, 0x01,

        XR20M1280_REG_SPECIAL_FUNCT, 0x10,

//        XR20M1280_REG_FIFO_CTRL, 0x07, //pour le test, on fait un reset des fifo avant le debut des transfert


    size_t remain_len;

    unsigned long irq_flags;

    int ret, i, len_buf;

    unsigned int read_time_out = 0;

    unsigned char data_spi[128 + 1];



    unsigned char reg_rhr = XR20M1280_SPI_WR_BYTE_2_RD(XR20M1280_REG_RHR);


    struct spi_transfer command_spi = {

        .tx_buf = &reg_rhr,

        .len = 1,




    struct spi_transfer data_xfer_spi_1 = {

        .rx_buf = data_spi,

        .len = 128,



    struct spi_message xfer_message;







    for (i=0; i<sizeof(config_tab); i+=2)

        spi_write(spi, config_tab + i, 2);



    private->xfer_mode = XR20M1280_RX_MODE;



    read_time_out = 15000000;

    do {

        ret = gpio_get_value(PINID_XR20M1280_IRQ);




    while (!((0 == ret)||(read_time_out == 0)));

    if (read_time_out == 0) {

        printk("time out (15s) !!!\n");

        return 0;




    spi_message_add_tail(&command_spi, &xfer_message);

    spi_message_add_tail(&data_xfer_spi_1, &xfer_message);


    spi_async(spi, &xfer_message);



    return 0;


When I try use the driver in user space, I have this error

Internal error: Oops - undefined instruction: 0 [#1] PREEMPT
last sysfs file: /sys/devices/platform/mxs-spi.0/spi1.2/char_interface/char_interface1.2/v
Modules linked in:
CPU: 0    Not tainted  ( #325)
PC is at 0xc3c64b94
LR is at mxs_spi_handle+0x288/0x310
pc : [<c3c64b94>]    lr : [<c0275878>]    psr: 80000013
sp : c3dd1f38  ip : c3dd1f08  fp : c3dd1f84
r10: 00000002  r9 : c3df7918  r8 : c3f7de78
r7 : c57fffff  r6 : c3f7de58  r5 : 00000000  r4 : c3f7de3c
r3 : c3c648d0  r2 : 00000003  r1 : 00000080  r0 : c3ce2e60
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 0005317f  Table: 43f8c000  DAC: 00000017
Process mxs-spi.0 (pid: 958, stack limit = 0xc3dd0270)
Stack: (0xc3dd1f38 to 0xc3dd2000)
1f20:                                                       00000080 c3dd1f54
1f40: c3dd1f50 00000000 c3df7954 c0043c40 00000000 00000000 c0393b44 c3df7944
1f60: c3dd0000 c3df7940 c3dfbdc0 c02755f0 00000000 c3dfbdc8 c3dd1fc4 c3dd1f88
1f80: c005cd14 c0275600 c04c5f1c 00000000 c3c648a0 c00609fc c3dd1f98 c3dd1f98
1fa0: c3dd1fcc c3c23dc8 c3dfbdc0 c005cb80 00000000 00000000 c3dd1ff4 c3dd1fc8
1fc0: c006066c c005cb90 00000000 00000000 c3dd1fd0 c3dd1fd0 c3c23dc8 c00605e4
1fe0: c004c78c 00000013 00000000 c3dd1ff8 c004c78c c00605f4 00000000 00000000
[<c02755f0>] (mxs_spi_handle+0x0/0x310) from [<c005cd14>] (worker_thread+0x194/0x25c)
[<c005cb80>] (worker_thread+0x0/0x25c) from [<c006066c>] (kthread+0x88/0x90)
[<c00605e4>] (kthread+0x0/0x90) from [<c004c78c>] (do_exit+0x0/0x6d8)
r7:00000013 r6:c004c78c r5:c00605e4 r4:c3c23dc8
Code: c3cae000 00000002 80208140 00000000 (ffffffff)
root@imx28evk:~# ---[ end trace be4809855772e467 ]---

is there someone who know this problem ?

Labels (1)
0 Kudos
2 Replies

Senior Contributor I

You use spi_async(), yet your xfer_message variable is allocated on stack. spi_async() will return immediatelly and once you leave this function ... puff ... your xfer_message is gone as well. Thus the crash I suspect. Use spi_sync() instead.

0 Kudos

Contributor IV

Thanks for your help.

After my post I continued to search the solution ans I resolved the problem.

When you do a PSI transfer with spi_async, you need :

- create an handler function in your driver (for example xr20m1280_completion_handler

- add this line after spi_message_init

          xfer_message.complete = xr20m1280_completion_handler;

          xfer_message.context = NULL;

0 Kudos