rtthread 设备及调用分析

硬件加密设备

1.框图

2.设备使用流程

1.初始化rt_hwcrypto_device, 并调用rt_hwcrypto_register注册;

初始化rt_hwcrypto_device nu_hwcrypto_dev变量, 设置ops, id以及user_data, 初始化硬件.

    rt_err_t result;
    static struct rt_hwcrypto_device nu_hwcrypto_dev;

    nu_hwcrypto_dev.ops = &nu_hwcrypto_ops;
    nu_hwcrypto_dev.id = 0;
    nu_hwcrypto_dev.user_data = &nu_hwcrypto_dev;

    nu_crypto_init();

    /* register hwcrypto operation */
    result = rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME);
    RT_ASSERT(result == RT_EOK);

    return 0;

2.初始化rt_device设备层属性, 并注册设备

rt_err_t rt_hwcrypto_register(struct rt_hwcrypto_device *device, const char *name)
{
    rt_err_t err;

    RT_ASSERT(device != RT_NULL);
    RT_ASSERT(name != RT_NULL);
    RT_ASSERT(device->ops != RT_NULL);
    RT_ASSERT(device->ops->create != RT_NULL);
    RT_ASSERT(device->ops->destroy != RT_NULL);
    RT_ASSERT(device->ops->copy != RT_NULL);
    RT_ASSERT(device->ops->reset != RT_NULL);

    rt_memset(&device->parent, 0, sizeof(struct rt_device));

    device->parent.ops = &hwcrypto_ops;
    device->parent.user_data  = RT_NULL;
    device->parent.type = RT_Device_Class_Miscellaneous;

    /* Register device */
    err = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);

    return err;
}

3.注册到对象层并初始化部分属性

rt_err_t rt_device_register(rt_device_t dev,
                            const char *name,
                            rt_uint16_t flags)
{
    rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
    dev->flag = flags;
    dev->ref_count = 0;
    dev->open_flag = 0;

    return RT_EOK;
}

4.对象层将设备加入链表, 并初始化相关对象属性. 设备注册完成.

void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
{
    register rt_base_t temp;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information;

    /* get object information */
    information = rt_object_get_information(type);

    /* enter critical */
    rt_enter_critical();
    /* try to find object */
    for (node  = information->object_list.next;
            node != &(information->object_list);
            node  = node->next)
    {
        struct rt_object *obj;

        obj = rt_list_entry(node, struct rt_object, list);
        if (obj) /* skip warning when disable debug */
        {
            RT_ASSERT(obj != object);
        }
    }
    /* leave critical */
    rt_exit_critical();

    /* initialize object's parameters */
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);

    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));

    /* lock interrupt */
    temp = rt_hw_interrupt_disable();

    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }

    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
}

5.设备的应用方法, 通过设备名称在链表中找到关于设备的指针.

//1111, 查询hwcrypto默认设备, 并创建和设备以及应用属性相关的上限文.
    struct rt_hwcrypto_ctx *ctx;

    /* 创建一个 SHA1/MD5 类型的上下文 */
    ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA256);

//2222 创建rt_hwcrypto_ctx类型xtc上下文, 内存大小sizeof(struct hwcrypto_hash), 实际内存属性满足hwcrypto_hash
    struct rt_hwcrypto_ctx *rt_hwcrypto_hash_create(struct rt_hwcrypto_device *device, hwcrypto_type type)
{
    struct rt_hwcrypto_ctx *ctx;

    ctx = rt_hwcrypto_ctx_create(device, type, sizeof(struct hwcrypto_hash));
    return ctx;
}
//3333 获取内存, 初始化ctx上下文.
struct rt_hwcrypto_ctx *rt_hwcrypto_ctx_create(struct rt_hwcrypto_device *device, hwcrypto_type type, rt_uint32_t obj_size)
{
    struct rt_hwcrypto_ctx *ctx;
    rt_err_t err;

