Hello,
I have worked with DE2i-150 Development Kit for 2 weeks. Now, I'm writing simple Kernel driver for Intel Antom Processor to Read/Write GPIO from FPGA. When I develop driver, I'm having some trouble with my PCI driver.
My driver works something wrong when I reboot DE2i-150 Development kit. It only works well when I "Power off" and " Power on" again.You can see my result below to more clear my problem.
I created my driver with name "altera.ko" end then insert module to the Linux kernel use : insmod altera.ko. I wrote small app to write data to DO PORT and then read data from DO PORT and DI PORT. The sumaries program I attached file with name "app.c"
*Case right: The result when I " Power off" and " Power on" again. I do it again alot of time, and everytime the result well:
[VRD] 542 value write : 0x63 // Value is wrote in DO port
[VRD] 168 test_write : Data write to DO PORT : 0x63
[VRD] 181 test_read_do : Data read from DO PORT: 0x63
[VRD] 210 test_read _di : Data read from DI PORT: 0xffffffff
*Case wrong: The result when I reboot DE2i-150 the first time:
[VRD] 542 value write : 0x63 // Value is wrote in DO port
[VRD] 168 test_write : Data write to DO PORT : 0x63
[VRD] 181 test_read_do : Data read from DO PORT: 0xffffffff
[VRD] 210 test_read _di : Data read from DI PORT: 0x63
=> it seems read inverse value between DI PORT and DO PORT.
But the value right back when I reboot the second times
[VRD] 542 value write : 0x63 // Value is wrote in DO port
[VRD] 168 test_write : Data write to DO PORT : 0x63
[VRD] 181 test_read_do : Data read from DO PORT: 0x63
[VRD] 210 test_read _di : Data read from DI PORT: 0xffffffff
And it get wrong result again when I reboot the third times. End then value right back when I reboot at fourth times. ....I do it again alot of time. I see every once read right value, next once wrong value, .... I hope you can understand my case
I don't understand alot my problem. Maybe it come from "map bar address". But I see I can read right value when I power off and power on again DE2i-150 kit, so I think it ok. I also attached "probe method" code in file "probe.c", can you help me to check it.
I developed my driver in Debian 8: "Linux debian 3.16.0-4-686-pae GNU/Linux".
Can anybody help me to know where is my problem. I hope can read right value every time either "reboot" or "power off".
Thank your for your attention. Thank you very much.
Best & Regard
Bắc
Sorry I can't attached file app.c and probe.c so I write all here, Sorry it's very too long:
* app.c
int main (int argc, char *argv[])
{
int fd;
struct app_opts opts;
long value=0;
opts.di_addr = 0x0020;
opts.do_addr = 0x0000;
opts.dio_bar_no = ALT_DIO_BAR_NO;
opts.rw_bar_no = 0x00;
opts.port_no = 0;
parse_opt(argc, argv, &opts);
fd = open(device, O_RDWR);
if (fd < 0) {
log_err("Open device failed");
return -ENODEV;
}
while(1)
{
value++;
log_info("value: %lu", value);
opts.port_data = value;
test_write(fd, opts); // Function write data to DO PORT
test_read(fd,opts, PORT_IN); // Function read data from DI PORT
test_read(fd,opts, PORT_OUT); // Function read data from DO PORT
sleep(0.01);
if(value>=100) break; // Loop write data to DO PORT 100 times then read.
}
close(fd);
return 0;
}
*probe.c
static int alt_pcie_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct alt_pcie_dev *alt_dev;
struct alt_pcie_pio *alt_pio;
unsigned long minor;
int i;
int ret = 0;
alt_dev = kzalloc(sizeof(struct alt_pcie_pio), GFP_KERNEL); //ok
if (!alt_dev) {
log_err("Can't allocate memory");
return -ENOMEM;
}
mutex_init(&alt_dev->buf_lock);
spin_lock_init(&alt_dev->pci_lock);
init_waitqueue_head(&alt_dev->wait_queue);
ret = pci_enable_device(dev);
if (ret) {
log_err("Can't enable PCIe device");
goto err_pci_enable;
}
ret = pci_request_regions(dev, ALT_DRV_NAME); //ok
if (ret) {
log_err("Can't enable PCIe device");
goto err_request_region;
}
for (i = 0; i < ALT_N_PCIE_BARS; i++) {
alt_dev->bars = pci_iomap(dev, i, 0);
alt_dev->bar_size = pci_resource_len(dev, i);
if (alt_dev->bars)
}
ret = pci_enable_msi(dev);
if (ret) {
log_err("Enable MSI FAILED");
goto err_enable_msi;
}
alt_dev->irq = dev->irq;
ret = request_irq(alt_dev->irq, alt_irq_handler, IRQF_SHARED, ALT_DRV_NAME, alt_dev);
if (ret) {
log_err("Request irq failed");
goto err_request_irq;
}
alt_dev->cra_bar_no = cra_bar_no;
alt_dev->cra_base_addr = cra_base_addr;
alt_dev->cra_regs.status = (void __iomem *) (alt_dev->bars[alt_dev->cra_bar_no] +
alt_dev->cra_base_addr +
ALT_CRA_REG_STATUS);
alt_dev->cra_regs.ctrl = (void __iomem *) (alt_dev->bars[alt_dev->cra_bar_no] +
alt_dev->cra_base_addr +
ALT_CRA_REG_CTRL);
alt_dev->cra_regs.trans = (void __iomem *) (alt_dev->bars[alt_dev->cra_bar_no] +
alt_dev->cra_base_addr +
ALT_CRA_REG_TRANS);
iowrite32(0xFFFFUL, alt_dev->cra_regs.ctrl);
ret = pci_write_config_byte(dev, PCI_INTERRUPT_LINE, alt_dev->irq);
if (ret) {
goto err_write_config;
}
/* Init PIO */
alt_pio = (struct alt_pcie_pio *) alt_dev;
alt_pio->n_di_ports = sizeof(di_ports)/sizeof(struct alt_pio_port);
alt_pio->n_do_ports = sizeof(do_ports)/sizeof(struct alt_pio_port);
for (i = 0; i < alt_pio->n_di_ports; i++) {
alt_pio->di_ports = di_ports;
alt_pio->di_ports.regs = alt_dev->bars[ALT_DIO_BAR_NO] +
alt_pio->di_ports.base_addr;
}
for (i = 0; i < alt_pio->n_do_ports; i++) {
alt_pio->do_ports = do_ports;
alt_pio->do_ports.regs = alt_dev->bars[ALT_DIO_BAR_NO] +alt_pio->do_ports.base_addr;
}
INIT_LIST_HEAD(&alt_dev->device_entry);
mutex_lock(&device_list_lock);
minor = find_first_zero_bit(minors, ALT_N_PCIE_MINORS);
if (minor < ALT_N_PCIE_MINORS) {
struct device *dev;
alt_dev->devt = MKDEV(major, minor);
dev = device_create(alt_class, NULL, alt_dev->devt,
alt_dev, "alt_pcie_dev%lu", minor);
if (IS_ERR(dev)) {
log_err("Create device alt_pcie_dev%lu failed", minor);
ret = PTR_ERR(dev);
}
else {
set_bit(minor, minors);
list_add(&alt_dev->device_entry, &device_list);
}
}
else {
log_err("no minor number available");
ret = -ENODEV;
}
mutex_unlock(&device_list_lock);
if (!ret)
pci_set_drvdata(dev, alt_dev);
else {
free_irq(alt_dev->irq, alt_dev);
pci_disable_msi(dev);
for (i = 0; i < ALT_N_PCIE_BARS; i++)
pci_iounmap(dev, alt_dev->bars);
pci_release_regions(dev);
pci_disable_device(dev);
kfree(alt_dev);
}
return ret;
err_write_config:
free_irq(alt_dev->irq, alt_dev);
err_request_irq:
pci_disable_msi(dev);
err_enable_msi:
for (i = 0; i < ALT_N_PCIE_BARS; i++)
[I] pci_iounmap(dev, alt_dev->bars);
pci_release_regions(dev);
err_request_region:
pci_disable_device(dev);
err_pci_enable:
kfree(alt_dev);
return ret;
}
I have worked with DE2i-150 Development Kit for 2 weeks. Now, I'm writing simple Kernel driver for Intel Antom Processor to Read/Write GPIO from FPGA. When I develop driver, I'm having some trouble with my PCI driver.
My driver works something wrong when I reboot DE2i-150 Development kit. It only works well when I "Power off" and " Power on" again.You can see my result below to more clear my problem.
I created my driver with name "altera.ko" end then insert module to the Linux kernel use : insmod altera.ko. I wrote small app to write data to DO PORT and then read data from DO PORT and DI PORT. The sumaries program I attached file with name "app.c"
*Case right: The result when I " Power off" and " Power on" again. I do it again alot of time, and everytime the result well:
[VRD] 542 value write : 0x63 // Value is wrote in DO port
[VRD] 168 test_write : Data write to DO PORT : 0x63
[VRD] 181 test_read_do : Data read from DO PORT: 0x63
[VRD] 210 test_read _di : Data read from DI PORT: 0xffffffff
*Case wrong: The result when I reboot DE2i-150 the first time:
[VRD] 542 value write : 0x63 // Value is wrote in DO port
[VRD] 168 test_write : Data write to DO PORT : 0x63
[VRD] 181 test_read_do : Data read from DO PORT: 0xffffffff
[VRD] 210 test_read _di : Data read from DI PORT: 0x63
=> it seems read inverse value between DI PORT and DO PORT.
But the value right back when I reboot the second times
[VRD] 542 value write : 0x63 // Value is wrote in DO port
[VRD] 168 test_write : Data write to DO PORT : 0x63
[VRD] 181 test_read_do : Data read from DO PORT: 0x63
[VRD] 210 test_read _di : Data read from DI PORT: 0xffffffff
And it get wrong result again when I reboot the third times. End then value right back when I reboot at fourth times. ....I do it again alot of time. I see every once read right value, next once wrong value, .... I hope you can understand my case
I don't understand alot my problem. Maybe it come from "map bar address". But I see I can read right value when I power off and power on again DE2i-150 kit, so I think it ok. I also attached "probe method" code in file "probe.c", can you help me to check it.
I developed my driver in Debian 8: "Linux debian 3.16.0-4-686-pae GNU/Linux".
Can anybody help me to know where is my problem. I hope can read right value every time either "reboot" or "power off".
Thank your for your attention. Thank you very much.
Best & Regard
Bắc
Sorry I can't attached file app.c and probe.c so I write all here, Sorry it's very too long:
* app.c
int main (int argc, char *argv[])
{
int fd;
struct app_opts opts;
long value=0;
opts.di_addr = 0x0020;
opts.do_addr = 0x0000;
opts.dio_bar_no = ALT_DIO_BAR_NO;
opts.rw_bar_no = 0x00;
opts.port_no = 0;
parse_opt(argc, argv, &opts);
fd = open(device, O_RDWR);
if (fd < 0) {
log_err("Open device failed");
return -ENODEV;
}
while(1)
{
value++;
log_info("value: %lu", value);
opts.port_data = value;
test_write(fd, opts); // Function write data to DO PORT
test_read(fd,opts, PORT_IN); // Function read data from DI PORT
test_read(fd,opts, PORT_OUT); // Function read data from DO PORT
sleep(0.01);
if(value>=100) break; // Loop write data to DO PORT 100 times then read.
}
close(fd);
return 0;
}
*probe.c
static int alt_pcie_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct alt_pcie_dev *alt_dev;
struct alt_pcie_pio *alt_pio;
unsigned long minor;
int i;
int ret = 0;
alt_dev = kzalloc(sizeof(struct alt_pcie_pio), GFP_KERNEL); //ok
if (!alt_dev) {
log_err("Can't allocate memory");
return -ENOMEM;
}
mutex_init(&alt_dev->buf_lock);
spin_lock_init(&alt_dev->pci_lock);
init_waitqueue_head(&alt_dev->wait_queue);
ret = pci_enable_device(dev);
if (ret) {
log_err("Can't enable PCIe device");
goto err_pci_enable;
}
ret = pci_request_regions(dev, ALT_DRV_NAME); //ok
if (ret) {
log_err("Can't enable PCIe device");
goto err_request_region;
}
for (i = 0; i < ALT_N_PCIE_BARS; i++) {
alt_dev->bars = pci_iomap(dev, i, 0);
alt_dev->bar_size = pci_resource_len(dev, i);
if (alt_dev->bars)
}
ret = pci_enable_msi(dev);
if (ret) {
log_err("Enable MSI FAILED");
goto err_enable_msi;
}
alt_dev->irq = dev->irq;
ret = request_irq(alt_dev->irq, alt_irq_handler, IRQF_SHARED, ALT_DRV_NAME, alt_dev);
if (ret) {
log_err("Request irq failed");
goto err_request_irq;
}
alt_dev->cra_bar_no = cra_bar_no;
alt_dev->cra_base_addr = cra_base_addr;
alt_dev->cra_regs.status = (void __iomem *) (alt_dev->bars[alt_dev->cra_bar_no] +
alt_dev->cra_base_addr +
ALT_CRA_REG_STATUS);
alt_dev->cra_regs.ctrl = (void __iomem *) (alt_dev->bars[alt_dev->cra_bar_no] +
alt_dev->cra_base_addr +
ALT_CRA_REG_CTRL);
alt_dev->cra_regs.trans = (void __iomem *) (alt_dev->bars[alt_dev->cra_bar_no] +
alt_dev->cra_base_addr +
ALT_CRA_REG_TRANS);
iowrite32(0xFFFFUL, alt_dev->cra_regs.ctrl);
ret = pci_write_config_byte(dev, PCI_INTERRUPT_LINE, alt_dev->irq);
if (ret) {
goto err_write_config;
}
/* Init PIO */
alt_pio = (struct alt_pcie_pio *) alt_dev;
alt_pio->n_di_ports = sizeof(di_ports)/sizeof(struct alt_pio_port);
alt_pio->n_do_ports = sizeof(do_ports)/sizeof(struct alt_pio_port);
for (i = 0; i < alt_pio->n_di_ports; i++) {
alt_pio->di_ports = di_ports;
alt_pio->di_ports.regs = alt_dev->bars[ALT_DIO_BAR_NO] +
alt_pio->di_ports.base_addr;
}
for (i = 0; i < alt_pio->n_do_ports; i++) {
alt_pio->do_ports = do_ports;
alt_pio->do_ports.regs = alt_dev->bars[ALT_DIO_BAR_NO] +alt_pio->do_ports.base_addr;
}
INIT_LIST_HEAD(&alt_dev->device_entry);
mutex_lock(&device_list_lock);
minor = find_first_zero_bit(minors, ALT_N_PCIE_MINORS);
if (minor < ALT_N_PCIE_MINORS) {
struct device *dev;
alt_dev->devt = MKDEV(major, minor);
dev = device_create(alt_class, NULL, alt_dev->devt,
alt_dev, "alt_pcie_dev%lu", minor);
if (IS_ERR(dev)) {
log_err("Create device alt_pcie_dev%lu failed", minor);
ret = PTR_ERR(dev);
}
else {
set_bit(minor, minors);
list_add(&alt_dev->device_entry, &device_list);
}
}
else {
log_err("no minor number available");
ret = -ENODEV;
}
mutex_unlock(&device_list_lock);
if (!ret)
pci_set_drvdata(dev, alt_dev);
else {
free_irq(alt_dev->irq, alt_dev);
pci_disable_msi(dev);
for (i = 0; i < ALT_N_PCIE_BARS; i++)
pci_iounmap(dev, alt_dev->bars);
pci_release_regions(dev);
pci_disable_device(dev);
kfree(alt_dev);
}
return ret;
err_write_config:
free_irq(alt_dev->irq, alt_dev);
err_request_irq:
pci_disable_msi(dev);
err_enable_msi:
for (i = 0; i < ALT_N_PCIE_BARS; i++)
[I] pci_iounmap(dev, alt_dev->bars);
pci_release_regions(dev);
err_request_region:
pci_disable_device(dev);
err_pci_enable:
kfree(alt_dev);
return ret;
}