Skip to content
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

Introduce AD7124 ADC #84197

Merged
merged 4 commits into from
Jan 30, 2025
Merged

Conversation

yasinustunerg
Copy link
Collaborator

This PR introduces AD7124 Analog to Digital Converter:

See AD7124-4 for detailed information.
See AD7124-8 for detailed information.

@yasinustunerg yasinustunerg marked this pull request as ready for review January 19, 2025 11:23
@zephyrbot zephyrbot added area: ADC Analog-to-Digital Converter (ADC) platform: ADI Analog Devices, Inc. labels Jan 19, 2025
@MaureenHelm MaureenHelm added this to the v4.1.0 milestone Jan 20, 2025
MaureenHelm
MaureenHelm previously approved these changes Jan 20, 2025
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
drivers/adc/adc_ad7124.c Outdated Show resolved Hide resolved
ttmut
ttmut previously approved these changes Jan 23, 2025
@yasinustunerg
Copy link
Collaborator Author

Hi @MaureenHelm, could you review again?

MaureenHelm
MaureenHelm previously approved these changes Jan 23, 2025
@yasinustunerg
Copy link
Collaborator Author

Hi @anangl , could you review the PR?

@yasinustunerg
Copy link
Collaborator Author

Hi @anangl , this PR is waiting for your review.


struct spi_buf tx_buf[] = {{
.buf = buffer_tx,
.len = ((data->crc_enable == AD7124_ENABLE_CRC) ? len + 1 : len) + 1 +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point in defining AD7124_*_CRC symbols and comparing crc_enable against them? It's a bool, so why not just use (data->crc_enable ? len + 1 : len) here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 560 to 552
for (int i = 1; i < len + 2 + add_status_length; i++) {
crc_buffer[i] = buffer_rx[i];
}
crc_check = crc8(crc_buffer, len + 2 + add_status_length,
AD7124_CRC8_POLYNOMIAL_REPRESENTATION, 0, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need to copy this buffer just to calculate CRC for it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unnecessary copy.

const struct spi_buf_set tx = {.buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)};
const struct spi_buf_set rx = {.buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)};

buffer_tx[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD | AD7124_COMM_REG_RA(reg);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this first byte all that actually needs to be transmitted (and the rest will be ignored anyway)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

const struct spi_buf_set tx = {.buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)};
const struct spi_buf_set rx = {.buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)};

ret = spi_transceive_dt(spec, &tx, &rx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of the RX buffer set here, when this is a write register transaction?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


struct ad7124_channel_config {
struct ad7124_config_props props;
uint32_t cfg_slot;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint32_t to store the slot index, when there are 8 slots?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed with uint8_t

int ret;

data->dev = dev;
data->spi_ready.spi_rdy_poll_cnt = AD7124_SPI_RDY_POLL_CNT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point in storing this value in driver data if it is not modified afterwards?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded added to the functions, removed from initialization

Comment on lines 1228 to 1207
num_active_channels = POPCOUNT(data->channels);
necessary = num_active_channels * sizeof(int32_t);

if (sequence->options) {
necessary *= (1 + sequence->options->extra_samplings);
}

if (sequence->buffer_size < necessary) {
LOG_ERR("buffer size %u is too small, need %u", sequence->buffer_size, necessary);
return -ENOMEM;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data->channels is the bitmask of configured channels and this code is supposed to check if the provided buffer is large enough for the sequence, which does not need to use all the configured channels. sequence->channels should be used instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AD7124 is using one channel to read all channels respectively so I was reading all the configured channels when reading command called. I changed the algorithm so currrently only the requested sequence->channels datas will be read like you said.

const struct spi_buf_set tx = {.buffers = tx_buf, .count = ARRAY_SIZE(tx_buf)};
const struct spi_buf_set rx = {.buffers = rx_buf, .count = ARRAY_SIZE(rx_buf)};

ret = spi_transceive_dt(spec, &tx, &rx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RX buffer set does not seem to be needed here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

anangl
anangl previously approved these changes Jan 30, 2025

k_sem_take(&data->acquire_signal, K_FOREVER);

uint16_t requested_channels = data->requested_channels;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use data->ctx.sequence.channels instead of adding requested_channels to struct adc_ad7124_data.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

static bool get_next_ch_idx(uint16_t ch_mask, uint16_t last_idx, uint16_t *new_idx)
{
last_idx++;
if (last_idx >= 16) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 16 is AD7124_MAX_CHANNELS, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +1163 to +1164
if (ch_idx == adc_ch_id) {
data->buffer++;
} else {
ch_idx = prev_ch_idx;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it needed to always read all the configured channels and then writing to the buffer only those selected for a given sequence, using this filtering? Wouldn't it make sense to only enable the channels required for the requested sequence when it is started?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried what you said. I disabled when the read command called and enabled only the selectes ones. However, via this method, Ad7124 is working inconsistently and stop at some point because AD7124 is resetting the all setup when some configurations changed. So when you enabled and disabled continously at every reading command, system stuck at some point. The second reason is that, Ad7124 have 16 channels so disabling and enabling is increasing the latency.

As a solution, I am just reading only the selected ones.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link is exactly what I tried.

This commit introduces ad7124 adc driver.

Signed-off-by: Yasin Ustuner <[email protected]>
This commit adds ad7124 binding.

Signed-off-by: Yasin Ustuner <[email protected]>
This commit adds analog inputs for AD7124 ADC.

Signed-off-by: Yasin Ustuner <[email protected]>
This commit adds build-only test of ad7124 spi based
adc.

Signed-off-by: Yasin Ustuner <[email protected]>
@kartben kartben merged commit 45f50f8 into zephyrproject-rtos:main Jan 30, 2025
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ADC Analog-to-Digital Converter (ADC) platform: ADI Analog Devices, Inc.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants