This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Image format in SitaraWare/StellarisWare

From Section 3.1.3 of the StellarisWare GrLib Manual:
"Images are stored as an array of unsigned characters. Ideally, they would be in a structure, but the limitations of C prevents an efficient definition of a structure for an image while still allowing a compile-time declaration of the data for an image. The effective definition of the structure is as follows (with no padding between members):

typedef struct
{
    //
    // Specifies the format of the image data; will be one of
    // IMAGE_FMT_1BPP_UNCOMP, IMAGE_FMT_4BPP_UNCOMP, IMAGE_FMT_8BPP_UNCOMP,
    // IMAGE_FMT_1BPP_COMP, IMAGE_FMT_4BPP_COMP, or IMAGE_FMT_8BPP_COMP. The
    // xxx_COMP varieties indicate that the image data is compressed.
    //
    unsigned char ucFormat;
   
    //
    // The width of the image in pixels.
    //
    unsigned short usWidth;
   
    //
    // The height of the image in pixels.
    //
    unsigned short usHeight;
   
    //
    // The image data. This is the structure member that C can not handle
    // efficiently at compile time.
    //
    unsigned char pucData[];
}
tImage;
"

I'm trying to use the SitaraWare Graphics Library and since so little of the StellarisWare Graphics Library is changed when ported to SitaraWare, can someone explain a couple things?
1. In what way can C not handle this structure efficiently at compile time? Wouldn't this work:
const tImage g_sTILogo = {
   .ucFormat = IMAGE_FMT_4BPP_COMP, .usWidth = 240, .usHeight = 13,
   .pucData = {0x00, 0x00, 0x00, 0x25, 0x26, 0x25, ... }
};

I think this is acceptable in C99 as a 'flexible array member' (ISO/IEC 9899:1999, Section 6.7.2.1, paragraph 16).

2. I'm trying to write a display driver for SitaraWare GrLib for a 1BPP (monochrome) display. The function GrOffScreen1BPPInit() contains the following code:
    //
    // Initialize the image buffer.
    //
    pucImage[0] = IMAGE_FMT_1BPP_UNCOMP;
    *(unsigned short *)(pucImage + 1) = lWidth;
    *(unsigned short *)(pucImage + 3) = lHeight;

Both CodeSourcery's and IAR's C Compilers produce the following instructions:
    //
    // Initialize the image buffer.
    //
    pucImage[0] = IMAGE_FMT_1BPP_UNCOMP;
c1080e00:    e3a00001     mov    r0, #1
c1080e04:    e5c10000     strb    r0, [r1]
    *(unsigned short *)(pucImage + 1) = lWidth;
c1080e08:    e1c120b1     strh    r2, [r1, #1]
    *(unsigned short *)(pucImage + 3) = lHeight;
c1080e0c:    e1c130b3     strh    r3, [r1, #3]

This leads to funky behavior when executed because, by default, pucImage is aligned on some even boundary, therefore pucImage + 1 is NOT on an even boundary. The compilers are generating a STRH (store halfword) instruction, which, according to the ARM Architecture Reference Manual (ARM DDI 0100I), Section A4.1.104, "If the address is not halfword-aligned, the result is UNPREDICTABLE." I can confirm, single-stepping through the instructions in IAR, that STRH will overwrite the ucFormat byte with the LSB of lWidth. Perhaps this problem didn't show up in StellarisWare because the Cortex-M3 (Thumb?) instructions didn't share this limitation? Any proposals for a solution?

  • Eric,

    I think you ran into the same issue we see with network protocols in Sitaraware (see the release notes). ARM9 architecture does not support unaligned access. Later ARM architectures (Cortex-M, -A) do support unaligned access in hardware.

    For ARM9 the issue is left to the programmer or the tools. Now each compiler might handle this differently I believe. For example in GCC there is a 'packed' attribute for structs. I haven't looked at the assembly code what it really does so far. But I ran one project where we compiled the network code with GCC just due to that issue.

    I will leave it to our Sitaraware team to comment further. Especially if we consider this an issue in Sitaraware or not. The image struct could just be changed to have no alignment issues (as long as you don't need binary compatibility with another system).

    Regards.