Hello to all,
I am learning how to use rtdm_timer and also rtdm_event to use on acquisition
board. The board itself has a FIFO and can be configurated do fill it in a
predefined time. The problem is that there is no interrupt generated when the
FIFO is full or on a given number of samples, so I have to poll the data.
As the conversion time is know (based on board latency, conversion time and
number os channels to scan), a better approach would be let the board do its
conversion and at given times, where the data should be ready on FIFO (and
also, the FIFO is far large than the amount of data retrieved) and then, get
it, setup a new delay based on the estimated remaining data for the next scan,
fire an event to unblock an read operation and loop the entire proccess
again...
Also, there is an user space real time application that will open the rtdm
device, issue some configurations via ioctl and loop reading the device.
The code specific to timming is working almost as good, I can see the app
returning a increasing counter by the time it is running. The only issue is
that the CPU hangs if I try to remove the module or run the app one second
time (or if I close and then reopen the device)
Any call to configure the rtdm_event will hang the CPU.
Hope you can give some appointments or tell me what I am doing wrong.
Here is the relevant sections of code, only code specific to xenomai and
related with the issues.
--- For the app
int main(int argc, char **argv)
{
int device;
int ret;
int32_t sample_number;
ret = mlockall(MCL_CURRENT | MCL_FUTURE);...
ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);...
sample_number = 0;
//Open
device = rt_dev_open(DEVICE_NAME, 0);....
// IOCTL Start
ret = rt_dev_ioctl(device, 0x07);...
sleep(3);
// Read
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
sleep(3);
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
sleep(3);
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
sleep(2);
ret = rt_dev_read (device, &sample_number, sizeof(sample_number));
printf("Read %d. Sample %d\n", ret, sample_number);
// IOCTL Stop
ret = ioctl(device, 0x08);...
/* close the device */
ret = rt_dev_close(device);...
return 0;
}
---
--- For the Driver
...
static struct rtdm_device RtdmDevice = {
.struct_version = RTDM_DEVICE_STRUCT_VER,
.device_flags = RTDM_NAMED_DEVICE,
.context_size = 0,
.device_name = DEVICE_NAME,
.open_nrt = pci18xx_rtdm_open,
.open_rt = pci18xx_rtdm_open,
.ops = {
.close_nrt = pci18xx_rtdm_close,
.close_rt = pci18xx_rtdm_close,
.read_rt = pci18xx_rtdm_read_rt,
.read_nrt = pci18xx_rtdm_read_rt,
.write_rt = pci18xx_rtdm_write_rt,
.ioctl_rt = pci18xx_rtdm_ioctl_nrt,
.ioctl_nrt = pci18xx_rtdm_ioctl_nrt,
},
.device_class = RTDM_CLASS_EXPERIMENTAL,
.device_sub_class = SOME_SUB_CLASS,
.profile_version = 1,
.driver_name = DRIVER_NAME,
.driver_version = RTDM_DRIVER_VER(0, 1, 2),
.peripheral_name = "Icpdas Daq18xx Board",
.provider_name = "Carlos Novaes",
.proc_name = RtdmDevice.device_name,
.device_id = -1,
};...
...
static int pci18xx_rtdm_ioctl_nrt(struct rtdm_dev_context
*context, rtdm_user_info_t *user_info, unsigned int request, void __user *arg)
{
pci18xx_context_t *ctx;
int err;
err = 0;
rtdm_printk("IOCTL Device NRT. Request = %d\n", request);
ctx = (pci18xx_context_t *)context->dev_private;
switch (request){
case IOCTL_START:
err = pci18xx_start(context, ctx, user_info, arg);
break;
case IOCTL_STOP:
err = pci18xx_stop(ctx, user_info, arg);
break;
default:
return PCI18XX_E_INVALID_IOCTL;
}
return PCI18XX_OK;
};...
...
static ssize_t pci18xx_rtdm_read_rt(struct rtdm_dev_context *context,
rtdm_user_info_t * user_info, void *buf, size_t nbyte){
int16_t size;
int32_t value;
int err;
pci18xx_context_t *ctx;
// following line fails
//err = rtdm_event_timedwait(&ctx->RtdmReadyEvent,2000000000, NULL);
ctx = (pci18xx_context_t *) context->dev_private;
size=sizeof(ctx->SampleNumber);
if (rtdm_safe_copy_to_user(user_info, buf, &(ctx->SampleNumber), size)){...
return size;
};...
...
static int pci18xx_start(struct rtdm_dev_context *context,
pci18xx_context_t *ctx, rtdm_user_info_t *user_info, void __user *arg){
rtdm_timer_init(&ctx->RtdmTimer, pci18xx_timer_proc, context->device-
>device_name);
// following line fail
//rtdm_event_init(&ctx->RtdmReadyEvent, 0);
ctx->Running=1;
ctx->SampleNumber=0;
ctx->time = rtdm_clock_read_monotonic();
ctx->time += 1000000000;
rtdm_timer_start(&ctx->RtdmTimer, ctx->time, 0, RTDM_TIMERMODE_ABSOLUTE);
return 0;
};
static int pci18xx_stop(pci18xx_context_t *ctx, rtdm_user_info_t
*user_info, void __user *arg){
rtdm_printk("stop function\n");
if (ctx->Running){
ctx->Running=0;
// following line fail
//rtdm_event_destroy(&ctx->RtdmReadyEvent);
rtdm_timer_destroy(&ctx->RtdmTimer);
}
return 0;
};
static void pci18xx_timer_proc(rtdm_timer_t *timer){
pci18xx_context_t *ctx;
int err;
ctx = container_of(timer, pci18xx_context_t, RtdmTimer);
ctx->SampleNumber++;
ctx->time += 1000000000;
err = rtdm_timer_start_in_handler(&ctx->RtdmTimer, ctx->time, 0,
RTDM_TIMERMODE_ABSOLUTE);
// following line fail
//rtdm_event_pulse(&ctx->RtdmReadyEvent);
};
---
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help