rtos: Make ChibiOS code aware of endiness
[fw/openocd] / src / rtos / ChibiOS.c
index c838b493c7d5f965bab2a2cfe6ee72de61e241d2..7d1f5cf852eb579bc9ff9cad6394e5360470b83a 100644 (file)
@@ -29,6 +29,8 @@
 #include <jtag/jtag.h>
 #include "target/target.h"
 #include "target/target_type.h"
+#include "target/armv7m.h"
+#include "target/cortex_m.h"
 #include "rtos.h"
 #include "helper/log.h"
 #include "helper/types.h"
@@ -94,12 +96,12 @@ struct ChibiOS_params ChibiOS_params_list[] = {
        {
        "cortex_m3",                                                    /* target_name */
        0,
-       &rtos_chibios_arm_v7m_stacking,         /* stacking_info */
+       NULL,                                                                   /* stacking_info */
        },
        {
        "stm32_stlink",                                                 /* target_name */
        0,
-       &rtos_chibios_arm_v7m_stacking,         /* stacking_info */
+       NULL,                                                                   /* stacking_info */
        }
 };
 #define CHIBIOS_NUM_PARAMS ((int)(sizeof(ChibiOS_params_list)/sizeof(struct ChibiOS_params)))
@@ -189,6 +191,15 @@ static int ChibiOS_update_memory_signature(struct rtos *rtos)
                        "running version %i.%i.%i", GET_CH_KERNEL_MAJOR(ch_version),
                        GET_CH_KERNEL_MINOR(ch_version), GET_CH_KERNEL_PATCH(ch_version));
 
+       /* Currently, we have the inherent assumption that all address pointers
+        * are 32 bit wide. */
+       if (signature->ch_ptrsize != sizeof(uint32_t)) {
+               LOG_ERROR("ChibiOS/RT target memory signature claims an address"
+                                 "width unequal to 32 bits!");
+               free(signature);
+               return -1;
+       }
+
        param->signature = signature;
        return 0;
 
@@ -219,8 +230,43 @@ static int ChibiOS_update_stacking(struct rtos *rtos)
         *    available than the current execution. In which case
         *    ChibiOS_get_thread_reg_list is called.
         */
+       int retval;
+
+       if (!rtos->rtos_specific_params)
+               return -1;
+
+       struct ChibiOS_params *param;
+       param = (struct ChibiOS_params *) rtos->rtos_specific_params;
+
+       /* Check for armv7m with *enabled* FPU, i.e. a Cortex M4  */
+       struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
+       if (is_armv7m(armv7m_target)) {
+               if (armv7m_target->fp_feature == FPv4_SP) {
+                       /* Found ARM v7m target which includes a FPU */
+                       uint32_t cpacr;
+
+                       retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Could not read CPACR register to check FPU state");
+                               return -1;
+                       }
+
+                       /* Check if CP10 and CP11 are set to full access.
+                        * In ChibiOS this is done in ResetHandler() in crt0.c */
+                       if (cpacr & 0x00F00000) {
+                               /* Found target with enabled FPU */
+                               /* FIXME: Need to figure out how to specify the FPU registers */
+                               LOG_ERROR("ChibiOS ARM v7m targets with enabled FPU "
+                                                 " are NOT supported");
+                               return -1;
+                       }
+               }
+
+               /* Found ARM v7m target with no or disabled FPU */
+               param->stacking_info = &rtos_chibios_arm_v7m_stacking;
+               return 0;
+       }
 
-       /* TODO: Add actual detection, currently it will not work  with FPU enabled.*/
        return -1;
 }
 
@@ -268,26 +314,17 @@ static int ChibiOS_update_threads(struct rtos *rtos)
        /* ChibiOS does not save the current thread count. We have to first
         * parse the double linked thread list to check for errors and the number of
         * threads. */
-       uint32_t rlist;
+       const uint32_t rlist = rtos->symbols[ChibiOS_VAL_rlist].address;
+       const struct ChibiOS_chdebug *signature = param->signature;
        uint32_t current;
        uint32_t previous;
        uint32_t older;
 