    /* Parameter checking */
    if (device == RT_NULL || obj_size < sizeof(struct rt_hwcrypto_ctx))
    {
        return RT_NULL;
    }
    ctx = rt_malloc(obj_size);
    if (ctx == RT_NULL)
    {
        return ctx;
    }
    rt_memset(ctx, 0, obj_size);
    /* Init context */
    err = rt_hwcrypto_ctx_init(ctx, device, type);
    if (err != RT_EOK)
    {
        rt_free(ctx);
        ctx = RT_NULL;
    }
    return ctx;
}
//4444 将设备注册到上下文, 并用之前注册设备是的ops中creat方法创建ctx上下文.
rt_err_t rt_hwcrypto_ctx_init(struct rt_hwcrypto_ctx *ctx, struct rt_hwcrypto_device *device, hwcrypto_type type)
{
    rt_err_t err;

    /* Setting context type */
    rt_hwcrypto_set_type(ctx, type);
    ctx->device = device;
    /* Create hardware context */
    err = ctx->device->ops->create(ctx);
    if (err != RT_EOK)
    {
        return err;
    }
    return RT_EOK;
}
//5555 将对应属性的ops注册到ctx->ops, 申请空间S_SHA_CONTEXT大小内存注册到ctx->contex,
//由此实现的方法以及数据传递的途径.
// 实例中现则的是HWCRYPTO_TYPE_SHA2属性
    ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT));

    if (ctx->contex == RT_NULL)
        return -RT_ERROR;

    rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT));
    //Setup operation
    ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops;

6.通过ctx上下文的ops进行顶层次的调用, contex属性可以传递数据, 以下更新数据

//1111 该内容为在定层次应用的调用
    rt_hwcrypto_hash_update(ctx, data, data_len);
//2222 调用注册的ops中的update方法
rt_err_t rt_hwcrypto_hash_update(struct rt_hwcrypto_ctx *ctx, const rt_uint8_t *input, rt_size_t length)
{
    if (ctx && ((struct hwcrypto_hash *)ctx)->ops->update)
    {
        return ((struct hwcrypto_hash *)ctx)->ops->update((struct hwcrypto_hash *)ctx, input, length, 0);
    }
    return -RT_ERROR;
}
//3333 本质为调用函数, 通过以上指针方式的调用, 程序重新运行到驱动层
static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t *in, rt_size_t length, rt_size_t key_length)
{
    uint32_t u32SHAOpMode;
    unsigned char *nu_in;
    unsigned char in_align_flag = 0;
    RT_ASSERT(hash_ctx != RT_NULL);
    RT_ASSERT(in != RT_NULL);

    //Select SHA operation mode
    switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
    {
    case HWCRYPTO_TYPE_SHA1:
        u32SHAOpMode = SHA_MODE_SHA1;
        break;
    case HWCRYPTO_TYPE_SHA224:
        u32SHAOpMode = SHA_MODE_SHA224;
        break;
    case HWCRYPTO_TYPE_SHA256:
        u32SHAOpMode = SHA_MODE_SHA256;
        break;
    case HWCRYPTO_TYPE_SHA384:
        u32SHAOpMode = SHA_MODE_SHA384;
        break;
    case HWCRYPTO_TYPE_SHA512:
        u32SHAOpMode = SHA_MODE_SHA512;
        break;
    default :
        return -RT_ERROR;
    }

    nu_in = (unsigned char *)in;

    //Checking in data buffer address not alignment or out of SRAM
    if (((rt_uint32_t)nu_in % 4) != 0 || ((rt_uint32_t)nu_in < SRAM_BASE) || ((rt_uint32_t)nu_in > SRAM_END))
    {
        nu_in = rt_malloc(length);
        if (nu_in == RT_NULL)
        {
            LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, length);
            return -RT_ENOMEM;
        }

        rt_memcpy(nu_in, in, length);
        in_align_flag = 1;
    }

    nu_sha_hash_run(hash_ctx->parent.contex, u32SHAOpMode, nu_in, length, key_length);

    if (in_align_flag)
    {
        rt_free(nu_in);
    }

    return RT_EOK;
}
//4444 nu_sha_hash_run调用时实际可以携带两组数据, 一组为hash_ctx->parent.contex中携带, 一组为un_in中携带
static rt_err_t nu_sha_hash_run(
    S_SHA_CONTEXT *psSHACtx,
    uint32_t u32OpMode,
    uint8_t *pu8InData,
    uint32_t u32DataLen,
    uint32_t u32KeyLen
)
posted @ 2022-04-07 11:03  mhtc  阅读(426)  评论(0编辑  收藏  举报