Handling bugs, quirks, or annoyances in vendor-supplied headers
Posted
by
supercat
on Programmers
See other posts from Programmers
or by supercat
Published on 2012-10-05T23:31:30Z
Indexed on
2012/10/06
3:49 UTC
Read the original article
Hit count: 276
If the header file supplied by a vendor of something with whom one's code must interact is deficient in some way, in what cases is it better to:
- Work around the header's deficiencies in the main code
- Copy the header file to the local project and fix it
- Fix the header file in the spot where it's stored as a vendor-supplied tool
- Fix the header file in the central spot, but also make a local copy and try to always have the two match
- Do something else
As an example, the header file supplied by ST Micro for the STM320LF series contains the lines:
typedef struct
{
__IO uint32_t MODER;
__IO uint16_t OTYPER;
uint16_t RESERVED0;
....
__IO uint16_t BSRRL; /* BSRR register is split to 2 * 16-bit fields BSRRL */
__IO uint16_t BSRRH; /* BSRR register is split to 2 * 16-bit fields BSRRH */
....
} GPIO_TypeDef;
In the hardware, and in the hardware documentation, BSRR is described as a single 32-bit register. About 98% of the time one wants to write to BSRR, one will only be interested in writing the upper half or the lower half; it is thus convenient to be able to use BSSRH and BSSRL as a means of writing half the register. On the other hand, there are occasions when it is necessary that the entire 32-bit register be written as a single atomic operation. The "optimal" way to write it (setting aside white-spacing issues) would be:
typedef struct
{
__IO uint32_t MODER;
__IO uint16_t OTYPER;
uint16_t RESERVED0;
....
union // Allow BSRR access as 32-bit register or two 16-bit registers
{
__IO uint32_t BSRR; // 32-bit BSSR register as a whole
struct { __IO uint16_t BSRRL, BSRRH; };// Two 16-bit parts
};
....
} GPIO_TypeDef;
If the struct were defined that way, code could use BSRR when necessary to write all 32 bits, or BSRRH/BSRRL when writing 16 bits. Given that the header isn't that way, would better practice be to use the header as-is, but apply an icky typecast in the main code writing what would be idiomatically written as thePort->BSRR = 0x12345678;
as *((uint32_t)&(thePort->BSSRH)) = 0x12345678;
, or would be be better to use a patched header file? If the latter, where should the patched file me stored and how should it be managed?
© Programmers or respective owner