-       retval = target_read_buffer(rtos->target,
-               rtos->symbols[ChibiOS_VAL_rlist].address,
-               param->signature->ch_ptrsize,
-               (uint8_t *)&rlist);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("Could not read ChibiOS ReadyList from target");
-               return retval;
-       }
        current = rlist;
        previous = rlist;
        while (1) {
-               retval = target_read_buffer(rtos->target,
-                       current + param->signature->cf_off_newer,
-                       param->signature->ch_ptrsize,
-                       (uint8_t *)&current);
+               retval = target_read_u32(rtos->target,
+                                                                current + signature->cf_off_newer, &current);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read next ChibiOS thread");
                        return retval;
@@ -301,10 +338,8 @@ static int ChibiOS_update_threads(struct rtos *rtos)
                        break;
                }
                /* Fetch previous thread in the list as a integrity check. */
-               retval = target_read_buffer(rtos->target,
-                 current + param->signature->cf_off_older,
-                 param->signature->ch_ptrsize,
-                 (uint8_t *)&older);
+               retval = target_read_u32(rtos->target,
+                                                                current + signature->cf_off_older, &older);
                if ((retval != ERROR_OK) || (older == 0) || (older != previous)) {
                        LOG_ERROR("ChibiOS registry integrity check failed, "
                                                "double linked list violation");
@@ -359,10 +394,8 @@ static int ChibiOS_update_threads(struct rtos *rtos)
                uint32_t name_ptr = 0;
                char tmp_str[CHIBIOS_THREAD_NAME_STR_SIZE];
 
-               retval = target_read_buffer(rtos->target,
-                                                                       current + param->signature->cf_off_newer,
-                                                                       param->signature->ch_ptrsize,
-                                                                       (uint8_t *)&current);
+               retval = target_read_u32(rtos->target,
+                                                                current + signature->cf_off_newer, &current);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read next ChibiOS thread");
                        return -6;
@@ -376,10 +409,8 @@ static int ChibiOS_update_threads(struct rtos *rtos)
                curr_thrd_details->threadid = current;
 
                /* read the name pointer */
-               retval = target_read_buffer(rtos->target,
-                                                                       current + param->signature->cf_off_name,
-                                                                       param->signature->ch_ptrsize,
-                                                                       (uint8_t *)&name_ptr);
+               retval = target_read_u32(rtos->target,
+                                                                current + signature->cf_off_name, &name_ptr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read ChibiOS thread name pointer from target");
                        return retval;
@@ -406,9 +437,8 @@ static int ChibiOS_update_threads(struct rtos *rtos)
                uint8_t threadState;
                const char *state_desc;
 
-               retval = target_read_buffer(rtos->target,
-                                                                       current + param->signature->cf_off_state,
-                                                                       1, &threadState);
+               retval = target_read_u8(rtos->target,
+                                                               current + signature->cf_off_state, &threadState);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Error reading thread state from ChibiOS target");
                        return retval;
@@ -429,15 +459,17 @@ static int ChibiOS_update_threads(struct rtos *rtos)
 
                curr_thrd_details++;
        }
+
+       uint32_t current_thrd;
        /* NOTE: By design, cf_off_name equals readylist_current_offset */
-       retval = target_read_buffer(rtos->target,
-                                                               rlist + param->signature->cf_off_name,
-                                                               param->signature->ch_ptrsize,
-                                                               (uint8_t *)&rtos->current_thread);
+       retval = target_read_u32(rtos->target,
+                                                        current + signature->cf_off_name,
+                                                        &current_thrd);
        if (retval != ERROR_OK) {
                LOG_ERROR("Could not read current Thread from ChibiOS target");
                return retval;
        }
+       rtos->current_thread = current_thrd;
 
        return 0;
 }
@@ -446,7 +478,7 @@ static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, cha
 {
        int retval;
        const struct ChibiOS_params *param;
-       int64_t stack_ptr = 0;
+       uint32_t stack_ptr = 0;
 
        *hex_reg_list = NULL;
        if ((rtos == NULL) || (thread_id == 0) ||
@@ -466,10 +498,8 @@ static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, cha
        }
 
        /* Read the stack pointer */
-       retval = target_read_buffer(rtos->target,
-                       thread_id + param->signature->cf_off_ctx,
-                       param->signature->ch_ptrsize,
-                       (uint8_t *)&stack_ptr);
+       retval = target_read_u32(rtos->target,
+                                                        thread_id + param->signature->cf_off_ctx, &stack_ptr);
        if (retval != ERROR_OK) {
                LOG_ERROR("Error reading stack frame from ChibiOS thread");
                return retval;