Hi,
I'm developping a driver for iMX28 to communicate with an external peripheral.
I use :
- iMX283
- Linux 2.6.35.3 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_TRIG,0x40,
XR20M1280_REG_TRIG,0x10,
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 = ®_rhr,
.len = 1,
};
struct spi_transfer data_xfer_spi_1 = {
.rx_buf = data_spi,
.len = 128,
};
struct spi_message xfer_message;
/***************/
gpio_direction_output(PINID_XR20M1280_FLOW_CTRL,1);
gpio_set_value(PINID_XR20M1280_TEST,1);
for (i=0; i<sizeof(config_tab); i+=2)
spi_write(spi, config_tab + i, 2);
gpio_set_value(PINID_XR20M1280_TEST,0);
private->xfer_mode = XR20M1280_RX_MODE;
gpio_set_value(PINID_XR20M1280_TEST,1);
read_time_out = 15000000;
do {
ret = gpio_get_value(PINID_XR20M1280_IRQ);
read_time_out--;
udelay(1);
}
while (!((0 == ret)||(read_time_out == 0)));
if (read_time_out == 0) {
printk("time out (15s) !!!\n");
return 0;
}
spi_message_init(&xfer_message);
spi_message_add_tail(&command_spi, &xfer_message);
spi_message_add_tail(&data_xfer_spi_1, &xfer_message);
spi_async(spi, &xfer_message);
gpio_set_value(PINID_XR20M1280_TEST,0);
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 (2.6.35.3-g5577b2c-dirty #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
Backtrace:
[<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 ?
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.
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;