Ashwin
Ashwin

Reputation: 431

Loss of precision (assignment)

I am getting below warning for my code (some part of my code):

# define MN2DIV                    0x14                     
# define PLL_BASE_ADDRESS          0x481C5000                
# define ISS_PLL_BASE              (PLL_BASE_ADDRESS+0x140)                  
# define    M_PLL                 (volatile Uint32*)(ISS_PLL_BASE+MN2DIV)           

uint16 getfreqmhz(void)
{          
    uint16 M;          
    M= *M_PLL;           
} 

I tried by casting like : M= (uint16)*M_PLL ;
Cause of above changes the warning 734 got removed ,But I think this is not correct idea.

Can somebody tell me the correct way for doing this ....

Upvotes: 0

Views: 2947

Answers (2)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385274

The key here is that you are interfacing with hardware for which you (presumably) have exacting specifications.

If MISRA is a general-purpose static analyser, it won't be cognisant of the unique guarantees in your microcontroller environment. You're doing things that C++ doesn't like very much as a standard, because they don't make sense on (say) a PC. But, with sufficient information about the hardware and its interface, your code can be perfectly safe in practice; if so, you may ignore/suppress these diagnostics.

  • The note is telling you about your (volatile Uint32*)(ISS_PLL_BASE+MN2DIV) (inside the macro), where you form a pointer from an integer.

    In any arbitrary C++ program I would agree with MISRA and say that this is bad form, but since you're specifying actual PLL locations that you know, it seems fine to me. I do it myself.

    So, you can safely ignore the note.

  • The "info" is self-explanatory: the macro suggests that you treat each register location as a 32-bit word, but then you're trying to cram that value into 16 bits.

    Some possibilities:

    • this is wrong and each register is actually 16 bits;
    • getfreqmhz should return a uint32; or
    • or you know for sure what you're doing is valid based on some knowledge of the value range, and then your cast approach is fine.

Upvotes: 2

Shahbaz
Shahbaz

Reputation: 47563

You are reading a 32-bit value from PLL and storing it in a 16-bit variable. There are two cases:

  1. You know for sure that the highest 16 bits of the value read from PLL are 0. In this case, ignore the warning (or remove it with a cast if you want), because the higher order 0s which you are not interested in are automatically dropped.
  2. You are interested in the whole 32 bits of the value read from PLL. In that case, M should be uint32 to be able to contain all of that data.

The first warning about cast from integer to pointer is for hosted code where casting integers to pointers is meaningless. In the microcontroller world, this is instead very meaningful when you are trying to access peripheral registers mapped to fixed addresses. Since you are on a microcontroller as it seems, ignore that warning.

Upvotes: 1

Related Questions