-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ad796x: Add project and driver for ad796x-fmc #2139
Conversation
b24a10b
to
0a3d1da
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some remarks from my side, also:
please create a different commit for the driver and in the same commit please also add the driver documentation
please use the new project structure
0a3d1da
to
cfff8a0
Compare
ok ill separate driver and project. but |
By new project structure I mean the src folder should have platform independent examples, with common folder and platform specific folders. This is an example from iio_demo project:
|
Ok, i did not know this structure was a requirement, will do. |
one question @rbolboac i would suppose the structure requirement is to keep the examples platform i see things like axi_dac_init_begin(&phy->tx_dac, &tx_dac_init); are there some rules as to what goes into platform/common/example? |
well, the idea is to have the examples generic and platform independent, but if that is not possible I suppose it is alright. |
576859c
to
2bb46dc
Compare
The failure of CI is currently due to the missing HDL:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some remarks from my side
drivers/adc/ad796x/ad796x.c
Outdated
uint16_t samples) | ||
{ | ||
int ret; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blank line can be removed, no reason to leave blank lines between declarations. see everywhere where it applies
drivers/adc/ad796x/ad796x.c
Outdated
dev->gpio_adc_en0_fmc, | ||
}; | ||
|
||
for (i = 0; i < 4; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create a macro value for that magic value
drivers/adc/ad796x/ad796x.c
Outdated
ret = axi_clkgen_set_rate(dev->clkgen, 125000000); | ||
if (ret) { | ||
pr_err("error: axi_clkgen_set_rate error: %d\n", ret); | ||
goto err_set_rate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for an extra label, can use err_clkgen
drivers/adc/ad796x/ad796x.c
Outdated
err_dmac: | ||
axi_adc_remove(dev->ad796x_core); | ||
err_adc: | ||
no_os_pwm_remove(dev->axi_pwm_1); | ||
err_pwm_1: | ||
no_os_pwm_remove(dev->axi_pwm_0); | ||
err_pwm_0: | ||
err_set_rate: | ||
axi_clkgen_remove(dev->clkgen); | ||
err_clkgen: | ||
ad796x_gpio_remove(dev); | ||
error_gpio: | ||
no_os_free(dev); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is safe to have a single error label (but please check before).
basically, if the init function has not been called, the desc will be null and the remove functions should check whether the desc is null or not. if it is null nothing will happen, if it is not null it will be freed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that just means that the convention is that if the desc returns something that
something has to be freed (even if the int func fails).
i guess i can add those checks in remove and just call remove then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well... the convention is that if something is allocated and ret is not 0, it should be freed before returning.
However, seeing how we use calloc, all pointers are initialized with null, so if we call the remove function, even if memory has not been allocated, then the remove function should check for null and free the memory only if the pointer is not null.
Assuming that all remove functions check for null pointer before attempting to free it, it is safe to call the remove function even if the init has not been called. This will make the code easier to follow and shorter (a single label can be used).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RE: if something is allocated and ret is not 0, it should be freed before returning
What i see from the no os-code is a bit confusing:
axi_dmac does not free before returning -1
(https://github.com/analogdevicesinc/no-OS/blob/main/drivers/axi_core/axi_dmac/axi_dmac.c#L349)
axi_adc_core frees the allocation before returning -1 But the the pointer is not checked for null in remove.
https://github.com/analogdevicesinc/no-OS/blob/main/drivers/axi_core/axi_adc_core/axi_adc_core.c#L677
So in case one of the int function call fails, im not sure we can trust the pointer to be freed, or
to be freed and null.
ill assume those are separate issues and make the change anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
regarding https://github.com/analogdevicesinc/no-OS/blob/main/drivers/axi_core/axi_dmac/axi_dmac.c#L349, it looks like the remove function should be called if ret is not 0. so the suggestion works great in this case. I do not know why this implementation was done like that. personally I would rework it into something like:
struct axi_dmac *dmac;
dmac = (struct axi_dmac *)no_os_calloc(1, sizeof(*dmac));
if (!dmac)
return -1;
dmac->name = init->name;
dmac->base = init->base;
dmac->irq_option = init->irq_option;
int32_t status = axi_dmac_detect_caps(dmac);
if (status < 0)
goto free;
*dmac_core = dmac;
return 0;
free:
no_os_free(dmac);
return -1;
regarding https://github.com/analogdevicesinc/no-OS/blob/main/drivers/axi_core/axi_adc_core/axi_adc_core.c#L677,
the descriptor remains null in case of an error, only in case of success the descriptor is set: https://github.com/analogdevicesinc/no-OS/blob/main/drivers/axi_core/axi_adc_core/axi_adc_core.c#L673
so basically, dev->ad796x_core will be null if init is not successful, and when calling the remove function nothing will happen.
the problem I see is that axi_adc_remove does not check for null pointer, we should add that check I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, ok. with those changes.
BTW i have done it this way because the logic i was following was
to keep balanced number of init/remove.
this would mean that:
- init will free its resources in case of fail, a failed init is not a init (like you mention)
- remove should not be called if init was not called before
- remove should not be called for a failed init
- should not assume the state of the pointer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand... this is not mandatory. in my case the code would look cleaner...
also, to me there is no real value in adding a duplicate label: err_pwm_0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, regarding my previous comment the problem I see is that axi_adc_remove does not check for null pointer, we should add that check I think.
there is no problem with that API, it is safe to call free for null pointers.
/******************************************************************************/ | ||
/***************************** Include Files **********************************/ | ||
/******************************************************************************/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove extra blank lines
#include <xil_cache.h> | ||
#include <xilinx_uart.h> | ||
#include "xilinx_gpio.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove extra blank line
#define UART_DEVICE_ID XPAR_AXI_UART_DEVICE_ID | ||
#define INTC_DEVICE_ID XPAR_INTC_SINGLE_DEVICE_ID | ||
#define UART_IRQ_ID XPAR_AXI_INTC_AXI_UART_INTERRUPT_INTR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use the same indentation
634a268
to
d477d84
Compare
changes:
|
drivers/adc/ad796x/ad796x.c
Outdated
{ | ||
int ret; | ||
|
||
if (dev->ad796x_core) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only thing I would check for null here is dev.
freeing a null pointer is allowed
drivers/adc/ad796x/ad796x.c
Outdated
int ret, i; | ||
|
||
struct no_os_gpio_desc *desc[] = { | ||
dev->gpio_adc_en3_fmc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dev should be checked for null before trying to access its members
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ill use a table index instead to loop though the gpios.
drivers/adc/ad796x/ad796x.c
Outdated
if (!desc[i]) | ||
continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no_os_gpio_remove already checks for null pointer, no need to do it here
4f70f6d
to
27fbc6a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor comments, otherwise lgtm
@@ -43,9 +43,10 @@ | |||
/***************************** Include Files **********************************/ | |||
/******************************************************************************/ | |||
|
|||
#include <inttypes.h> | |||
#include <stdio.h> | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop this extra line.
drivers/adc/ad796x/ad796x.c
Outdated
[AD796X_MODE1_EXT_REF_5P0] = {1, 0, 0, 1}, | ||
[AD796X_MODE2_INT_REF_4P0] = {1, 0, 0, 1}, | ||
[AD796X_MODE3_EXT_REF_4P0] = {0, 1, 0, 1}, | ||
[AD796X_MODE4_SNOOZE] = {1, 1, 0, 1}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
odd indentation: check raw file.
drivers/adc/ad796x/ad796x.c
Outdated
|
||
return ret; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop extra line
/* Read samples from the device */ | ||
int32_t ad796x_read_data(struct ad796x_dev *dev, uint32_t *buf, | ||
uint16_t samples); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop extra line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some remarks from my side, also ad796x driver documentation is missing
same remark regarding commit message length, can have up to 72 characters per line.
if (ret) | ||
goto err_app_run; | ||
|
||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove these lines...if fore some reason iio_app_run returns (either with 0 or another value), the remove APIs should call before exiting this example.
iio_axi_adc_remove(iio_axi_adc_desc); | ||
err_adc_init: | ||
ad796x_remove(adc_dev); | ||
return ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (ret) I would print an error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok ill put print in after the ret that fails were i can show who produced the error.
ret = iio_example_main(); | ||
#elif BASIC_EXAMPLE | ||
ret = basic_example_main(); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add an #error
message in case no example is defined
27fbc6a
to
3b8c8a9
Compare
do you plan on adding the driver documentation in this PR or in a new one? |
i will add it to this PR |
if inttypes.h is decared at the start of the header a compilation error might happen because __int64_t_defined is not defined causing PRIi64 to not be defined either. By moving the inttypes.h header after sdio, __int64_t_defined is defiend and we can use PRIi64. Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
Memory should be freed when returning error from init. Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
This adds the driver for the ad796x series of chips. Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
This adds the project files for ad796x. It supports iio and basic example for the xilinx platform. Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
c5408f2
to
9520c43
Compare
|
||
AD796X Device Configuration | ||
---------------------------- | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like device configuration documentation is missing...
in general, I think it will be useful to also describe the available APIs, just in case someone checks the documentation before the code... there are various examples here: http://analogdevicesinc.github.io/no-OS/drivers_doc.html
also, the commit message states that only project documentation is added, meanwhile you also add the driver documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i took the example from https://analogdevicesinc.github.io/no-OS/drivers/adm1177.html
where "driver initialization " is a subtopic of "device configuration "
in fact there is no device configuration for this driver. only driver initialization and reading data,
which i mention, but perhaps not clearly enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not clear that driver initialization is a subtopic of device configuration. they are using the same indentation. use ^^^^
, instead of ----
for driver initialization if that is the case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok , i just followed what was done in the other docs:
AD405X Device Configuration
---------------------------
Driver Initialization
---------------------
In order to be able to use the device, you will have to provide the support for
the communication protocol (SPI) as well as 3 external GPIOs for the CNV pin and two
ADM1177 Device Configuration
----------------------------
Driver Initialization
---------------------
In order to be able to use the device, you will have to provide the support for
the communication protocol (I2C) as mentioned above.
The first API to be called is **adm1177_init**. Make sure that it returns 0,
which means that the driver was initialized correctly.
This adds project documentation for ad796x. Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
9520c43
to
176b39a
Compare
This adds driver files and a project test the ad796x series of pulsar Differential ADC.
The HDL for this project is still not merged, and probably its why CI is failing.
perhaps review can start without the HDL
this was tested using the HDL binary at https://github.com/adi-ses/sea-misc/tree/main/AD796x-PRJ
PR Type
PR Checklist