0
votes

I was trying to transform a char type buffer into a struct defined by me in order to analyze the buffer by TLV. But i jumped into hard fault again and again.

codes are these: a little bit long.

#define BigtoLittle32(A)   ((( (uint32_t)(A) & 0xff000000) >> 24) | \
                                   (( (uint32_t)(A) & 0x00ff0000) >> 8)   | \
                                   (( (uint32_t)(A) & 0x0000ff00) << 8)   | \
                                   (( (uint32_t)(A) & 0x000000ff) << 24))

enum {
    DISH = 0
} CB_DISH_TLV_TYPES;

typedef struct cb_tlv_node_s
{
    uint32_t type;
    uint32_t length;
    char value[0];
} cb_tlv_node_t;


typedef struct cb_ble_buffer_s {
    uint16_t total_length;
    uint16_t current_length;
    int8_t current_data_id;
    int8_t expect_package_id;
    char buffer[500];
} cb_ble_buffer_t;

static cb_ble_buffer_t                  current_buffer;

cb_tlv_node_t *
cb_tlv_read(char *buffer)
{
    uint32_t a,b,c,d;
    cb_tlv_node_t * tlv_p;
    tlv_p =  (cb_tlv_node_t *)buffer;
/*    tlv_p->length = BigtoLittle32(tlv_p->length);*/  //this code also cause hard fault
/*    tlv_p->type = BigtoLittle32(tlv_p->type);*/  //didn't test this one ,but high risk causing hard fault

    return tlv_p;
}

//ble packages are reorgnized and call this function. it excutes in the ble recieve interupt
int
cb_dish_data_processer(char * data, int length)
{
    assert(data != NULL);
    assert(length > 0);


    cb_tlv_node_t *tlv_p = cb_tlv_read(data);

    //test
    int a = sizeof(CB_DISH_TLV_TYPES);

    //if ((char)tlv_p->type != DISH) { //this code is fine and steady
    if (tlv_p->type != DISH) {         //this leads to hard fault
        return CB_PC_CODE_UNRECOGNIZE;
    }

    cb_dish_tlv_read(tlv_p->value, tlv_p->length);
    return CB_PC_CODE_PROCESSED;
}

Fist I am sure that pointers are not lost ,so there should not be any kind if illegal address been used; Second I assume my process is too long to be in an interrupt so I moved my codes out side and excite in the main loop, but still useless;

So I am stucked here, I can't find any reason causing this. if you need more info ,leave a message, I will be waiting online. ps:the hardware board is Nordic nf51822 with 8kB RAM, 256kB flash ROM

BTW:Is it true that calloc and other alloc functions are forbidden in this kind of boards? because when I try to alloc a new space dynamically, the board goes wrong and reset it self.

Thanks a lot

1
Whether dynamic memory allocation functions are available or not, is dependent on your compilation tools. 8kB is very small amount of memory, and it is possible that there is no memory pool reserved for allocation functions. Check your compiler/linker settings. - user694733
@user694733 keil c 4.0 is the complier i'm using, i didn't know the exactly params used for compiling, I used the Keil uVersion IDE on Windows. and use the Nordic template project to develop the board. Hope this information is useful - Kevin wang
One thing that looks suspicious is that you convert char* buffer to (cb_tlv_node_t *) and try to use it. ARM requires that 32-bit integers are correctly aligned to 4-byte boundaries when accesing them. It is likely that buffer pointed by char *buffer is aligned to 1-byte boundaries. - user694733
@user694733 WTF.....I used to use gcc compile and run program in Linux, so i never thought of it..... thanks a lot , the problem is solved. Thank you very much! - Kevin wang
Glad if it helped. If you want to avoid problems, avoid anything that C standard considers undefined behaviour. You can do this by: 1. Set compiler warning levels to MAX, and fix any warnings. 2. Use casting as little as possible, as it usually hides the problems. 3. Do not use testing to determine if something works in C; it's not reliable. When in doubt, check the C standard (and stackoverflow.com). - user694733

1 Answers

0
votes

One thing that looks suspicious is that you convert char* buffer to (cb_tlv_node_t *) and try to use it. ARM requires that 32-bit integers are correctly aligned to 4-byte boundaries when accesing them. It is likely that buffer pointed by char *buffer is aligned to 1-byte boundaries. by user694733

so i changed this

typedef struct cb_ble_buffer_s {
    uint16_t total_length;
    uint16_t current_length;
    int8_t current_data_id;
    int8_t expect_package_id;
    char buffer[500];
} cb_ble_buffer_t;

into this

typedef struct cb_ble_buffer_s {
    uint16_t total_length;
    uint16_t current_length;
    int16_t current_data_id;
    int16_t expect_package_id;
    char buffer[500];
} cb_ble_buffer_t;

and it just works fine and steady many thanks to @user694733