Hi all,

A month or so back I added ADC peripherals bindings for the MicroPython
fork. As this had to be generic across boards I also stumbled over a
missing run-time indicator for which resolutions are supported. At that
moment I worked around it by iterating over all possible ADC resolutions
until a supported resolution was tried. Of course this is a bit suboptimal.

I'm very much in favor of some way to determine the available
resolutions and min/max resolutions of an ADC. I was thinking of a
function such as `adc_res_t adc_res_max(adc_line_t line)` to be able to
support different ADC peripherals on a single image.

Just my 2 cents on this issue. I'm already glad that this is tackled.

Cheers,
Koen

On 08/01/2020 14.30, Hauke Petersen wrote:
> Hi Marian,
>
> I agree that users are unlikely to produce that garbage when passing
> value to the `adc_sample` function directly. More likely those kind of
> values are produced in cases where values are deducted
> programmatically via (potentially broken) code, or from broken
> indirect configuration (nested defines...). The main point is simply
> that the compiler does not catch this and we need to handle it somehow
> -> which we agree upon as it seems :-)
>
>  So +1 in documenting the preconditions correctly, checking the `line`
> and `res` values using assertions and not returning any specific code.
> How about we change the API doc to something `@return <0 for any
> internal error` or similar, to still allow certain peripherals to
> signal an error and mark the result invalid.
>
> While touching this API, would it make sense to also change the return
> type from `int` to `int32_t`? This would allow for 16-bit ADCs on 16-
> and 8-bit platforms... Just thinking loud here :-)
>
> Cheers (and thanks for tackling this!),
> Hauke
>
> On 1/7/20 10:09 AM, Marian Buschsieweke wrote:
>> Hi,
>>
>> thanks for your reply.
>>
>> On Tue, 7 Jan 2020 09:00:54 +0100
>> Hauke Petersen <hauke.peter...@fu-berlin.de> wrote:
>>
>>> Hi,
>>>
>>> keep in mind that just because an enum value is not defined, it does not 
>>> prevent code like
>>> ```
>>> adc_res_t res = 77;
>>> adc_init(.., res);
>>> ```
>>> Also, calling `adc_init(..., 1234)` is completely fine for the compiler...
>> To me, this is a text book example of garbage in, garbage out. I personally
>> don't expect someone to use random numbers out of the head of their mind
>> instead of the enum constants and expecting things to just somehow magically
>> work.
>>
>> How about we add a precondition statement to the API documentation that only
>> values provided via enum constants are valid input for the resolution?
>>
>> But if we cannot assume a minimum level of common sense being applied to the
>> users source code, why not at least use assert()? This way at least 
>> production
>> code doesn't have to pay the overhead of checking for completely insane bugs.
>>
>> (Don't get me wrong: I personally very much in favor of doing proper error
>> handling even at the expense of some overhead. But adding overhead to check 
>> for
>> completely crazy stuff seams not to be a good trade off to me.)
>>
>>> Hence the two fold approach in the current implementations: each CPU 
>>> should define only the ADC_RES_X values it actually supports and on top 
>>> adc_sample() *should* return -1 on unsupported values to catch mishaps 
>>> as stated above.
>> Sadly, neither is it (consistently) implemented like this nor documented this
>> way. But if there is an agreement that only the enum constants actually
>> supported should be defined, I can open a PR to document this. But let's keep
>> the discussion on how to handle it if users call adc_sample() with a 
>> resolution
>> not provided by the enum going for while.
>>
>> While I'm at it: How should adc_sample() behave if the line parameter is out 
>> of
>> range? This is something that can easily happen, e.g. when compiling code
>> written for one board for a different board. Again: I would say a 
>> precondition
>> added to the doc and an assert() would be this best solution here.
>>
>> I'd also like to add that the API is not safe to be called from IRQ context, 
>> as
>> (at least some) implementations use a mutex to serialize access to the ADC.
>>
>> (Btw: If we would replace the `ADC_LINE()` macro by a `static inline adc_t
>> adc_line(unsinged num)` function, we could use `_Static_assert()` to generate
>> compile time errors there as well. For backward compatibility an macro
>> ADC_LINE() calling that function could be provided.)
>>
>>> But I do like the idea of adding defines like `HAVE_ADC_RES_X` and 
>>> `_MAX` (and `_MIN`).
>>>
>> I'll open a PR for that. (I will also add the minimum resolution in that.)
>>
>> Kind regards,
>> Marian
>>
>>> Cheers,
>>> Hauke
>>>
>>> On 12/26/19 10:01 AM, Marian Buschsieweke wrote:
>>>> Hi,
>>>>
>>>> I just noticed that most of the ADC implementations providing their own
>>>> adc_res_t do not cover all values. The API documentation states that
>>>> adc_sample() should return -1 on unsupported resolutions. This indicates 
>>>> that
>>>> all possible resolutions have to be defined in any case, so that a user 
>>>> could
>>>> check at run time which resolutions are provided.
>>>>
>>>> However: Wouldn't it make more sense to only provide the enum values 
>>>> actually
>>>> supported? This would have two advantages:
>>>>
>>>> 1. Currently all places where adc_res_t is provided need to be updated 
>>>> when new
>>>>     resolutions are added, resulting in some maintenance effort
>>>> 2. Only having the resolutions defined that are actually supported would 
>>>> result
>>>>     in compile time errors, which are much easier to spot and debug than 
>>>> run time
>>>>     errors
>>>>
>>>> Additionally, use cases where users needed to determine available 
>>>> resolutions
>>>> could be address by e.g. defining HAVE_ADC_RES_10BIT when ADC_RES_10BIT is
>>>> supported. And ADC_RES_MAX could be provided for the highest resolution 
>>>> enum
>>>> and ADC_RES_MAX_BITS for the number of bits this has. This would allow to
>>>> determine the resolution at compile time, resulting in less overhead in 
>>>> terms
>>>> of both runtime and memory.
>>>>
>>>> But: As currently the approach to detect available resolutions would 
>>>> result in
>>>> compile time errors (when testing for resolutions not covered in the enum),
>>>> maybe nobody actually needs this?
>>>>
>>>> Kind regards,
>>>> Marian
>>>>
>>>> _______________________________________________
>>>> devel mailing list
>>>> devel@riot-os.org
>>>> https://lists.riot-os.org/mailman/listinfo/devel  
>>> _______________________________________________
>>> devel mailing list
>>> devel@riot-os.org
>>> https://lists.riot-os.org/mailman/listinfo/devel
>>
>> _______________________________________________
>> devel mailing list
>> devel@riot-os.org
>> https://lists.riot-os.org/mailman/listinfo/devel
>
>
> _______________________________________________
> devel mailing list
> devel@riot-os.org
> https://lists.riot-os.org/mailman/listinfo/devel

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
devel mailing list
devel@riot-os.org
https://lists.riot-os.org/mailman/listinfo/devel

Reply via email to