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
)