GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
../build/mcu.mk
+7
View File
@@ -0,0 +1,7 @@
SRCS-y += drivers/
SRCS-y += devices/
SRCS-y += sensors/
SRCS-y += sample/
+1
View File
@@ -0,0 +1 @@
../../source/gmp/usr/isp/libs/riscv
+3
View File
@@ -0,0 +1,3 @@
SRCS-y += i2c_dev.c
+30
View File
@@ -0,0 +1,30 @@
#include"xmedia_type.h"
#include"xmedia_errcode.h"
#include"i2c.h"
#include "compile.h"
#define REG_ADDR_MAX_WIDTH 2//16BIT
STAGE1_FUNC xmedia_s32 i2c_read(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u32 read_addr,
xmedia_u8 addr_width, xmedia_u8 *buff, xmedia_u32 length)
{
struct i2c_client client;
if(addr_width > REG_ADDR_MAX_WIDTH){
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
client.i2c_num = fd;
client.dev_addr = slave_addr >> 1;
client.reg_addr = read_addr;
client.reg_width = addr_width;
return i2c_recv(&client, buff, length);
}
STAGE1_FUNC xmedia_s32 i2c_write(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u8 *buff, xmedia_u32 length)
{
return i2c_send(fd, slave_addr >> 1, (xmedia_void *)buff, length);
}
+7
View File
@@ -0,0 +1,7 @@
SRCS-y += hal_isp.c
SRCS-y += drv_isp.c
SRCS-y += hal_vi.c
SRCS-y += drv_vi.c
+826
View File
@@ -0,0 +1,826 @@
#include "config.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "xmedia_type.h"
#include "xmedia_isp.h"
#include "xmedia_errcode.h"
#include "isp_def.h"
#include "hal_isp.h"
#include "drv_isp.h"
#include "platform.h"
#include "timer.h"
#define CCM_MINUS_PARAM_TH 32768
typedef struct {
xmedia_bool ae_lib;
xmedia_bool awb_lib;
xmedia_bool sensor_lib;
xmedia_isp_ae_register_info ae_info;
xmedia_isp_awb_register_info awb_info;
xmedia_sensor_register_info sensor_info;
} isp_lib_info;
typedef struct {
xmedia_isp_config isp_config;
xmedia_u32 isp_frame_cnt;
xmedia_void *firmware_info;
isp_lib_info *lib_info;
xmedia_sensor_init_param *result;
} isp_context;
STAGE1_GLOBAL static isp_context *g_isp_ctx[ISP_PIPE_MAX_NUM] = { 0 };
STAGE1_GLOBAL static isp_lib_info g_isp_lib[ISP_PIPE_MAX_NUM] = { 0 };
STAGE1_GLOBAL static xmedia_u8 g_sensor_clk_ch[ISP_PIPE_MAX_NUM] = { 0 };
STAGE1_GLOBAL static xmedia_u8 g_sensor_rst_ch[ISP_PIPE_MAX_NUM] = { 0 };
#define ISP_GET_CTX(pipe, ctx) ctx = g_isp_ctx[pipe]
#define ISP_GET_LIB(pipe, ptr) ptr = &g_isp_lib[pipe]
#define TIMER_CLOCK_FRQ 24000000
xmedia_u32 isp_get_time_stamp(xmedia_void)
{
return (xmedia_u32)timer_get_val() / 24; // = timer_value * 10000000 / 24000000
}
STAGE1_FUNC xmedia_s32 xmedia_isp_register_sensor(xmedia_u32 pipe, const xmedia_sensor_register_info *info)
{
isp_context *ctx = XMEDIA_NULL;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM || info == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib == XMEDIA_TRUE) {
return XMEDIA_ERRCODE_EXIST;
}
// sensor需要在ISP初始化之前注册,ISP初始化时才会为ctx分配内存,所以用ctx来作为判断条件
if (ctx != XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
memcpy(&lib->sensor_info, info, sizeof(xmedia_sensor_register_info));
lib->sensor_lib = XMEDIA_TRUE;
return XMEDIA_SUCCESS;
}
xmedia_s32 xmedia_isp_unregister_sensor(xmedia_u32 pipe, xmedia_u32 dev_id)
{
isp_context *ctx = XMEDIA_NULL;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib == XMEDIA_FALSE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
// sensor需要在ISP退出之后反注册,ISP退出时才会释放ctx内存,所以用ctx来作为判断条件
if (ctx != XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
if (lib->sensor_info.dev_id != dev_id) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
lib->sensor_lib = XMEDIA_FALSE;
memset(&lib->sensor_info, 0, sizeof(xmedia_sensor_register_info));
return XMEDIA_SUCCESS;
}
xmedia_s32 xmedia_isp_register_ae_lib(xmedia_u32 pipe, const xmedia_isp_ae_register_info *ae_info,
xmedia_sensor_register_ae_info *sensor_func)
{
isp_context *ctx = XMEDIA_NULL;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM || ae_info == XMEDIA_NULL || sensor_func == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
ISP_GET_LIB(pipe, lib);
if (lib->ae_lib == XMEDIA_TRUE) {
return XMEDIA_ERRCODE_EXIST;
}
// 3a需要在ISP初始化之前注册,ISP初始化时才会为ctx分配内存,所以用ctx来作为判断条件
if (ctx != XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
memcpy(&sensor_func->func, &lib->sensor_info.ae_func, sizeof(xmedia_sensor_register_ae_func));
sensor_func->dev_id = lib->sensor_info.dev_id;
memcpy(&lib->ae_info, ae_info, sizeof(xmedia_isp_ae_register_info));
lib->ae_lib = XMEDIA_TRUE;
return XMEDIA_SUCCESS;
}
xmedia_s32 xmedia_isp_unregister_ae_lib(xmedia_u32 pipe, xmedia_char name[XMEDIA_ISP_ALG_NAME_MAX_SIZE], xmedia_s32 id)
{
isp_context *ctx = XMEDIA_NULL;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM || name == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
ISP_GET_LIB(pipe, lib);
if (lib->ae_lib == XMEDIA_FALSE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
// 3a需要在ISP退出之后反注册,ISP退出时才会释放ctx内存,所以用ctx来作为判断条件
if (ctx != XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
if (lib->ae_info.alg_id == id && strncmp(lib->ae_info.alg_name, name, XMEDIA_ISP_ALG_NAME_MAX_SIZE) == 0) {
memset(&lib->ae_info, 0, sizeof(xmedia_isp_ae_register_info));
lib->ae_lib = XMEDIA_FALSE;
} else {
return XMEDIA_ERRCODE_NOT_EXIST;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 xmedia_isp_register_awb_lib(xmedia_u32 pipe, const xmedia_isp_awb_register_info *awb_info,
xmedia_sensor_register_awb_info *sensor_func)
{
isp_context *ctx = XMEDIA_NULL;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM || awb_info == XMEDIA_NULL || sensor_func == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
ISP_GET_LIB(pipe, lib);
if (lib->awb_lib == XMEDIA_TRUE) {
return XMEDIA_ERRCODE_EXIST;
}
// 3a需要在ISP初始化之前注册,ISP初始化时才会为ctx分配内存,所以用ctx来作为判断条件
if (ctx != XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
memcpy(&sensor_func->func, &lib->sensor_info.awb_func, sizeof(xmedia_sensor_register_awb_func));
sensor_func->dev_id = lib->sensor_info.dev_id;
memcpy(&lib->awb_info, awb_info, sizeof(xmedia_isp_awb_register_info));
lib->awb_lib = XMEDIA_TRUE;
return XMEDIA_SUCCESS;
}
xmedia_s32 xmedia_isp_unregister_awb_lib(xmedia_u32 pipe, xmedia_char name[XMEDIA_ISP_ALG_NAME_MAX_SIZE], xmedia_s32 id)
{
isp_context *ctx = XMEDIA_NULL;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM || name == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
ISP_GET_LIB(pipe, lib);
if (lib->awb_lib == XMEDIA_FALSE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
// 3a需要在ISP退出之后反注册,ISP退出时才会释放ctx内存,所以用ctx来作为判断条件
if (ctx != XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_PERMITTED;
}
if (lib->awb_info.alg_id == id && strncmp(lib->awb_info.alg_name, name, XMEDIA_ISP_ALG_NAME_MAX_SIZE) == 0) {
memset(&lib->awb_info, 0, sizeof(xmedia_isp_awb_register_info));
lib->awb_lib = XMEDIA_FALSE;
} else {
return XMEDIA_ERRCODE_NOT_EXIST;
}
return XMEDIA_SUCCESS;
}
STAGE1_FUNC xmedia_s32 drv_sensor_init(xmedia_u32 pipe, xmedia_sensor_config *cfg)
{
xmedia_s32 ret = 0;
isp_lib_info *lib = XMEDIA_NULL;
xmedia_sensor_capability capability;
if (pipe >= ISP_PIPE_MAX_NUM || cfg == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_init == XMEDIA_NULL ||
lib->sensor_info.isp_func.pfn_sensor_set_bus_info == XMEDIA_NULL ||
lib->sensor_info.isp_func.pfn_sensor_get_capability == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
g_sensor_clk_ch[pipe] = cfg->ctrl_sig.clk_ch;
g_sensor_rst_ch[pipe] = cfg->ctrl_sig.rst_ch;
ret = lib->sensor_info.isp_func.pfn_sensor_set_bus_info(lib->sensor_info.dev_id, &cfg->comm_bus);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
ret = lib->sensor_info.isp_func.pfn_sensor_get_capability(&capability);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
if (capability.reset_time <= 0) {
capability.reset_time = 100;
}
hal_sensor_set_mclk(g_sensor_clk_ch[pipe], capability.init_mclk);
//sensor cold start use normal, hot start use skip
if (cfg->init_mode != XMEDIA_SENSOR_INIT_MODE_SKIP) {
hal_sensor_reset(g_sensor_rst_ch[pipe], XMEDIA_TRUE);
udelay(capability.reset_time);
hal_sensor_reset(g_sensor_rst_ch[pipe], XMEDIA_FALSE);
}
udelay(1000*4);
return lib->sensor_info.isp_func.pfn_sensor_init(lib->sensor_info.dev_id, cfg->init_mode);
}
xmedia_s32 drv_sensor_exit(xmedia_u32 pipe)
{
xmedia_s32 ret = 0;
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_exit == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
ret = lib->sensor_info.isp_func.pfn_sensor_exit(lib->sensor_info.dev_id);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
return XMEDIA_SUCCESS;
}
STAGE1_FUNC xmedia_s32 drv_sensor_resume(xmedia_u32 pipe)
{
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("pipe error \n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
puts("sensor lib error\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_resume == XMEDIA_NULL) {
puts("sensor resume none\n");
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
return lib->sensor_info.isp_func.pfn_sensor_resume(lib->sensor_info.dev_id);
}
STAGE1_FUNC xmedia_s32 drv_sensor_start(xmedia_u32 pipe)
{
xmedia_s32 ret = 0;
xmedia_u32 mclk = 0;
isp_lib_info *lib = XMEDIA_NULL;
xmedia_sensor_property property;
if (pipe >= ISP_PIPE_MAX_NUM) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_start == XMEDIA_NULL ||
lib->sensor_info.isp_func.pfn_sensor_get_property == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
ret = lib->sensor_info.isp_func.pfn_sensor_get_property(lib->sensor_info.dev_id, &property);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
hal_sensor_read_mclk(g_sensor_clk_ch[pipe], &mclk);
if (property.input_clock != mclk) {
hal_sensor_set_mclk(g_sensor_clk_ch[pipe], property.input_clock);
}
return lib->sensor_info.isp_func.pfn_sensor_start(lib->sensor_info.dev_id);
}
xmedia_s32 drv_sensor_stop(xmedia_u32 pipe)
{
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_stop == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
return lib->sensor_info.isp_func.pfn_sensor_stop(lib->sensor_info.dev_id);
}
STAGE1_FUNC xmedia_s32 drv_sensor_set_mipi_lanes(xmedia_u32 pipe, const xmedia_sensor_mipi_lanes mipi_lanes)
{
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_set_mipi_lanes == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
return lib->sensor_info.isp_func.pfn_sensor_set_mipi_lanes(lib->sensor_info.dev_id, mipi_lanes);
}
STAGE1_FUNC xmedia_s32 drv_sensor_set_attr(xmedia_u32 pipe, const xmedia_sensor_attr *sns_attr)
{
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_set_attr == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
return lib->sensor_info.isp_func.pfn_sensor_set_attr(lib->sensor_info.dev_id, sns_attr);
}
xmedia_s32 drv_sensor_set_init_param(xmedia_u32 pipe, const xmedia_sensor_init_param *init_param)
{
isp_lib_info *lib = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM || init_param == XMEDIA_NULL) {
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_LIB(pipe, lib);
if (lib->sensor_lib != XMEDIA_TRUE) {
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (lib->sensor_info.isp_func.pfn_sensor_set_init_param == XMEDIA_NULL) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
return lib->sensor_info.isp_func.pfn_sensor_set_init_param(lib->sensor_info.dev_id, init_param);
}
xmedia_s32 drv_isp_init(xmedia_u32 pipe, xmedia_isp_config *cfg)
{
isp_context *ctx = XMEDIA_NULL;
xmedia_sensor_black_level blc;
xmedia_s32 ret;
xmedia_isp_ae_param ae_param;
xmedia_isp_awb_param awb_param;
xmedia_sensor_isp_default isp_default;
#if ISP_COST_TIME_DEBUG
xmedia_u32 start, end;
start = isp_get_time_stamp();
#endif
if (pipe >= ISP_PIPE_MAX_NUM || cfg == XMEDIA_NULL) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
if (ctx != XMEDIA_NULL) {
puts("isp ctx already exist!\n");
return XMEDIA_ERRCODE_EXIST;
}
if (g_isp_lib[pipe].ae_lib == XMEDIA_FALSE) {
puts("isp not register ae lib!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (g_isp_lib[pipe].awb_lib == XMEDIA_FALSE) {
puts("isp not register awb lib!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
ctx = malloc(sizeof(isp_context));
if (ctx == XMEDIA_NULL) {
puts("isp malloc ctx failed!\n");
return XMEDIA_ERRCODE_NO_BUFFER_FREE;
}
g_isp_ctx[pipe] = ctx;
g_isp_ctx[pipe]->lib_info = &g_isp_lib[pipe];
g_isp_ctx[pipe]->lib_info->sensor_info.isp_func.pfn_sensor_get_isp_black_level(
g_isp_ctx[pipe]->lib_info->sensor_info.dev_id, &blc);
ae_param.balck_level[0] = blc.black_level[0];
ae_param.balck_level[1] = blc.black_level[1];
ae_param.balck_level[2] = blc.black_level[2];
ae_param.balck_level[3] = blc.black_level[3];
ae_param.sensor_id = 0;
ae_param.wdr_mode = cfg->wdr_mode;
ae_param.hdr_mode = cfg->wdr_mode;
ae_param.fps = cfg->fps;
ae_param.bayer_format = cfg->bayer_fmt;
ae_param.blend_config.blend_en = XMEDIA_FALSE;
ae_param.blend_config.blend_num = 0;
if (cfg->mode_config.work_mode == XMEDIA_ISP_WORK_MODE_MASTER) {
ae_param.blend_config.blend_en = cfg->mode_config.master_mode.blend_stat_enable;
ae_param.blend_config.blend_num = cfg->mode_config.master_mode.slave_num + 1;
}
g_isp_ctx[pipe]->lib_info->ae_info.pfn_ae_init(g_isp_ctx[pipe]->lib_info->ae_info.alg_id, &ae_param);
awb_param.wdr_mode = cfg->wdr_mode;
awb_param.init_iso = 100;
if (cfg->mode_config.work_mode == XMEDIA_ISP_WORK_MODE_MASTER) {
awb_param.blend_config.blend_en = cfg->mode_config.master_mode.blend_stat_enable;
awb_param.blend_config.blend_num = cfg->mode_config.master_mode.slave_num + 1;
}
g_isp_ctx[pipe]->lib_info->awb_info.pfn_awb_init(g_isp_ctx[pipe]->lib_info->awb_info.alg_id, &awb_param);
ctx->result = (xmedia_sensor_init_param *)CONFIG_PARAM_MEM_START;
memset(ctx->result, 0, sizeof(xmedia_sensor_init_param));
ret = hal_isp_init(pipe, cfg, &blc);
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_init failed.\n");
return ret;
}
if (cfg->wdr_mode == XMEDIA_VIDEO_WDR_MODE_BUILT_IN ) {
if (g_isp_ctx[pipe]->lib_info->sensor_info.isp_func.pfn_sensor_get_isp_default == XMEDIA_NULL ) {
return XMEDIA_ERRCODE_NOT_SUPPORT;
}
g_isp_ctx[pipe]->lib_info->sensor_info.isp_func.pfn_sensor_get_isp_default(
g_isp_ctx[pipe]->lib_info->sensor_info.dev_id, &isp_default);
ret = hal_isp_init_expander(pipe, isp_default.expander);
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_init_expander failed.\n");
return ret;
}
}
#if ISP_COST_TIME_DEBUG
end = isp_get_time_stamp();
puts("isp init cost time: ");
putdec(end - start);
puts(" us\n");
#endif
#if ISP_COUNT_SIZE_DEBUG
puts("isp_context size = ");
putdec(sizeof(isp_context));
puts("\n");
puts("g_isp_ctx size = ");
putdec(sizeof(g_isp_ctx));
puts("\n");
puts("g_isp_lib size = ");
putdec(sizeof(g_isp_lib));
puts("\n");
puts("g_sensor_clk_ch size = ");
putdec(sizeof(g_sensor_clk_ch));
puts("\n");
puts("g_sensor_rst_ch size = ");
putdec(sizeof(g_sensor_rst_ch));
puts("\n");
#endif
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_isp_exit(xmedia_u32 pipe)
{
isp_context *ctx = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
if (ctx == XMEDIA_NULL) {
puts("isp ctx not exist!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
g_isp_ctx[pipe]->lib_info->ae_info.pfn_ae_exit(g_isp_ctx[pipe]->lib_info->ae_info.alg_id);
g_isp_ctx[pipe]->lib_info->awb_info.pfn_awb_exit(g_isp_ctx[pipe]->lib_info->awb_info.alg_id);
free(ctx);
g_isp_ctx[pipe] = XMEDIA_NULL;
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_isp_start(xmedia_u32 pipe)
{
isp_context *ctx = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
if (ctx == XMEDIA_NULL) {
puts("isp ctx not exist!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_isp_stop(xmedia_u32 pipe)
{
isp_context *ctx = XMEDIA_NULL;
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
if (ctx == XMEDIA_NULL) {
puts("isp ctx not exist!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_isp_notifier(xmedia_u32 pipe, isp_irq_type irq_type)
{
isp_context *ctx = XMEDIA_NULL;
xmedia_s32 ret;
#if ISP_COST_TIME_DEBUG
xmedia_u32 start, end;
start = isp_get_time_stamp();
#endif
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
if (ctx == XMEDIA_NULL) {
puts("isp ctx not exist!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
if (irq_type == ISP_IRQ_TYPE_BE_FRAME_END) {
ret = hal_isp_format_statistics(pipe);
#if ISP_COST_TIME_DEBUG
end = isp_get_time_stamp();
puts("isp ISP_IRQ_TYPE_BE_FRAME_END cost time: ");
putdec(end - start);
puts(" us\n");
#endif
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_format_statistics failed!\n");
return ret;
}
} else if (irq_type == ISP_IRQ_TYPE_FE_FRAME_START) {
ret = hal_isp_sync(pipe);
#if ISP_COST_TIME_DEBUG
end = isp_get_time_stamp();
puts("isp ISP_IRQ_TYPE_FE_FRAME_START cost time: ");
putdec(end - start);
puts(" us\n");
#endif
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_sync failed!\n");
return ret;
}
}
return XMEDIA_SUCCESS;
}
// TODO: 统计耗时
xmedia_s32 drv_isp_process(xmedia_u32 pipe)
{
isp_context *ctx = XMEDIA_NULL;
xmedia_s32 ret;
xmedia_isp_statistics isp_stat = { 0 };
xmedia_isp_ae_info ae_info = { 0 };
xmedia_isp_awb_info awb_info = { 0 };
xmedia_isp_result isp_result = { 0 };
xmedia_sensor_regs_info reg_info = { 0 };
static xmedia_u64 last_frame_cnt = -1;
xmedia_u64 sys_gain;
xmedia_s32 i;
#if ISP_COST_TIME_DEBUG
xmedia_u32 start, end;
start = isp_get_time_stamp();
#endif
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ISP_GET_CTX(pipe, ctx);
if (ctx == XMEDIA_NULL) {
puts("isp ctx not exist!\n");
return XMEDIA_ERRCODE_NOT_EXIST;
}
ret = hal_isp_stat(pipe, &isp_stat);
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_stat failed!\n");
return ret;
}
if (last_frame_cnt == isp_stat.ae_stat.frame_cnt) {
return XMEDIA_ERRCODE_NOT_READY;
}
last_frame_cnt = isp_stat.ae_stat.frame_cnt;
ae_info.frame_cnt = isp_stat.ae_stat.frame_cnt;
ae_info.be_ae_stat_global_avg = &isp_stat.ae_stat.ae_stat_global_avg;
ae_info.be_ae_stat_hist = isp_stat.ae_stat.ae_stat_hist;
ctx->lib_info->ae_info.pfn_ae_run(ctx->lib_info->ae_info.alg_id, &ae_info, &isp_result.ae_result);
// awb分块统计信息是紧凑排布的,即行与行之间没有空白内存
awb_info.frame_cnt = isp_stat.awb_stat.frame_cnt;
awb_info.awb_zone_row = isp_stat.awb_stat.awb_zone_row_num;
awb_info.awb_zone_col = isp_stat.awb_stat.awb_zone_col_num;
awb_info.awb_width = isp_stat.awb_stat.awb_width;
awb_info.awb_height = isp_stat.awb_stat.awb_height;
awb_info.awb_stat_switch = XMEDIA_ISP_AE_SWITCH_AFTER_DGN2;
awb_info.awb_stat_local_avg_r = (xmedia_isp_awb_stat_local_avg_r *)isp_stat.awb_stat.awb_zone_avg_r;
awb_info.awb_stat_local_avg_g = (xmedia_isp_awb_stat_local_avg_g *)isp_stat.awb_stat.awb_zone_avg_g;
awb_info.awb_stat_local_avg_b = (xmedia_isp_awb_stat_local_avg_b *)isp_stat.awb_stat.awb_zone_avg_b;
awb_info.stat_local_valid_count = (xmedia_isp_awb_stat_local_valid_count *)isp_stat.awb_stat.awb_zone_valid_count;
ctx->lib_info->awb_info.pfn_awb_run(ctx->lib_info->awb_info.alg_id, &awb_info, &isp_result.awb_result);
sys_gain = (xmedia_u64)isp_result.ae_result.again * isp_result.ae_result.dgain * isp_result.ae_result.isp_dgain /
(1024 * 1024 * 256 / 64);
ctx->result->exp_time = isp_result.ae_result.int_time[0];
ctx->result->again = isp_result.ae_result.again;
ctx->result->dgain = isp_result.ae_result.dgain;
ctx->result->ispdgain = isp_result.ae_result.isp_dgain;
ctx->result->init_iso = isp_result.ae_result.iso;
ctx->result->exposure = (xmedia_u64)isp_result.ae_result.int_time[0] * sys_gain;
ctx->result->wb_rgain = isp_result.awb_result.white_balance_gain[0];
ctx->result->wb_ggain = isp_result.awb_result.white_balance_gain[1];
ctx->result->wb_bgain = isp_result.awb_result.white_balance_gain[3];
for (i = 0; i < XMEDIA_SENSOR_CCM_MATRIX_SIZE; i++) {
if (isp_result.awb_result.color_matrix[i] < 0) {
ctx->result->ccm[i] = CCM_MINUS_PARAM_TH - isp_result.awb_result.color_matrix[i];
} else {
ctx->result->ccm[i] = isp_result.awb_result.color_matrix[i];
}
}
ctx->lib_info->sensor_info.isp_func.pfn_sensor_get_reg_info(ctx->lib_info->sensor_info.dev_id, &reg_info);
ret = hal_isp_update(pipe, &isp_result, &reg_info);
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_update failed!\n");
return ret;
}
#if 0
puts("debug dudu r");
puthex(ctx->result->wb_rgain);
puts(" g");
puthex(ctx->result->wb_ggain);
puts(" b");
puthex(ctx->result->wb_bgain);
puts("\n");
puts("isp process frame count [");
putdec(isp_stat.ae_stat.frame_cnt);
puts("]\n");
#endif
#if ISP_COST_TIME_DEBUG
end = isp_get_time_stamp();
puts("isp process cost time: ");
putdec(end - start);
puts(" us\n");
#endif
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_isp_config(xmedia_u32 pipe)
{
xmedia_s32 ret;
#if ISP_COST_TIME_DEBUG
xmedia_u32 start, end;
start = isp_get_time_stamp();
#endif
if (pipe >= ISP_PIPE_MAX_NUM) {
puts("isp invalid param!\n");
return XMEDIA_ERRCODE_INVALID_PARAM;
}
ret = hal_isp_config(pipe);
if (ret != XMEDIA_SUCCESS) {
puts("isp hal_isp_config failed!\n");
return ret;
}
#if ISP_COST_TIME_DEBUG
end = isp_get_time_stamp();
puts("isp config cost time: ");
putdec(end - start);
puts(" us\n");
#endif
return XMEDIA_SUCCESS;
}
+241
View File
@@ -0,0 +1,241 @@
#include "stdio.h"
#include "defines.h"
#include "interrupt.h"
#include "drv_vi.h"
#include "drv_isp.h"
#include "hal_vi.h"
#include <timer.h>
#define VICAP_IRQ_DEBUG 0
#define VIPROC_IRQ_DEBUG 0
static xmedia_bool vi_vicap_is_report_int(xmedia_u32 fe_id, xmedia_u32 int_status)
{
xmedia_u32 fe_int_mask[VI_MAX_PHY_PIPE_NUM] = { 0x1 << 5, 0x1 << 6, 0x1 << 7, 0x1 << 8 };
if (int_status & fe_int_mask[fe_id]) {
return XMEDIA_TRUE;
}
return XMEDIA_FALSE;
}
static xmedia_void vi_vicap_irq_callback_proc(xmedia_u32 vicap_wch, xmedia_u32 irq_status)
{
if (irq_status & VI_CAP_FRAME_START_INT) {
drv_isp_notifier(vicap_wch, ISP_IRQ_TYPE_FE_FRAME_START);
}
if (irq_status & VI_CAP_FRAME_EARLY_INT) {
// vicap reg newer
hal_vi_vicap_reg_newer(vicap_wch);
}
if (irq_status & VI_CAP_FRAME_LOWDELAY_INT) {
}
if (irq_status & VI_CAP_FRAME_END_INT) {
drv_isp_notifier(vicap_wch, ISP_IRQ_TYPE_FE_FRAME_END);
}
if (irq_status & VI_CAP_FRAME_TIMEOUT_INT) {
puts("vicap timeout int!\n");
}
if (irq_status & VI_CAP_FRAME_ERR_INT) {
puthex(irq_status);
puts("vicap err int!\n");
}
}
ATTRIBUTE_ISR xmedia_void vi_vicap_irq_route(xmedia_void)
{
xmedia_s32 vicap_wch;
xmedia_u32 vicap_int_status;
xmedia_u32 vicap_int_mask;
xmedia_u32 irq_status;
vicap_int_status = hal_vi_vicap_get_top_int_status(0);
vicap_int_mask = hal_vi_vicap_get_top_int_mask(0);
vicap_int_status &= (~vicap_int_mask);
for (vicap_wch = VI_MAX_PHY_PIPE_NUM - 1; vicap_wch >= 0; vicap_wch--) {
if (vi_vicap_is_report_int(vicap_wch, vicap_int_status) == XMEDIA_FALSE) {
continue;
}
irq_status = hal_vi_vicap_get_chn_int_status(vicap_wch);
hal_vi_vicap_clear_int(vicap_wch, irq_status);
#if VICAP_IRQ_DEBUG
puts("vicap irq_status 0x");
puthex(irq_status);
puts("\n");
#endif
vi_vicap_irq_callback_proc(vicap_wch, irq_status);
}
}
static xmedia_void vi_viproc_irq_callback_proc(xmedia_u32 pipe, xmedia_u32 irq_status)
{
if (irq_status & VI_PROC_FRAME_START_INT) {
}
if (irq_status & VI_PROC_FRAME_EARLY_INT) {
drv_isp_config(pipe); // 配置isp be算法寄存器
hal_vi_viproc_reg_start(0);
}
if (irq_status & VI_PROC_FRAME_END_INT || irq_status & VI_PROC_FRAME_LIST_INT) {
drv_isp_notifier(pipe, ISP_IRQ_TYPE_BE_FRAME_END);
}
if (irq_status & VI_PROC_LOWDELAY_INT) {
}
if (irq_status & VI_PROC_FRAME_ERR_INT) {
puts("viproc err int!\n");
}
if (irq_status & VI_PROC_FRAME_TIMEOUT_INT) {
puts("viproc timeout int!\n");
}
if (irq_status & VI_PROC_FRAME_ERR_IGNORE_INT) {
puts("viproc err ignore int!\n");
}
}
ATTRIBUTE_ISR xmedia_void vi_viproc_irq_route(xmedia_void)
{
xmedia_u32 pipe = 0; // 对外暂时仅支持pipe 0
xmedia_u32 cl_irq_status;
xmedia_u32 irq_status;
xmedia_u32 irq_mask;
xmedia_u32 early_mask;
irq_status = hal_viproc_get_reg_public_int_status(0); // viproc irq status
irq_mask = hal_viproc_get_reg_public_int_mask(0); // irq mask
early_mask = hal_viproc_common_get_reg_early_mask(0); // early irq mask
cl_irq_status = irq_status;
irq_status &= (~(irq_mask | early_mask));
hal_viproc_clr_reg_int(0, cl_irq_status); // clear int
#if VIPROC_IRQ_DEBUG
puts("viproc irq_status 0x");
puthex(irq_status);
puts("\n");
#endif
vi_viproc_irq_callback_proc(pipe, irq_status);
}
STAGE1_FUNC xmedia_void drv_mipi_init(xmedia_void)
{
hal_mipi_init();
}
STAGE1_FUNC xmedia_s32 drv_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
return hal_mipi_enable(dev, dev_config);
}
xmedia_s32 drv_vi_init(xmedia_void)
{
xmedia_s32 ret;
xmedia_u32 vicap_irq_num;
xmedia_u32 viproc_irq_num;
// 注册vicap中断、viproc中断
vicap_irq_num = hal_vi_get_vicap_irq_num(0);
viproc_irq_num = hal_vi_get_viproc_irq_num(0);
ret = drv_irq_register(vicap_irq_num, vi_vicap_irq_route);
if (ret < 0) {
puts("Fail to register vicap irq!\n");
return ret;
}
ret = drv_irq_register(viproc_irq_num, vi_viproc_irq_route);
if (ret < 0) {
puts("Fail to register viproc irq!\n");
drv_irq_unregister(vicap_irq_num);
return ret;
}
hal_vi_init();
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_exit(xmedia_void)
{
xmedia_u32 vicap_irq_num;
xmedia_u32 viproc_irq_num;
// 反注册中断
vicap_irq_num = hal_vi_get_vicap_irq_num(0);
viproc_irq_num = hal_vi_get_viproc_irq_num(0);
drv_irq_unregister(vicap_irq_num);
drv_irq_unregister(viproc_irq_num);
hal_vi_exit();
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_enable_dev(xmedia_s32 dev)
{
return hal_vi_enable_dev(dev);
}
xmedia_s32 drv_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
hal_vi_disable_dev(dev, dev_config);
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 pipe)
{
return hal_vi_set_dev_bind_pipe(dev, pipe);
}
xmedia_s32 drv_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 pipe)
{
hal_vi_set_dev_unbind_pipe(dev, pipe);
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_start_pipe(xmedia_s32 pipe, xmedia_vi_pipe_config *pipe_config)
{
xmedia_s32 ret;
ret = hal_vi_start_vicap(pipe, pipe_config);
if (ret != XMEDIA_SUCCESS) {
puts("start vicap failed\n");
return ret;
}
// 调用isp update be接口,配置第一帧算法参数
drv_isp_config(pipe);
ret = hal_vi_start_viproc(pipe, pipe_config);
if (ret != XMEDIA_SUCCESS) {
puts("start viproc failed\n");
hal_vi_stop_vicap(pipe);
return ret;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_vi_stop_pipe(xmedia_s32 pipe)
{
hal_vi_stop_viproc(pipe);
hal_vi_stop_vicap(pipe);
return XMEDIA_SUCCESS;
}
+2065
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
#ifndef _HAL_ISP_H_
#define _HAL_ISP_H_
xmedia_void delay(xmedia_u32 us);
xmedia_s32 hal_sensor_reset(xmedia_u32 ch, xmedia_bool enable);
xmedia_s32 hal_sensor_read_mclk(xmedia_u32 ch, xmedia_u32 *clk);
xmedia_s32 hal_sensor_set_mclk(xmedia_u32 ch, xmedia_u32 clk);
xmedia_s32 hal_isp_init(xmedia_u32 pipe, xmedia_isp_config *cfg, xmedia_sensor_black_level *blc);
xmedia_s32 hal_isp_init_expander(xmedia_u32 pipe, const xmedia_isp_expander_attr *attr);
xmedia_s32 hal_isp_stat(xmedia_u32 pipe, xmedia_isp_statistics *stat);
xmedia_s32 hal_isp_update(xmedia_u32 pipe, xmedia_isp_result *result, xmedia_sensor_regs_info *reg_info);
xmedia_s32 hal_isp_format_statistics(xmedia_u32 pipe);
xmedia_s32 hal_isp_config(xmedia_u32 pipe);
xmedia_s32 hal_isp_sync(xmedia_u32 pipe);
#endif
+933
View File
@@ -0,0 +1,933 @@
#include "stdio.h"
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "defines.h"
#include "hal_vi.h"
/*
* 系统控制寄存器,MISC_CTRL81
* BIT [0] :
* 0:MIPI_RX_PHY1连接MIPI_2L_RX0控制器
* 1:MIPI_RX_PHY1连接MIPI_4L_RX0控制器
* BIT [1] :
* 0:MIPI_RX_PHY3连接MIPI_2L_RX1控制器
* 1:MIPI_RX_PHY3连接MIPI_4L_RX1控制器
* */
#define MIPI_MISC_CTRL 0x12028900
#define VIPROC_EXTERNAL_TIMING_EN_ADDR 0x1202899C
#define CRG_REGS_ADDR 0x12010000
#define VICAP_IRQ_NUM 66
#define VIPROC0_IRQ_NUM 63
#define VI_RESET_WAIT_CNT 100
typedef struct {
xmedia_u32 phy0_data_lane0;
xmedia_u32 phy0_data_lane1;
xmedia_u32 phy1_data_lane0;
xmedia_u32 phy1_data_lane1;
xmedia_u32 phy0_clk_sel;
xmedia_u32 phy1_clk_sel;
} mipi_lane_swap_attr;
volatile xmedia_u32 g_vicap_all_reg[VICAP_IP_NUM] = { 0x11000000 };
volatile xmedia_u32 g_viproc_all_reg[VIPROC_IP_NUM] = { 0x11200000 };
STAGE1_GLOBAL volatile xmedia_u32 g_mipi_rx_reg[VI_MIPI_RX_NUM] = { 0x10fe0000, 0x11010000 };
STAGE1_GLOBAL volatile xmedia_u32 g_mipi_phy_reg_addr = 0x12028900;
STAGE1_FUNC static xmedia_u32 vi_read_reg(volatile xmedia_uintptr_t addr)
{
return *(volatile xmedia_u32 *)(addr);
}
STAGE1_FUNC static xmedia_void vi_write_reg(volatile xmedia_uintptr_t addr, xmedia_u32 val)
{
*(volatile xmedia_u32 *)(addr) = val;
}
STAGE1_FUNC xmedia_void vi_reg_write_bit(xmedia_u32 addr, xmedia_u32 value, xmedia_u32 bit_pos)
{
xmedia_u32 t, mask;
mask = 1 << bit_pos;
t = vi_read_reg(addr);
t &= ~mask;
t |= (value << bit_pos) & mask;
vi_write_reg(addr, t);
}
STAGE1_FUNC xmedia_void vi_reg_write_32(xmedia_u32 addr, xmedia_u32 value, xmedia_u32 bit_pos, xmedia_u32 bit_count)
{
xmedia_u32 t;
xmedia_u32 mask;
t = vi_read_reg(addr);
mask = ((1U << bit_count) - 1) << bit_pos;
t &= ~mask;
t |= (value << bit_pos) & mask;
vi_write_reg(addr, t);
}
static xmedia_s32 vi_dev_reset(xmedia_s32 dev, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 wait_cnt = 0;
xmedia_u32 reg;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 4 + dev); // 4 : pt0 offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (8 + dev))) >> (8 + dev); // bit[8:12]: pt0-pt4 reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (8 + dev))) >> (8 + dev); // bit[8:12]: pt0-pt4 reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("dev reset err\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_fe_reset(xmedia_s32 fe_id, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 reg;
xmedia_u32 wait_cnt = 0;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 9 + fe_id); // 9 : fe0 offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (13 + fe_id))) >> (13 + fe_id); // bit[13:20]: fe0-fe7 reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << (13 + fe_id))) >> (13 + fe_id); // bit[13:20]: fe0-fe7 reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("vicap reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_viproc_reset_set(xmedia_u32 proc_id, xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 wait_cnt = 0;
xmedia_u32 reg;
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, reset, 4); // 4 : viproc reset offset
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & 0x80) >> 7; // bit[7]: viproc reset state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & 0x80) >> 7; // bit[7]: viproc reset state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("viproc reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_all_reset(xmedia_bool reset)
{
xmedia_bool reset_state = 0;
xmedia_u32 reg;
xmedia_u32 wait_cnt = 0;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, reset, 17); // [17] : vicap总软复位请求
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << 21)) >> 21; // bit[21]: vicap all state
while (reset_state != reset) {
sleep_us(1);
wait_cnt++;
reg = vi_read_reg(CRG_REGS_ADDR + 0x1e4);
reset_state = (reg & (0x1 << 21)) >> 21; // bit[21]: vicap all state
if (reset_state != reset && wait_cnt > VI_RESET_WAIT_CNT) {
puts("vicap reset failed\n");
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 vi_vicap_clk_reset_init(xmedia_u32 cap_id)
{
xmedia_s32 dev;
xmedia_s32 fe;
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, XMEDIA_TRUE, 0); // enable vicap clk
sleep_us(5); // 等待时钟稳定
if (vi_vicap_all_reset(XMEDIA_FALSE) != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
if (vi_dev_reset(dev, XMEDIA_TRUE) != 0) {
return XMEDIA_FAILURE;
}
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
if (vi_vicap_fe_reset(fe, XMEDIA_TRUE) != 0) {
return XMEDIA_FAILURE;
}
}
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
if (vi_dev_reset(dev, XMEDIA_FALSE) != 0) {
return XMEDIA_FAILURE;
}
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
if (vi_vicap_fe_reset(fe, XMEDIA_FALSE) != 0) {
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}
static xmedia_void vi_vicap_clk_reset_deinit(xmedia_u32 cap_id)
{
xmedia_s32 dev;
xmedia_s32 fe;
for (dev = 0; dev < VI_MAX_DEV_NUM; dev++) {
vi_dev_reset(dev, XMEDIA_TRUE);
}
for (fe = 0; fe < VI_MAX_PHY_PIPE_NUM; fe++) {
vi_vicap_fe_reset(fe, XMEDIA_TRUE);
}
vi_vicap_all_reset(XMEDIA_TRUE);
vi_reg_write_bit(CRG_REGS_ADDR + 0xf4, 0, 0);
}
static xmedia_s32 vi_viproc_clk_reset_init(xmedia_u32 proc_id)
{
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, XMEDIA_TRUE, 0);
sleep_us(5); // 等待时钟稳定
if (vi_viproc_reset_set(proc_id, XMEDIA_FALSE) != 0) {
puts("viproc clk reset false failed\n");
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_void vi_viproc_clk_reset_deinit(xmedia_u32 proc_id)
{
vi_viproc_reset_set(proc_id, XMEDIA_TRUE);
vi_viproc_reset_set(proc_id, XMEDIA_FALSE);
vi_reg_write_bit(CRG_REGS_ADDR + 0xfc, XMEDIA_FALSE, 0);
}
STAGE1_FUNC static xmedia_void mipi_rx_set_misc_sel(xmedia_s32 dev_id, xmedia_vi_mipi_lane_divide_mode mipi_lane_num)
{
volatile xmedia_u32 mipi_misc_reg = MIPI_MISC_CTRL;
if (mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
if (dev_id == 0) {
vi_reg_write_bit(mipi_misc_reg, 1, 0);
} else {
vi_reg_write_bit(mipi_misc_reg, 1, 1);
}
} else {
if (dev_id == 0 || dev_id == 1) {
vi_reg_write_bit(mipi_misc_reg, 0, 0);
} else {
vi_reg_write_bit(mipi_misc_reg, 0, 1);
}
}
}
static xmedia_void mipi_rx_phy_get_lane_swap(xmedia_s32 dev_id, const xmedia_vi_dev_config *dev_config,
mipi_lane_swap_attr *lane_swap_mode)
{
/*
* 默认phy与lane的链接关系:
* mipi0-phy0-data0-lane0
* mipi0-phy0-data1-lane1
* mipi1-phy1-data0-lane2
* mipi1-phy1-data1-lane3
*/
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
lane_swap_mode->phy0_data_lane0 = 0;
lane_swap_mode->phy0_data_lane1 = 1;
lane_swap_mode->phy1_data_lane0 = 2;
lane_swap_mode->phy1_data_lane1 = 3;
lane_swap_mode->phy0_clk_sel = 0;
lane_swap_mode->phy1_clk_sel = 1;
} else {
if (dev_id == 0) {
lane_swap_mode->phy0_data_lane0 = 0;
lane_swap_mode->phy0_data_lane1 = 1;
lane_swap_mode->phy0_clk_sel = 0;
} else { // VI_DEV1
lane_swap_mode->phy1_data_lane0 = 2;
lane_swap_mode->phy1_data_lane1 = 3;
lane_swap_mode->phy1_clk_sel = 0;
}
}
if (dev_config->lane_config.enable != XMEDIA_TRUE) {
return;
}
// 用户任意配置链接关系
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
lane_swap_mode->phy0_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy0_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy1_data_lane0 = dev_config->lane_config.lane_cfg[2];
lane_swap_mode->phy1_data_lane1 = dev_config->lane_config.lane_cfg[3];
lane_swap_mode->phy0_clk_sel = 0;
lane_swap_mode->phy1_clk_sel = 1;
} else {
if (dev_id == 0) {
lane_swap_mode->phy0_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy0_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy0_clk_sel = (lane_swap_mode->phy0_data_lane0 > 1) ? 1 : 0;
} else {
lane_swap_mode->phy1_data_lane0 = dev_config->lane_config.lane_cfg[0];
lane_swap_mode->phy1_data_lane1 = dev_config->lane_config.lane_cfg[1];
lane_swap_mode->phy1_clk_sel = (lane_swap_mode->phy1_data_lane0 > 1) ? 0 : 1;
}
}
}
static xmedia_void mipi_rx_phy_lane_swap(xmedia_s32 dev_id, xmedia_vi_mipi_lane_divide_mode lane_mode,
mipi_lane_swap_attr *lane_swap)
{
volatile xmedia_u32 mipi_phy_addr = g_mipi_phy_reg_addr;
if (lane_mode == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane1, 2, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane1, 6, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
} else if (lane_mode == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane1, 2, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
} else { // VI_DEV1
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane1, 6, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
}
} else {
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_data_lane0, 0, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy0_clk_sel, 8, 1);
} else { // VI_DEV1
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_data_lane0, 4, 2);
vi_reg_write_32(mipi_phy_addr + 0xac, lane_swap->phy1_clk_sel, 9, 1);
}
}
}
STAGE1_FUNC static xmedia_void mipi_rx_phy_init(xmedia_s32 dev_id, xmedia_u32 mipi_rate,
xmedia_vi_mipi_lane_divide_mode mipi_lane_num,
mipi_lane_swap_attr *lane_swap)
{
volatile xmedia_u32 mipi_phy_addr = g_mipi_phy_reg_addr;
xmedia_u32 data_rate;
xmedia_u32 td_term_en_max;
xmedia_u32 td_term_en;
xmedia_u32 ths_settle_max;
xmedia_u32 ths_settle;
xmedia_u32 tclk_term_en_max;
xmedia_u32 tclk_term_en;
xmedia_u32 tclk_settle_max;
xmedia_u32 tclk_settle;
xmedia_u32 tx_clk_esc = 24; // 24MHz 晶振配置 (T-tx_clk_esc = 41.7 ns)
if (mipi_rate == 0) {
puts("mipi_rate invalid");
puts("\n");
}
if (mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(mipi_phy_addr, 1, 0); // mipirxphy_sel
} else {
vi_reg_write_bit(mipi_phy_addr, 0, 0); // mipirxphy_sel
}
mipi_rx_phy_lane_swap(dev_id, mipi_lane_num, lane_swap);
data_rate = mipi_rate;
td_term_en_max = 35 + 4000 / data_rate;
td_term_en = td_term_en_max * data_rate / 2000 - 1;
ths_settle_max = 145 + 10 * 1000 / data_rate;
ths_settle = (ths_settle_max - td_term_en * 2000 / data_rate) * data_rate / 2000 - 1;
tclk_term_en_max = 38;
tclk_term_en = (tx_clk_esc * tclk_term_en_max) / 1000;
tclk_settle_max = 300;
tclk_settle = (tclk_settle_max - tclk_term_en * 1000 / tx_clk_esc) * tx_clk_esc / 1000 - 1;
if (dev_id == 0) {
vi_reg_write_32(mipi_phy_addr + 0xb4, td_term_en, 24, 8); // time_hs_term_en
vi_reg_write_32(mipi_phy_addr + 0xb4, ths_settle, 16, 8); // time_hs_settle
vi_reg_write_32(mipi_phy_addr + 0xb4, tclk_term_en, 8, 8); // time_ck_term_en
vi_reg_write_32(mipi_phy_addr + 0xb4, tclk_settle, 0, 8); // time_ck_settle
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 0); // cr_csi_en
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 1); // dl0_enable
vi_reg_write_bit(mipi_phy_addr + 0xb0, XMEDIA_TRUE, 2); // dl1_enable
} else if (dev_id == 1) {
vi_reg_write_32(mipi_phy_addr + 0xd4, td_term_en, 24, 8); // time_hs_term_en
vi_reg_write_32(mipi_phy_addr + 0xd4, ths_settle, 16, 8); // time_hs_settle
vi_reg_write_32(mipi_phy_addr + 0xd4, tclk_term_en, 8, 8); // time_ck_term_en
vi_reg_write_32(mipi_phy_addr + 0xd4, tclk_settle, 0, 8); // time_ck_settle
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 0); // cr_csi_en
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 1); // dl0_enable
vi_reg_write_bit(mipi_phy_addr + 0xd0, XMEDIA_TRUE, 2); // dl1_enable
} else {
puts("mipi phy num err, dev_id ");
putdec(dev_id);
puts("\n");
}
}
STAGE1_GLOBAL static xmedia_u32 ret_mipi_date_type[10] = { 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x27, 0x18, 0x1a, 0x1e };
STAGE1_FUNC xmedia_u32 mipi_rx_get_data_type(xmedia_intf_mipi_csi_data_type data_type)
{
return ret_mipi_date_type[data_type];
}
STAGE1_FUNC xmedia_void mipi_rx_set_ipi_reg(xmedia_s32 dev_id, xmedia_intf_mipi_csi_data_type data_type)
{
volatile unsigned int mipi_rx_addr = g_mipi_rx_reg[dev_id];
xmedia_u32 ipi_data_type;
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 24); // ipi enable
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 16); // ipi_cut_through
// ipi_color_com
if (data_type <= XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_16BIT) {
vi_reg_write_bit(mipi_rx_addr + 0x80, 1, 8);
} else {
vi_reg_write_bit(mipi_rx_addr + 0x80, 0, 8);
}
vi_reg_write_32(mipi_rx_addr + 0x84, 0, 0, 2); // ipi vc id
ipi_data_type = mipi_rx_get_data_type(data_type);
vi_reg_write_32(mipi_rx_addr + 0x88, ipi_data_type, 0, 6); // ipi data type
vi_reg_write_bit(mipi_rx_addr + 0x88, 1, 8); // embedded_data[A]
vi_reg_write_bit(mipi_rx_addr + 0x8c, 1, 8); // ipi mem auto flush
vi_reg_write_32(mipi_rx_addr + 0x90, 0xa, 0, 12); // hsa
vi_reg_write_32(mipi_rx_addr + 0x94, 0xa, 0, 12); // hbp
vi_reg_write_32(mipi_rx_addr + 0x98, 0xa, 0, 12); // hsd
vi_reg_write_32(mipi_rx_addr + 0x9c, 0x898, 0, 15); // hline_time
vi_reg_write_bit(mipi_rx_addr + 0xa0, 1, 0); // soft reset
// advanced feature
vi_reg_write_bit(mipi_rx_addr + 0xac, 0, 0);
vi_reg_write_32(mipi_rx_addr + 0xac, 0, 8, 6);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 16);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 17);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 18);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 19);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 20);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 21);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 22);
vi_reg_write_bit(mipi_rx_addr + 0xac, 1, 24);
}
xmedia_u32 vi_get_bit_width(xmedia_video_data_width data_width)
{
xmedia_u32 bit_width;
switch (data_width) {
case XMEDIA_VIDEO_DATA_WIDTH_8:
bit_width = 8;
break;
case XMEDIA_VIDEO_DATA_WIDTH_10:
bit_width = 10;
break;
case XMEDIA_VIDEO_DATA_WIDTH_12:
bit_width = 12;
break;
case XMEDIA_VIDEO_DATA_WIDTH_14:
bit_width = 14;
break;
case XMEDIA_VIDEO_DATA_WIDTH_16:
bit_width = 16;
break;
default:
bit_width = 16;
break;
}
return bit_width;
}
xmedia_u32 vi_viproc_get_bit_deepth(xmedia_video_data_width bit_width, xmedia_video_wdr_mode wdr_mode)
{
if (wdr_mode == XMEDIA_VIDEO_WDR_MODE_NONE) {
return VI_PACK_12BIT;
} else if (wdr_mode == XMEDIA_VIDEO_WDR_MODE_BUILT_IN) {
if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_8) {
return VI_PACK_8BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_10) {
return VI_PACK_10BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_12) {
return VI_PACK_12BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_14) {
return VI_PACK_14BIT;
} else if (bit_width == XMEDIA_VIDEO_DATA_WIDTH_16) {
return VI_PACK_16BIT;
} else {
puts("viproc built-in wdr mode not support bit_width ");
putdec(bit_width);
puts("\n");
return VI_PACK_12BIT;
}
} else {
puts("viproc not support wdr_mode ");
putdec(wdr_mode);
puts("\n");
return VI_PACK_12BIT;
}
}
xmedia_void hal_vi_vicap_reg_newer(xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000 + 0x48), 1, 0);
}
xmedia_void hal_vi_vicap_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
xmedia_u32 bit_width;
// input_size
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x4), pipe_config->width, 0, 14);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x4), pipe_config->height, 16, 14);
// bit_width
bit_width = vi_get_bit_width(pipe_config->bit_width);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x28), bit_width, 16, 6);
// output_size
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x2c), pipe_config->width, 0, 14);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x2c), pipe_config->height, 16, 14);
// vicap reg newer
hal_vi_vicap_reg_newer(fe_id);
// todo offline set_output_memory
if (pipe_config->vi_work_mode == 1) {
}
}
xmedia_u32 hal_vi_vicap_get_top_int_status(xmedia_u32 vicap_id)
{
xmedia_u32 top_int_status;
xmedia_u32 vicap_addr = g_vicap_all_reg[vicap_id];
top_int_status = vi_read_reg(vicap_addr + 0x10);
return top_int_status;
}
xmedia_u32 hal_vi_vicap_get_top_int_mask(xmedia_u32 vicap_id)
{
xmedia_u32 top_int_mask;
xmedia_u32 vicap_addr = g_vicap_all_reg[vicap_id];
top_int_mask = vi_read_reg(vicap_addr + 0x14);
return top_int_mask;
}
xmedia_u32 hal_vi_vicap_get_chn_int_status(xmedia_s32 fe_id)
{
xmedia_u32 irq_status;
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
irq_status = vi_read_reg(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40));
return irq_status;
}
xmedia_void hal_vi_vicap_clear_int(xmedia_s32 fe_id, xmedia_u32 mask)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_write_reg(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), mask); // clear int
}
xmedia_s32 hal_vi_get_vicap_irq_num(xmedia_u32 vicap_id)
{
return VICAP_IRQ_NUM;
}
xmedia_s32 hal_vi_get_viproc_irq_num(xmedia_u32 viproc_id)
{
return VIPROC0_IRQ_NUM;
}
xmedia_u32 hal_viproc_get_reg_public_int_status(xmedia_u32 viproc_id)
{
xmedia_u32 int_status;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_status = vi_read_reg(viproc_addr + 0x48);
return int_status;
}
xmedia_u32 hal_viproc_get_reg_public_int_mask(xmedia_u32 viproc_id)
{
xmedia_u32 int_mask;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_mask = vi_read_reg(viproc_addr + 0x2c);
return int_mask;
}
xmedia_u32 hal_viproc_common_get_reg_early_mask(xmedia_u32 viproc_id)
{
xmedia_u32 int_mask;
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
int_mask = vi_read_reg(viproc_addr + 0x1e8);
return int_mask;
}
xmedia_void hal_viproc_clr_reg_int(xmedia_u32 viproc_id, xmedia_u32 mask)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
vi_write_reg(viproc_addr + 0x48, mask);
}
STAGE1_FUNC xmedia_void hal_mipi_init(xmedia_void)
{
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 0, 3); // bit[0:2]: mipi_rx_clk_sel
}
STAGE1_FUNC xmedia_s32 hal_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
xmedia_u32 mipi_lane_num = 0;
xmedia_u32 mipi_rx_addr = g_mipi_rx_reg[dev];
xmedia_u32 sys_config_addr = CRG_REGS_ADDR + 0xf8;
mipi_lane_swap_attr lane_swap_mode = { 0 };
// mipi_rx mipi_phy clk enable
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, dev); // mipi_rx_cken
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, 3); // mipi_rx0_4line_cken
}
vi_reg_write_bit(sys_config_addr, XMEDIA_TRUE, 9); // mipi_phy0_cken
// 延时5 us,等待时钟稳定
sleep_us(5);
// mipi_rx复位
vi_reg_write_bit(mipi_rx_addr + 0x8, XMEDIA_FALSE, 0);
sleep_us(5);
vi_reg_write_bit(mipi_rx_addr + 0x8, XMEDIA_TRUE, 0);
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE) {
mipi_lane_num = 0x0;
} else if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
mipi_lane_num = 0x1;
} else if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_lane_num = 0x3;
} else {
// mipi_lane错误参数
puts("vi mipi lane is invalid\n");
}
vi_reg_write_32(mipi_rx_addr + 0x4, mipi_lane_num, 0, 3); // mipi_lane
vi_reg_write_bit(mipi_rx_addr + 0x44, 1, 0); // mipi0_dphy_rstz
vi_reg_write_bit(mipi_rx_addr + 0x40, 1, 0); // mipi0_phy_shutdownz
mipi_rx_set_misc_sel(dev, dev_config->mipi_lane_num);
mipi_rx_phy_get_lane_swap(dev, dev_config, &lane_swap_mode);
mipi_rx_phy_init(dev, dev_config->mipi_rate, dev_config->mipi_lane_num, &lane_swap_mode);
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_rx_phy_init(dev + 1, dev_config->mipi_rate, dev_config->mipi_lane_num, &lane_swap_mode);
}
sleep_us(5);
mipi_rx_set_ipi_reg(dev, dev_config->data_type); // ipi cfg, todo:暂不考虑wdr
vi_reg_write_32(mipi_rx_addr + 0x640, 0, 0, 3); // hdr_data_mode,0:VC
vi_reg_write_32(mipi_rx_addr + 0x654, 0x142, 0, 16); // rft_speeder
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_init(xmedia_void)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// 初始化mipi_rx、vicap、viproc时钟
// vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 0, 3); // bit[0:2]: mipi_rx_clk_sel
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 3, 3); // bit[3:5]: vicap_clk_sel
vi_reg_write_32(CRG_REGS_ADDR + 0xa0, 0, 6, 3); // bit[6:8]: viproc_clk_sel
// vicap时钟使能,dev、fe复位
vi_vicap_clk_reset_init(0);
// viproc时钟使能、复位,init开启时钟,isp_init需要配置viproc算法寄存器
vi_viproc_clk_reset_init(0);
// vicap viproc outstanding
vi_reg_write_32(vicap_addr + 0x74, 0x88, 0, 9);
vi_reg_write_32(viproc_addr + 0x10, 0x10, 8, 5); // wr outstanding
vi_reg_write_32(viproc_addr + 0x10, 0x20, 16, 6); // rd outstanding
// 屏蔽中断
vi_reg_write_32(vicap_addr + 0x14, 0x7fffff, 0, 23); // top mask
}
xmedia_void hal_vi_exit(xmedia_void)
{
// viproc时钟去使能,dev、fe复位
// vi_viproc_clk_reset_deinit(0);
// vicap时钟去使能,dev、fe复位
vi_vicap_clk_reset_deinit(0);
}
xmedia_s32 hal_vi_enable_dev(xmedia_s32 dev)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
// pt intf modetodo :其他接口待适配
if (dev == 0) {
vi_reg_write_32(vicap_addr + 0xc, 0, 0, 2);
} else if (dev == 1) {
vi_reg_write_32(vicap_addr + 0xc, 0, 2, 2);
} else if (dev == 2) {
vi_reg_write_32(vicap_addr + 0xc, 0, 4, 3);
} else {
puts("dev_id is err ");
putdec(dev);
puts("\n");
}
// enable pt
vi_reg_write_bit(vicap_addr, XMEDIA_TRUE, dev);
if (dev < 2) {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 4); // debug_en
} else {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_TRUE, 0); // pt_timing_en
}
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
#if 0
xmedia_u32 mipi_rx_addr = g_mipi_rx_reg[dev];
xmedia_u32 sys_config_addr = CRG_REGS_ADDR + 0xf8;
vi_reg_write_bit(mipi_rx_addr + 0x44, 0, 0); //mipi0_dphy_rstz
vi_reg_write_bit(mipi_rx_addr + 0x40, 0, 0); //mipi0_phy_shutdownz
// mipi_rx mipi_phy clk disable
vi_reg_write_bit(sys_config_addr, 0, dev); // diable mipi_rx clk
vi_reg_write_bit(sys_config_addr, 0, 9 + dev); // diable mipi_rx phy clk
if (dev_config->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
vi_reg_write_bit(sys_config_addr, 0, 9 + dev + 1);
}
#endif
// disable pt
vi_reg_write_bit(vicap_addr, XMEDIA_FALSE, dev);
if (dev < 2) {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 4); // debug_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 2); // ck_dyn_gt_en
} else {
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000), XMEDIA_FALSE, 0); // pt_timing_en
vi_reg_write_bit(vicap_addr + ((dev + 1) * 0x1000) + 0x2c, XMEDIA_FALSE, 0); // ck_dyn_gt_en
}
}
xmedia_s32 hal_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_32(vicap_addr + 0x4, dev, (fe_id * 3), 3);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_reg_write_32(vicap_addr + 0x4, 0, (fe_id * 3), 3);
}
xmedia_s32 hal_vi_start_vicap(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
vi_vicap_fe_reset(fe_id, XMEDIA_FALSE);
// 打开对应fe上报中断开关、中断掩码
vi_reg_write_bit(vicap_addr + 0x14, 0, fe_id + 5);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x3c), 0x6, 0, 16);
// 在线离线工作模式
if (pipe_config->vi_work_mode == 0) {
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000), XMEDIA_TRUE, 0); // online_en
vi_reg_write_bit(VIPROC_EXTERNAL_TIMING_EN_ADDR, XMEDIA_TRUE, 1); // viproc_external_timing_en
} else {
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000), 0, 0);
vi_reg_write_bit(VIPROC_EXTERNAL_TIMING_EN_ADDR, XMEDIA_FALSE, 1);
}
// 设置early行号、early位置
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x1c), 1, 0, 2);
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x1c), (pipe_config->height * 4 / 5), 8, 13);
// clear_int
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), 0xffff, 0, 16);
hal_vi_vicap_online_config(fe_id, pipe_config);
// enable fe
vi_reg_write_bit(vicap_addr, XMEDIA_TRUE, fe_id + 5);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_viproc_reg_start(xmedia_u32 viproc_id)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[viproc_id];
vi_reg_write_bit(viproc_addr + 0x14, XMEDIA_TRUE, 0); // ctl_up_finish_enable
vi_reg_write_bit(viproc_addr + 0x14, XMEDIA_TRUE, 4); // filter_up_finish_enable
}
xmedia_void hal_vi_viproc_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 bit_deepth;
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// inch0_path_sel
vi_reg_write_32(viproc_addr + 0x174, 0, 1, 2);
// list_mode_enable false
vi_reg_write_bit(viproc_addr + 0x14, 0, 8);
// early line/location
vi_reg_write_32(viproc_addr + 0x1dc, 1, 4, 2);
vi_reg_write_32(viproc_addr + 0x1e0, (pipe_config->height * 4 / 5), 16, 14);
// inch0_en
vi_reg_write_bit(viproc_addr + 0x174, XMEDIA_TRUE, 0);
// inch0_bit_deepth
bit_deepth = vi_viproc_get_bit_deepth(pipe_config->bit_width, pipe_config->wdr_mode);
vi_reg_write_32(viproc_addr + 0x174, bit_deepth, 16, 5);
// input_data_mode
vi_reg_write_bit(viproc_addr + 0x16c, 0, 3);
// valid_in_width/height
vi_reg_write_32(viproc_addr + 0x190, pipe_config->width, 0, 14);
vi_reg_write_32(viproc_addr + 0x190, pipe_config->height, 16, 14);
// early mask
vi_reg_write_32(viproc_addr + 0x1e8, 0x6, 0, 3);
// todo:node id
}
xmedia_s32 hal_vi_start_viproc(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config)
{
xmedia_u32 viproc_addr = g_viproc_all_reg[0];
// vi_viproc_clk_reset_init(0);
// viproc 中断掩码
vi_reg_write_32(viproc_addr + 0x2c, 0x20, 0, 32);
// viproc clear int
vi_reg_write_32(viproc_addr + 0x48, 0xffffffff, 0, 32);
hal_vi_viproc_online_config(fe_id, pipe_config);
// ctl_up_finish_enable/filter_up_finish_enable
hal_vi_viproc_reg_start(0);
return XMEDIA_SUCCESS;
}
xmedia_void hal_vi_stop_viproc(xmedia_s32 fe_id)
{
vi_viproc_clk_reset_deinit(0);
}
xmedia_void hal_vi_stop_vicap(xmedia_s32 fe_id)
{
xmedia_u32 vicap_addr = g_vicap_all_reg[0];
// disable fe
vi_reg_write_bit(vicap_addr, XMEDIA_FALSE, fe_id + 5);
// ck_dyn_gt_en_enable
vi_reg_write_bit(vicap_addr + ((fe_id + 6) * 0x1000 + 0xa0), XMEDIA_FALSE, 0);
// int none mask
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x3c), 0xffff, 0, 16);
// clear int
vi_reg_write_32(vicap_addr + ((fe_id + 6) * 0x1000 + 0x40), 0xffff, 0, 16);
vi_vicap_fe_reset(fe_id, XMEDIA_TRUE);
vi_vicap_fe_reset(fe_id, XMEDIA_FALSE);
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef __HAL_VI_H_
#define __HAL_VI_H_
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "compile.h"
#define VI_CAP_FRAME_START_INT (0x1 << 6)
#define VI_CAP_FRAME_LOWDELAY_INT (0x1 << 1)
#define VI_CAP_FRAME_EARLY_INT (0x1 << 0)
#define VI_CAP_FRAME_END_INT (0x1 << 7)
#define VI_CAP_FRAME_END_INT_TIMING (0x1 << 11)
#define VI_CAP_FRAME_ERR_INT ((0x1 << 8) | (0x1 << 12) | (0x1 << 3) | (0x1 << 4) | (0x1 << 13))
#define VI_CAP_FRAME_TIMEOUT_INT ((0x1 << 9) | (0x1 << 10))
#define VI_PROC_FRAME_LIST_INT (0x1 << 5)
#define VI_PROC_FRAME_START_INT (0x1 << 3)
#define VI_PROC_FRAME_EARLY_INT (0x1)
#define VI_PROC_LOWDELAY_INT (0x1 << 1)
#define VI_PROC_FRAME_END_INT (0x1 << 4)
#define VI_PROC_FRAME_ERR_INT \
((0x1 << 6) | (0x1 << 7) | (0x1 << 8) | (0x1 << 9) | (0x1 << 13) | (0x1 << 14) | (0x1 << 15) | (0x1 << 16) | \
(0x1 << 17) | (0x1 << 18) | (0x1 << 19) | (0x1 << 20) | (0x1 << 21) | (0x1 << 22) | (0x1 << 27) | (0x1 << 28) | \
(0x1 << 29) | (0x1 << 30) | (0x1 << 31))
#define VI_PROC_FRAME_TIMEOUT_INT ((0x1 << 19) | (0x1 << 20))
#define VI_PROC_FRAME_ERR_IGNORE_INT (0x7 << 10)
#define sleep_us(x) \
do { \
for (xmedia_s32 i = x; i > 0; i--) { \
asm("nop"); \
asm("nop"); \
asm("nop"); \
asm("nop"); \
asm("nop"); \
} \
} while (0)
typedef enum {
VI_PACK_8BIT = 8,
VI_PACK_10BIT = 10,
VI_PACK_12BIT = 12,
VI_PACK_14BIT = 14,
VI_PACK_16BIT = 16,
VI_PACK_MAX,
} vi_pack_bit_width;
xmedia_void hal_vi_vicap_reg_newer(xmedia_s32 fe_id);
xmedia_void hal_vi_vicap_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_u32 hal_vi_vicap_get_top_int_status(xmedia_u32 vicap_id);
xmedia_u32 hal_vi_vicap_get_top_int_mask(xmedia_u32 vicap_id);
xmedia_u32 hal_vi_vicap_get_chn_int_status(xmedia_s32 fe_id);
xmedia_void hal_vi_vicap_clear_int(xmedia_s32 fe_id, xmedia_u32 mask);
xmedia_s32 hal_vi_get_vicap_irq_num(xmedia_u32 vicap_id);
xmedia_s32 hal_vi_get_viproc_irq_num(xmedia_u32 viproc_id);
xmedia_u32 hal_viproc_get_reg_public_int_status(xmedia_u32 viproc_id);
xmedia_u32 hal_viproc_get_reg_public_int_mask(xmedia_u32 viproc_id);
xmedia_u32 hal_viproc_common_get_reg_early_mask(xmedia_u32 viproc_id);
xmedia_void hal_viproc_clr_reg_int(xmedia_u32 viproc_id, xmedia_u32 mask);
xmedia_void hal_vi_init(xmedia_void);
xmedia_void hal_vi_exit(xmedia_void);
xmedia_s32 hal_vi_enable_dev(xmedia_s32 dev);
xmedia_void hal_mipi_init(xmedia_void);
xmedia_s32 hal_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_void hal_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_s32 hal_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 fe_id);
xmedia_void hal_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 fe_id);
xmedia_s32 hal_vi_start_vicap(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_void hal_vi_viproc_online_config(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_void hal_vi_viproc_reg_start(xmedia_u32 viproc_id);
xmedia_s32 hal_vi_start_viproc(xmedia_s32 fe_id, xmedia_vi_pipe_config *pipe_config);
xmedia_void hal_vi_stop_viproc(xmedia_s32 fe_id);
xmedia_void hal_vi_stop_vicap(xmedia_s32 fe_id);
#endif
+65
View File
@@ -0,0 +1,65 @@
#ifndef _ISP_DEF_H_
#define _ISP_DEF_H_
#include "compile.h"
#define ISP_SUPPORT_PIPE_NUM 1
#if CONFIG_MEDIA_PIPE_NUM > ISP_SUPPORT_PIPE_NUM
#error "NOT supportted CONFIG_MEDIA_PIPE_NUM > 1.\n"
#endif
#define ISP_PIPE_MAX_NUM CONFIG_MEDIA_PIPE_NUM
#define ISP_COST_TIME_DEBUG 0
#define ISP_COUNT_SIZE_DEBUG 0
typedef struct {
xmedia_u32 frame_cnt;
xmedia_isp_awb_stat_global awb_stat_global;
// xmedia_isp_awb_stat_local_avg_r awb_stat_local_avg_r;
// xmedia_isp_awb_stat_local_avg_g awb_stat_local_avg_g;
// xmedia_isp_awb_stat_local_avg_b awb_stat_local_avg_b;
// xmedia_isp_awb_stat_local_valid_count stat_local_valid_count;
xmedia_u32 *awb_zone_avg_r;
xmedia_u32 *awb_zone_avg_g;
xmedia_u32 *awb_zone_avg_b;
xmedia_u32 *awb_zone_valid_count;
xmedia_u8 awb_gain_switch;
xmedia_u8 awb_stat_switch;
xmedia_u32 wdr_wb_gain[XMEDIA_ISP_BAYER_PATTERN_NUM];
xmedia_u8 awb_zone_row_num;
xmedia_u8 awb_zone_col_num;
xmedia_u16 awb_width;
xmedia_u16 awb_height;
} xmedia_isp_awb_stat;
typedef xmedia_isp_be_ae_stat_hist xmedia_isp_ae_stat_hist;
typedef xmedia_isp_be_ae_stat_global_avg xmedia_isp_ae_stat_global_avg;
typedef xmedia_isp_be_ae_stat_zone_avg xmedia_isp_ae_stat_zone_avg;
typedef struct {
xmedia_u64 frame_cnt;
// xmedia_u8 ae_zone_row_num;
// xmedia_u8 ae_zone_col_num;
xmedia_isp_ae_stat_hist ae_stat_hist;
xmedia_isp_ae_stat_global_avg ae_stat_global_avg;
// xmedia_isp_ae_stat_zone_avg ae_stat_zone_avg;
} xmedia_isp_ae_stat;
typedef struct{
xmedia_isp_ae_stat ae_stat;
xmedia_isp_awb_stat awb_stat;
}xmedia_isp_statistics;
typedef struct{
xmedia_isp_ae_result ae_result;
xmedia_isp_awb_result awb_result;
}xmedia_isp_result;
#endif
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/common.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/defines.h
+34
View File
@@ -0,0 +1,34 @@
#ifndef _DRV_ISP_H_
#define _DRV_ISP_H_
#include "xmedia_isp.h"
typedef enum {
ISP_IRQ_TYPE_PT_FRAME_START,
ISP_IRQ_TYPE_PT_FRAME_END,
ISP_IRQ_TYPE_FE_FRAME_START,
ISP_IRQ_TYPE_FE_FRAME_END,
ISP_IRQ_TYPE_BE_FRAME_START,
ISP_IRQ_TYPE_BE_FRAME_END,
ISP_IRQ_TYPE_MAX,
} isp_irq_type;
xmedia_s32 drv_sensor_init(xmedia_u32 pipe, xmedia_sensor_config *cfg);
xmedia_s32 drv_sensor_exit(xmedia_u32 pipe);
xmedia_s32 drv_sensor_resume(xmedia_u32 pipe);
xmedia_s32 drv_sensor_start(xmedia_u32 pipe);
xmedia_s32 drv_sensor_stop(xmedia_u32 pipe);
xmedia_s32 drv_sensor_set_mipi_lanes(xmedia_u32 pipe, const xmedia_sensor_mipi_lanes mipi_lanes);
xmedia_s32 drv_sensor_set_attr(xmedia_u32 pipe, const xmedia_sensor_attr *sns_attr);
xmedia_s32 drv_sensor_set_init_param(xmedia_u32 pipe, const xmedia_sensor_init_param *init_param);
xmedia_s32 drv_isp_init(xmedia_u32 pipe, xmedia_isp_config *cfg);
xmedia_s32 drv_isp_exit(xmedia_u32 pipe);
xmedia_s32 drv_isp_start(xmedia_u32 pipe);
xmedia_s32 drv_isp_stop(xmedia_u32 pipe);
xmedia_s32 drv_isp_notifier(xmedia_u32 pipe, isp_irq_type irq_type);
xmedia_s32 drv_isp_process(xmedia_u32 pipe);
xmedia_s32 drv_isp_config(xmedia_u32 pipe);
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef __DRV_VI_H_
#define __DRV_VI_H_
#include "xmedia_type.h"
#include "xmedia_vi.h"
#include "compile.h"
xmedia_s32 drv_vi_init(xmedia_void);
xmedia_s32 drv_vi_exit(xmedia_void);
xmedia_void drv_mipi_init(xmedia_void);
xmedia_s32 drv_mipi_enable(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_s32 drv_vi_enable_dev(xmedia_s32 dev);
xmedia_s32 drv_vi_disable_dev(xmedia_s32 dev, xmedia_vi_dev_config *dev_config);
xmedia_s32 drv_vi_set_dev_bind_pipe(xmedia_s32 dev, xmedia_s32 pipe);
xmedia_s32 drv_vi_set_dev_unbind_pipe(xmedia_s32 dev, xmedia_s32 pipe);
xmedia_s32 drv_vi_start_pipe(xmedia_s32 pipe, xmedia_vi_pipe_config *pipe_config);
xmedia_s32 drv_vi_stop_pipe(xmedia_s32 pipe);
#endif
+28
View File
@@ -0,0 +1,28 @@
#ifndef _I2C_DEV_H_
#define _I2C_DEV_H_
#include "xmedia_type.h"
static __inline__ xmedia_s32 i2c_open(xmedia_u8 i2c_dev)
{
return i2c_dev;
}
static __inline__ xmedia_s32 i2c_close(xmedia_s32 fd)
{
return XMEDIA_SUCCESS;
}
static __inline__ xmedia_s32 i2c_set_slave_addr(xmedia_s32 fd, xmedia_u16 slave_addr)
{
return XMEDIA_SUCCESS;
}
xmedia_s32 i2c_read(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u32 read_addr,
xmedia_u8 addr_width, xmedia_u8 *buff, xmedia_u32 length);
xmedia_s32 i2c_write(xmedia_s32 fd, xmedia_u16 slave_addr, xmedia_u8 *buff, xmedia_u32 length);
#endif
+53
View File
@@ -0,0 +1,53 @@
#ifndef __MEDIA_SAMPLE_H__
#define __MEDIA_SAMPLE_H__
#include <stdio.h>
#include "xmedia_type.h"
#include "drv_vi.h"
#include "drv_isp.h"
#include "xmedia_ae.h"
#include "xmedia_awb.h"
#include "i2c_dev.h"
#include "i2c.h"
#include "compile.h"
#define MEDIA_ERROR 1
#define MEDIA_PRINTF 1
#define MEDIA_ERR(fmt...) \
do {\
if(MEDIA_ERROR == 1)\
{\
puts(fmt);\
}\
}while(0)
#define MEDIA_PRT(fmt...) \
do {\
if(MEDIA_PRINTF == 1)\
{\
puts(fmt);\
}\
}while(0)
#define MEDIA_STAGE1_ERR(fmt...) \
do {\
if(MEDIA_ERROR == 1)\
{\
puts(STAGE1_STR(fmt));\
}\
}while(0)
//#define SENSOR_SC485SL_2LANE_SUPPORT 1
//#define SENSOR_SC485SL_4LANE_SUPPORT
#define SENSOR_SC485SL_4LANE_60FPS_SUPPORT
//#define SENSOR_SC235HAI_2LANE_60FPS_SUPPORT
#ifdef CONFIG_MEDIA_SAMPLE_QUICKSTART
xmedia_s32 quickstart_media_preinit(void);
xmedia_s32 quickstart_media_start(void);
#endif
#endif /*__MEDIA_SAMPLE_H__*/
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/sns_comm.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_ae.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_af.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_awb.h
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _XMEDIA_DEBUG_H_
#define _XMEDIA_DEBUG_H_
#define MODULE_DBG_EMERG 0
#define MODULE_DBG_ALERT 1
#define MODULE_DBG_CRIT 2
#define MODULE_DBG_ERR 3
#define MODULE_DBG_WARN 4
#define MODULE_DBG_NOTICE 5
#define MODULE_DBG_INFO 6
#define MODULE_DBG_DEBUG 7
#define XMEDIA_ASSERT(expr)
#define MODULE_TRACE(level, mod_id, fmt...)
#endif
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_errcode.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_intf_common.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_isp.h
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_type.h
+37
View File
@@ -0,0 +1,37 @@
#ifndef __XMEDIA_VI_H__
#define __XMEDIA_VI_H__
#include "xmedia_video_common.h"
#include "xmedia_intf_common.h"
#include "xmedia_type.h"
#define VI_MIPI_DATA_LANE_MAX_NUM 4
typedef enum {
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE = 0,
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE,
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE,
XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_MAX
} xmedia_vi_mipi_lane_divide_mode;
typedef struct {
xmedia_bool enable;
xmedia_u32 lane_cfg[VI_MIPI_DATA_LANE_MAX_NUM];
} xmedia_vi_mipi_lane_config;
typedef struct {
xmedia_vi_mipi_lane_divide_mode mipi_lane_num;
xmedia_intf_mipi_csi_data_type data_type;
xmedia_u32 mipi_rate; // 单位:Mbps
xmedia_vi_mipi_lane_config lane_config;
} xmedia_vi_dev_config;
typedef struct {
xmedia_video_data_width bit_width;
xmedia_u32 width;
xmedia_u32 height;
xmedia_u32 vi_work_mode; // 0:在线 1:离线
xmedia_video_wdr_mode wdr_mode;
} xmedia_vi_pipe_config;
#endif
+1
View File
@@ -0,0 +1 @@
../../../source/gmp/include/xmedia_video_common.h
+1
View File
@@ -0,0 +1 @@
SRCS-$(CONFIG_MEDIA_SAMPLE_QUICKSTART) += media_quickstart.c
+412
View File
@@ -0,0 +1,412 @@
#include <malloc.h>
#include <timer.h>
#include <pwm.h>
#include <common.h>
#include "media_sample.h"
#define MCU_CPU_SYNC_REG 0x1202014c
#define MCU_END_VALUE 0xbeef0002
#define MCU_EXIT_VALUE 0xbeef0003
//#define INFRARED_SUPPORT 1
#ifdef INFRARED_SUPPORT
#define PWM_R_LED_NUM 8
#define PWM_R_LED_REG 0x11980014
#define PWM_R_LED_VALUE 0x401
#define PWM_ENABLE_REG 0x11980018
#endif
#ifdef SENSOR_SC485SL_2LANE_SUPPORT
#define MCU_SENSOR_WIDTH 2560
#define MCU_SENSOR_HEIGHT 1440
#elif defined (SENSOR_SC485SL_4LANE_SUPPORT)
#define MCU_SENSOR_WIDTH 2688
#define MCU_SENSOR_HEIGHT 1520
#elif defined (SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
#define MCU_SENSOR_WIDTH 2560
#define MCU_SENSOR_HEIGHT 1440
#elif defined (SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
#define MCU_SENSOR_WIDTH 1920
#define MCU_SENSOR_HEIGHT 1080
#else
#define MCU_SENSOR_WIDTH 2688
#define MCU_SENSOR_HEIGHT 1520
#endif
STAGE1_FUNC xmedia_void media_comm_write_reg(xmedia_u32 addr, xmedia_u32 value)
{
*((xmedia_u32 *)addr) = value;
}
STAGE1_FUNC xmedia_u32 media_comm_read_reg(xmedia_u32 addr)
{
return *((xmedia_u32 *)addr);
}
xmedia_bool media_comm_get_mcu_end_signal()
{
if (MCU_END_VALUE == media_comm_read_reg(MCU_CPU_SYNC_REG))
{
return XMEDIA_TRUE;
}
return XMEDIA_FALSE;
}
xmedia_void media_comm_set_mcu_exit_signal()
{
media_comm_write_reg(MCU_CPU_SYNC_REG, MCU_EXIT_VALUE);
}
#ifdef INFRARED_SUPPORT
xmedia_s32 media_comm_infrared_init()
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
//set pinmux
media_comm_write_reg(PWM_R_LED_REG, PWM_R_LED_VALUE);
//duty_cycle_us > 0, is smaller the light brighter
s32Ret = pwm_config(PWM_R_LED_NUM, 1, 100);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("pwm config fail \n");
return s32Ret;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 media_comm_set_infrared(LIGHT_STATUS state)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
if (state == LIGHT_STATUS_NIGHT) {
media_comm_write_reg(PWM_ENABLE_REG, 1 << 8);
return pwm_enable(PWM_R_LED_NUM);
} else if (state == LIGHT_STATUS_DAY) {
return pwm_disable(PWM_R_LED_NUM);
}
return s32Ret;
}
xmedia_s32 media_comm_set_ir_cut_state(xmedia_s32 vi_dev, LIGHT_STATUS state)
{
if (vi_dev == 0 || vi_dev == 1) {
media_comm_write_reg(0x112C00BC,0x1400);
media_comm_write_reg(0x112C00C0,0x1400);
if (state == LIGHT_STATUS_DAY) {
media_comm_write_reg(0x120B2400,0x03);
media_comm_write_reg(0x120B200C,0x02);
} else if (state == LIGHT_STATUS_NIGHT){
media_comm_write_reg(0x120B2400,0x03);
media_comm_write_reg(0x120B200C,0x01);
} else {
return XMEDIA_FAILURE;
}
} else if (vi_dev == 2 || vi_dev == 3) {
media_comm_write_reg(0x112C00C8,0x1400);
media_comm_write_reg(0x112C00CC,0x1400);
if (state == LIGHT_STATUS_DAY) {
media_comm_write_reg(0x120B5400,0x03);
media_comm_write_reg(0x120B500C,0x02);
} else if (state == LIGHT_STATUS_NIGHT){
media_comm_write_reg(0x120B5400,0x03);
media_comm_write_reg(0x120B500C,0x01);
} else {
return XMEDIA_FAILURE;
}
}
if (vi_dev == 0 || vi_dev == 1) {
media_comm_write_reg(0x120B2400,0x00);
media_comm_write_reg(0x120B200C,0x00);
} else if (vi_dev == 2 || vi_dev == 3) {
media_comm_write_reg(0x120B5400,0x00);
media_comm_write_reg(0x120B500C,0x00);
}
return XMEDIA_SUCCESS;
}
#endif
STAGE1_FUNC static xmedia_void quickstart_sensor_register(xmedia_s32 isp_pipe)
{
#if defined(SENSOR_SC485SL_2LANE_SUPPORT) || defined(SENSOR_SC485SL_4LANE_SUPPORT) || defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_REGISTER_DRIVER(isp_pipe, sc485sl);
#elif defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_REGISTER_DRIVER(isp_pipe, sc235hai);
#else
#error "should define sensor type first"
#endif
}
STAGE1_FUNC static xmedia_void quickstart_sensor_unregister(xmedia_s32 isp_pipe)
{
#if defined(SENSOR_SC485SL_2LANE_SUPPORT) || defined(SENSOR_SC485SL_4LANE_SUPPORT)
XMEDIA_SENSOR_UNREGISTER_DRIVER(isp_pipe, sc485sl);
#elif defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_UNREGISTER_DRIVER(isp_pipe, sc485sl);
#elif defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
XMEDIA_SENSOR_UNREGISTER_DRIVER(isp_pipe, sc235hai);
#else
#error "should define sensor type first"
#endif
}
STAGE1_FUNC static xmedia_void quickstart_vi_get_devcfg(xmedia_vi_dev_config *vi_dev_cfg)
{
#if defined(SENSOR_SC485SL_2LANE_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_12BIT;
vi_dev_cfg->mipi_rate = 1080;
#elif defined(SENSOR_SC485SL_4LANE_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_12BIT;
vi_dev_cfg->mipi_rate = 1126;
#elif defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_12BIT;
vi_dev_cfg->mipi_rate = 864;
#elif defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
vi_dev_cfg->mipi_lane_num = XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE;
vi_dev_cfg->data_type = XMEDIA_INTF_MIPI_CSI_DATA_TYPE_RAW_10BIT;
vi_dev_cfg->mipi_rate = 756;
#else
#error "should define sensor type first"
#endif
}
STAGE1_FUNC static xmedia_sensor_mipi_lanes quickstart_from_vi_get_mipi_lanes(xmedia_vi_dev_config *vi_dev_cfg)
{
xmedia_sensor_mipi_lanes mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_2L;
if (vi_dev_cfg->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_1_LANE) {
mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_1L;
} else if (vi_dev_cfg->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_2_LANE) {
mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_2L;
} else if (vi_dev_cfg->mipi_lane_num == XMEDIA_VI_MIPI_LANE_DIVIDE_MODE_4_LANE) {
mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_4L;
}
return mipi_lanes;
}
STAGE1_FUNC xmedia_s32 quickstart_media_preinit(void)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
xmedia_s32 isp_pipe = 0;
xmedia_s32 vi_dev = 0;
xmedia_vi_dev_config vi_dev_cfg = {0};
xmedia_sensor_config sensor_cfg = {0};
xmedia_sensor_attr sensor_attr = {0};
xmedia_sensor_mipi_lanes mipi_lanes = XMEDIA_SENSOR_MIPI_LANES_2L;
sensor_cfg.comm_bus.type = XMEDIA_SENSOR_BUS_TYPE_I2C;
sensor_cfg.init_mode = XMEDIA_SENSOR_INIT_MODE_NORMAL;
sensor_cfg.comm_bus.i2c_dev = 0;
sensor_cfg.ctrl_sig.clk_ch = 0;
sensor_cfg.ctrl_sig.rst_ch = 0;
s32Ret = i2c_init(sensor_cfg.comm_bus.i2c_dev);
if (s32Ret != 0) {
MEDIA_STAGE1_ERR("i2c init error\n");
return s32Ret;
}
drv_mipi_init();
quickstart_vi_get_devcfg(&vi_dev_cfg);
s32Ret = drv_mipi_enable(vi_dev, &vi_dev_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("mipi enable fail \n");
return s32Ret;
}
quickstart_sensor_register(isp_pipe);
s32Ret = drv_sensor_init(isp_pipe, &sensor_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("sensor init fail\n");
return s32Ret;
}
mipi_lanes = quickstart_from_vi_get_mipi_lanes(&vi_dev_cfg);
drv_sensor_set_mipi_lanes(isp_pipe, mipi_lanes);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("sensor set mipi lanes fail\n");
return s32Ret;
}
sensor_attr.width = MCU_SENSOR_WIDTH;
sensor_attr.height = MCU_SENSOR_HEIGHT;
sensor_attr.wdr_mode = 0;
s32Ret = drv_sensor_set_attr(isp_pipe, &sensor_attr);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_STAGE1_ERR("sensor set attr fail\n");
return s32Ret;
}
s32Ret = drv_sensor_start(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("sensor start fail\n");
return s32Ret;
}
#ifdef CONFIG_STOPWATCH_SUPPORT
stopwatch_trigger();
#endif
return XMEDIA_SUCCESS;
}
xmedia_s32 quickstart_media_start(void)
{
xmedia_s32 s32Ret = XMEDIA_FAILURE;
xmedia_s32 isp_pipe = 0;
xmedia_s32 vi_dev = 0;
xmedia_s32 vi_pipe = 0;
xmedia_vi_dev_config vi_dev_cfg = {0};
xmedia_vi_pipe_config vi_pipe_cfg = {0};
xmedia_isp_config isp_cfg = {0};
quickstart_vi_get_devcfg(&vi_dev_cfg);
s32Ret = drv_vi_init();
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi init fail \n");
return s32Ret;
}
s32Ret = drv_vi_enable_dev(vi_dev);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi enable dev fail\n");
return s32Ret;
}
s32Ret = drv_vi_set_dev_bind_pipe(vi_dev, vi_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi dev bind pipe fail\n");
return s32Ret;
}
quickstart_vi_get_devcfg(&vi_dev_cfg);
vi_pipe_cfg.bit_width = vi_dev_cfg.data_type;
vi_pipe_cfg.width = MCU_SENSOR_WIDTH;
vi_pipe_cfg.height = MCU_SENSOR_HEIGHT;
vi_pipe_cfg.vi_work_mode = 0;
vi_pipe_cfg.wdr_mode = XMEDIA_VIDEO_WDR_MODE_NONE;
s32Ret = xmedia_awb_register(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("awb init fail\n");
puthex(s32Ret);
return s32Ret;
}
s32Ret = xmedia_ae_register(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("ae init fail\n");
puthex(s32Ret);
return s32Ret;
}
isp_cfg.size.width = MCU_SENSOR_WIDTH;
isp_cfg.size.height = MCU_SENSOR_HEIGHT;
#if defined(SENSOR_SC485SL_4LANE_60FPS_SUPPORT) ||defined(SENSOR_SC235HAI_2LANE_60FPS_SUPPORT)
isp_cfg.fps = 60;
#else
isp_cfg.fps = 30;
#endif
isp_cfg.wdr_mode = XMEDIA_VIDEO_WDR_MODE_NONE;
isp_cfg.bayer_fmt = XMEDIA_VIDEO_BAYER_FMT_BGGR;
isp_cfg.pixel_fmt = XMEDIA_VIDEO_PIXEL_FMT_RAW;
isp_cfg.mode_config.work_mode = XMEDIA_ISP_WORK_MODE_MASTER;
isp_cfg.mode_config.master_mode.blend_stat_enable = XMEDIA_FALSE;
isp_cfg.mode_config.master_mode.slave_num = 0;
s32Ret = drv_isp_init(isp_pipe, &isp_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp init fail\n");
return s32Ret;
}
s32Ret = drv_vi_start_pipe(vi_pipe, &vi_pipe_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi start pipe fail\n");
return s32Ret;
}
s32Ret = drv_isp_start(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp start fail\n");
return s32Ret;
}
while(1)
{
s32Ret = drv_isp_process(isp_pipe);
if (s32Ret == XMEDIA_SUCCESS ) {
if (XMEDIA_TRUE == media_comm_get_mcu_end_signal()){
break;
}
}
}
#ifdef CONFIG_STOPWATCH_SUPPORT
stopwatch_trigger();
#endif
s32Ret = drv_isp_stop(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp stop fail\n");
return s32Ret;
}
s32Ret = drv_vi_stop_pipe(vi_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp stop fail\n");
return s32Ret;
}
s32Ret = drv_isp_exit(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("isp exit fail\n");
return s32Ret;
}
s32Ret = xmedia_ae_unregister(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("ae exit fail\n");
return s32Ret;
}
s32Ret = xmedia_awb_unregister(isp_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("awb exit fail\n");
return s32Ret;
}
quickstart_sensor_unregister(isp_pipe);
s32Ret = drv_vi_set_dev_unbind_pipe(vi_dev, vi_pipe);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi dev unbind pipe fail\n");
return s32Ret;
}
s32Ret = drv_vi_disable_dev(vi_dev, &vi_dev_cfg);
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi disable dev fail\n");
return s32Ret;
}
s32Ret = drv_vi_exit();
if (s32Ret != XMEDIA_SUCCESS) {
MEDIA_ERR("vi exit fail \n");
return s32Ret;
}
media_comm_set_mcu_exit_signal();
return XMEDIA_SUCCESS;
}
+1
View File
@@ -0,0 +1 @@
../../source/gmp/usr/isp/sensor/
+166
View File
@@ -0,0 +1,166 @@
CROSS_COMPILE ?= riscv64-unknown-elf-
O ?= $(shell pwd)/out
ARCH ?= riscv
CONFIG_INC := $(O)/include/autoconf.h
CONFIG_MAKE := $(O)/.makefile
CONFIG_FILE := $(O)/.config
export CONFIG_FILE CONFIG_INC
sinclude $(CONFIG_FILE)
TOPDIR := $(shell pwd)
export TOPDIR
CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
SIZE := $(CROSS_COMPILE)size
STRIP := $(CROSS_COMPILE)strip
OBJDUMP := $(CROSS_COMPILE)objdump
RM := $(shell if [ -x "/bin/rm" ]; then echo /bin/rm; else type -P rm; fi)
LS := $(shell if [ -x "/bin/ls" ]; then echo /bin/ls; else type -P ls; fi)
MCU := mcu
RM := $(RM) -f
export CC AR LD OBJCOPY RM TOPDIR MCU SIZE STRIP LS
include $(TOPDIR)/scripts/Makefile.define
V ?= 0
ifeq ($(V),1)
Q :=
QUIET :=
else
Q := @
QUIET := -s
endif
MKFLAGS := $(QUIET) -f $(TOPDIR)/scripts/Makefile.build
CLFLAGS := $(QUIET) -f $(TOPDIR)/scripts/Makefile.clean
export MKFLAGS CLFLAGS Q QUIET
MKDEP := .mkdep
export MKDEP
ARFLAGS += rcs
LDFLAGS +=
CFLAGS += -fno-builtin -fno-common -ffreestanding -nostdinc \
-I$(shell pwd)/include -I$(O)/include -I$(TOPDIR) -pipe -g -gdwarf-4 -Wall -Werror \
-DCONFIG_$(strip $(call upper, $(ARCH)))_ARCH
GC_ENABLE ?= y
CFLAGS += $(if $(GC_ENABLE),-fdata-sections -ffunction-sections)
CFLAGS += $(shell echo $(CONFIG_CFLAGS))
LDFLAGS += $(shell echo $(CONFIG_LDFLAGS))
ARCH_DIR := $(ARCH)/
CFLAGS += -I$(TOPDIR)/$(ARCH_DIR)include
ASFLAGS += $(CFLAGS) -D__ASSEMBLY__
export ARFLAGS LDFLAGS CFLAGS ASFLAGS
LIB_DIRS := init/ libs/ drivers/ common/
ifdef CONFIG_MEDIA_SUPPORT
MEDIA = $(if $(wildcard $(TOPDIR)/media/Makefile),y,)
endif
LIB_DIRS-stage2 += $(call is_enabled, MEDIA,media/,)
CFLAGS += $(call is_enabled, MEDIA,-I$(TOPDIR)/media/include,)
ifeq ($(strip $(CONFIG_UT_ENABLE)),y)
LIB_DIRS-stage2 += test/
endif
LIBS := $(foreach LIB,$(LIB_DIRS),$(LIB)lib$(LIB:/=).a)
LIBS-stage2 := $(foreach LIB,$(LIB_DIRS-stage2),$(LIB)lib$(LIB:/=).a)
################################################################################
sinclude $(CONFIG_MAKE)
PHONYS += help
help:
@echo "Usage: make [config]"
@echo " make clean"
@echo " make distclean"
@echo " make help"
@echo " make"
@echo " support configs:"
@for ix in $(notdir $(wildcard $(TOPDIR)/configs/*)); do ( \
echo " $${ix}"; \
) done
@echo;
PHONYS += $(MCU).bin
$(MCU).bin: $(MCU).elf
$(call show_cmd,OBJCOPY,$@)
$(Q)$(OBJCOPY) -R .comment --gap-fill=0xff -O binary $(O)/$< $(O)/$@
$(call show_cmd,MCU,$@)
$(Q)$(OBJDUMP) -D $(O)/$(MCU).elf > $(O)/mcu.asm
@echo "Config File: $(CONFIG_PLATFORM)_defconfig"
@echo "Entry Point: $(CONFIG_TEXT_BASE)"
@MSG=$$(cd $(O); $(LS) -gG --time-style=long-iso $@); \
echo "Image Size: $$(echo $${MSG} | awk '{print $$3}') Bytes"; \
echo "Create: $$(echo $${MSG} | awk '{print $$4" "$$5}')"
@echo "Output Path: $(O)"
@echo " Image $(@) is ready"
PHONYS += $(MCU).bin
$(MCU).elf: $(LIBS) $(LIBS-stage2)
$(Q)$(MAKE) $(MKFLAGS) SRCDIR="$(ARCH_DIR)" LIBS="$(LIBS)" LIBS-stage2="$(LIBS-stage2)" O="$(O)/" $(@)
PHONYS += $(LIBS) $(LIBS-stage2)
$(LIBS): $(O)/$(MKDEP) force
@touch init/main.c
$(Q)$(MAKE) $(MKFLAGS) -C $(TOPDIR)/$(@D)/ SRCDIR="$(@D)/" O="$(O)/" $(@F)
$(LIBS-stage2): $(O)/$(MKDEP) force
$(Q)$(MAKE) $(MKFLAGS) -C $(TOPDIR)/$(@D)/ SRCDIR="$(@D)/" O="$(O)/" $(@F)
%: $(TOPDIR)/configs/%
$(call show_cmd,GEN,$(notdir $(CONFIG_MAKE)))
$(call checkdir,$(dir $(CONFIG_MAKE)))
$(Q)(echo "# auto produce, don't modify this ") > $(CONFIG_MAKE)
$(Q)(echo "all: $(MCU).bin";) >> $(CONFIG_MAKE)
$(call show_cmd,GEN,$(notdir $(CONFIG_FILE)))
$(call checkdir,$(dir $(CONFIG_FILE)))
$(Q)cp "$<" "$(CONFIG_FILE)"
$(call show_cmd,GEN,$(notdir $(CONFIG_INC)))
$(call checkdir,$(dir $(CONFIG_INC)))
$(Q)(echo "/* auto produce, don't modify this */") > $(CONFIG_INC)
$(Q)set -e; cat $(CONFIG_FILE) | sed -n -f $(TOPDIR)/scripts/env2inc.sed >> $(CONFIG_INC)
force:;
$(O)/$(MKDEP): $(TOPDIR)/Makefile
@touch $@
PHONYS += clean
clean: $(addsuffix .clean,$(LIBS) $(ARCH_DIR))
$(Q)$(RM) -f $(O)/{$(MCU).bin,$(MCU).elf,$(MCU).map,$(MKDEP)}
$(addsuffix .clean,$(LIBS) $(ARCH_DIR)):
$(call show_cmd,ENTRY,$(TOPDIR)/$(@D))
$(Q)$(MAKE) $(CLFLAGS) SRCDIR="$(@D)/" O="$(O)/" clean
PHONYS += distclean
distclean:
$(Q)$(RM) -rf $(O)
$(Q)$(RM) -rf cscope.files cscope.in.out cscope.out cscope.po.out tags
PHONYS += cscope
cscope:
$(Q)find -name "*.S" -o -name "*.c" -o -name "*.h" -o -name "*.s" >cscope.files
$(Q)cscope -bkq -i ./cscope.files
$(Q)ctags -R
################################################################################
.PHONY: $(PHONYS)
################################################################################
+10
View File
@@ -0,0 +1,10 @@
CFLAGS_start += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
CFLAGS_start += -DSTACK_TOP=$(CONFIG_STACK_TOP)
CFLAGS += -DSTACK_TOP=$(CONFIG_STACK_TOP)
ASFLAGS += -DSTACK_TOP=$(CONFIG_STACK_TOP)
LINKLDS := firmware.lds
START = start.S
TAIL = tail.S
SRCS-y += chip.c
+4
View File
@@ -0,0 +1,4 @@
void reset_cpu(void)
{
}
+45
View File
@@ -0,0 +1,45 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
#include <config.h>
ENTRY(_start)
SECTIONS
{
. = CONFIG_TEXT_BASE;
. = ALIGN(4);
.text : {
. = ALIGN(4);
__text_start = .;
start.o (.text)
*(.text)
__text_end = .;
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
__data_start = .;
*(.data)
__data_end = .;
}
.tail : {
tail.o(.tail)
}
. = ALIGN(4);
.bss : {
__bss_start = .;
*(.bss)
__bss_end = .;
ASSERT(((__bss_end - __bss_start) == 0), "All global and static
variables MUST be initialized with non-zero value!");
}
_end = .;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef __BARRIERS_H__
#define __BARRIERS_H__
#ifndef __ASSEMBLY__
#define ISB asm volatile ("isb sy" : : : "memory")
#define DSB asm volatile ("dsb sy" : : : "memory")
#define DMB asm volatile ("dmb sy" : : : "memory")
#define isb() ISB
#define dsb() DSB
#define dmb() DMB
#endif /* __ASSEMBLY__ */
#endif /* __BARRIERS_H__ */
+24
View File
@@ -0,0 +1,24 @@
#ifndef __ASM_ARM_IO_H
#define __ASM_ARM_IO_H
#include <sys/types.h>
#include <barriers.h>
#define __arch_getl(a) (*(volatile unsigned int *)(a))
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
#define mb() dsb()
#define __iormb() dmb()
#define __iowmb() dmb()
#ifdef REG_IORW_DEBUG
#include <serial.h>
#define writel(v,c) ({ u32 __v = v; __iowmb(); serial_puts("REG W: 0x"); serial_put_hex(c); serial_puts(", 0x"); serial_put_hex(__v); serial_puts("\n"); __arch_putl(__v,c); __v; })
#define readl(c) ({ u32 __v; serial_puts("REG R: 0x"); serial_put_hex(c); __v = __arch_getl(c); __iormb(); serial_puts(", 0x"); serial_put_hex(__v); serial_puts("\n"); __v; })
#else
#define writel(v,c) ({ u32 __v = v; __iowmb(); __arch_putl(__v,c); __v; })
#define readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; })
#endif
#endif /* __ASM_ARM_IO_H */
+113
View File
@@ -0,0 +1,113 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __CHIP_REGS_H__
#define __CHIP_REGS_H__
#define BIT(nr) (1 << (nr))
#define RAM_START_ADRS 0x04010500
#define STACK_TRAINING 0x04018000
#define DDR_DDRT_REG_BASE 0x11330000
#define TIMER0_REG_BASE 0x12000000
#define TIMER1_REG_BASE 0x12000020
#define TIMER2_REG_BASE 0x12001000
#define TIMER3_REG_BASE 0x12001020
#define REG_TIMER_RELOAD 0x0
#define REG_TIMER_VALUE 0x4
#define REG_TIMER_CONTROL 0x8
#define CRG_REG_BASE 0x12010000
#define SYS_CTRL_REG_BASE 0x12020000
#define REG_BASE_SCTL SYS_CTRL_REG_BASE
#define REG_SC_CTRL 0
#define REMAPCLEAR BIT(8)
#define REMAPCLEAR_SHIFT 8
#define TIME0_CLK_SEL BIT(16)
#define TIME0_CLK_SEL_SHIFT 16
#define TIME0_CLK_SEL_3M 0x0
#define TIME0_CLK_SEL_APB 0x1
#define REG_SC_SYSRES 0x8
#define REG_SYSSTAT 0x008C
#define REG_OTP_PO_BIT2 0x88
/* Generic register */
#define REG_SC_DDRT0 0x90
#define REG_SC_DDRT1 0x94
#define REG_SC_DDRT2 0x98
#define REG_SC_DDRT3 0x9c
#define REG_SC_DDRT4 0xa0
#define REG_SC_DDRT5 0xa4
#define REG_SC_DDRT6 0xa8
#define REG_SC_DDRT7 0xac
#define REG_SC_DDRT8 0xb0
#define REG_SC_DDRT9 0xb4
#define REG_SC_DDRT10 0xb8
#define REG_SC_DDRT11 0xbc
#define REG_SC_DDRT12 0xc0
#define REG_SC_DDRT13 0xc4
#define REG_SC_DDRT14 0xc8
#define REG_SC_DDRT15 0xcc
#define REG_SC_SYSBOOT0 0x130
#define REG_SC_SYSBOOT1 0x134
#define REG_SC_SYSBOOT2 0x138
#define REG_SC_SYSBOOT3 0x13c
#define REG_SC_SYSBOOT4 0x140
#define REG_SC_SYSBOOT5 0x144
#define REG_SC_SYSBOOT6 0x148
#define REG_SC_SYSBOOT7 0x14c
#define REG_SC_SYSBOOT8 0x150
#define REG_SC_SYSBOOT9 0x154
#define REG_SC_SYSBOOT10 0x158
#define REG_SC_SYSBOOT11 0x15c
#define REG_SC_SYSBOOT12 0x160
#define REG_SC_SYSBOOT13 0x164
#define REG_SC_SYSBOOT14 0x168
#define REG_SC_SYSBOOT15 0x16c
#define DDRCA_UPDATE (SYS_CTRL_REG_BASE + 0x8034)
#define DDRCA_RANDOM0 (SYS_CTRL_REG_BASE + 0x8600)
#define DDRCA_RANDOM1 (SYS_CTRL_REG_BASE + 0x8604)
#define DDRCA_RANDOM2 (SYS_CTRL_REG_BASE + 0x8608)
#define DDRCA_RANDOM3 (SYS_CTRL_REG_BASE + 0x860c)
#define MISC_REG_BASE 0x12028000
#define DDRC0_REG_BASE 0x11330000
#define UART0_REG_BASE 0x12040000
#define FMC_MEM_BASE 0x14000000
#define DDR_MEM_BASE 0x40000000
#define TIMER0_BASE 0x12000000
#define SERIAL_BASE UART0_REG_BASE
#define UART_PL01x_DR 0x00
#define UART_PL01x_RSR 0x04
#define UART_PL01x_ECR 0x04
#define UART_PL01x_FR 0x18
#define UART_PL01x_FR_TXFE 0x80
#define UART_PL01x_FR_RXFF 0x40
#define UART_PL01x_FR_TXFF 0x20
#define UART_PL01x_FR_RXFE 0x10
#define UART_PL01x_FR_BUSY 0x08
#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
#define START_MAGIC 0x444f574e
#define SUCCESS 0
#define FAILURE -1
#define REG_OTP_PO_BIT0 0x12020080
/* i2c0 reg */
#define REG_I2C_BASE (0x12060000)
/* clk reg control */
#define CRG_I2C (CRG_REG_BASE + 0x1B8)
#define I2C_CKEN BIT(16)
#define I2C_SRST BIT(24)
#endif
+19
View File
@@ -0,0 +1,19 @@
#include <platform.h>
.arm
.globl _start
_start:
push {r4-r11, lr}
bl main
pop {r4-r11, pc}
nop
nop
nop
nop
nop
nop
nop
nop
b . /* bug here */
+6
View File
@@ -0,0 +1,6 @@
#include <platform.h>
.section .tail,#alloc
.fill 0x200,1,0
+1
View File
@@ -0,0 +1 @@
SRCS-y += common.c
+46
View File
@@ -0,0 +1,46 @@
#include <stddef.h>
#include <common.h>
#include <time.h>
void wait_stage2_ready(void)
{
int c = 0;
while (readl(REG_SC_SYSBOOT7) != 0xbeef0001) {
udelay(1);
if (c > 0 && (c % (1000 * 1000 * 2)) == 0) {
puts("Waiting firmware ready!\n");
}
c++;
}
}
int run_stage2_func(int (*func)(void))
{
int ret;
__DSB();
__ISB();
puts("Check firmware...\n");
wait_stage2_ready();
rv32_dcache_disable();
rv32_icache_disable();
if (readl((ulong *)__bin_end_pad) != CONFIG_BIN_END_PAD) {
puts("Firmware ERROR!\n");
return -1;
}
rv32_icache_enable();
rv32_dcache_enable();
puts("Run 0x");puthex((u32)func);puts("\n");
ret = func();
return ret;
}
+30
View File
@@ -0,0 +1,30 @@
CONFIG_PLATFORM = xmfalcon
CONFIG_PLATFORM_XMFALCON = y
CONFIG_CFLAGS = "-march=rv32imafc -mabi=ilp32f -mtune=e906 -Wall -Os"
CONFIG_LDFLAGS = "--oformat=elf32-littleriscv -lm -L$(shell $(CC) -print-sysroot)/lib/rv32imafc/ilp32f/ -lgcc -L$(dir $(shell $(CC) $(CFLAGS) -print-libgcc-file-name))"
CONFIG_PRINT = y
#CONFIG_PRINTF = y
#CONFIG_SERIAL_DISABLE = y
#CONFIG_DEBUG_INFO = y
CONFIG_MALLOC = y
CONFIG_MCU_FW_MAGIC = 0x57465652
CONFIG_MCU_FW_VERSION = 1
CONFIG_MCU_SRAM_SIZE = 256*1024
CONFIG_MCU_HEAD_SIZE = 64
CONFIG_TEXT_BASE = 0x4020000
CONFIG_STAGE2_START = 0x4028000
CONFIG_STACK_SIZE = 8192
CONFIG_PARAM_MEM_SIZE = 4096
CONFIG_RESERVED_MEM_SIZE = (1 * 1024 * 1024)
CONFIG_FPGA = y
CONFIG_I2C = y
CONFIG_BIN_END_PAD = 0xdeadbeef
CONFIG_PWM = y
#CONFIG_SIMPILE_SHELL = y
##CONFIG_UT_ENABLE = y
#CONFIG_XTHEAD_ISA_EXT = y
CONFIG_MEDIA_SUPPORT = y
CONFIG_MEDIA_PIPE_NUM = 1
#CONFIG_MEDIA_SAMPLE_AOV = y
#CONFIG_MEDIA_SAMPLE_QUICKSTART = y
+30
View File
@@ -0,0 +1,30 @@
CONFIG_PLATFORM = xmorca
CONFIG_PLATFORM_XMORCA = y
CONFIG_CFLAGS = "-march=rv32imafc -mabi=ilp32f -mtune=e906 -Wall -Os"
CONFIG_LDFLAGS = "--oformat=elf32-littleriscv -lm -L$(shell $(CC) -print-sysroot)/lib/rv32imafc/ilp32f/ -lgcc -L$(dir $(shell $(CC) $(CFLAGS) -print-libgcc-file-name))"
CONFIG_PRINT = y
#CONFIG_PRINTF = y
#CONFIG_SERIAL_DISABLE = y
#CONFIG_DEBUG_INFO = y
CONFIG_MALLOC = y
CONFIG_MCU_FW_MAGIC = 0x57465652
CONFIG_MCU_FW_VERSION = 1
CONFIG_MCU_SRAM_SIZE = 208*1024
CONFIG_MCU_HEAD_SIZE = 64
CONFIG_TEXT_BASE = 0x401C000
CONFIG_STAGE2_START = 0x4028000
CONFIG_STACK_SIZE = 8192
CONFIG_PARAM_MEM_SIZE = 4096
CONFIG_RESERVED_MEM_SIZE = (1 * 1024 * 1024)
#CONFIG_FPGA = y
CONFIG_I2C = y
CONFIG_BIN_END_PAD = 0xdeadbeef
CONFIG_PWM = y
#CONFIG_SIMPILE_SHELL = y
##CONFIG_UT_ENABLE = y
#CONFIG_XTHEAD_ISA_EXT = y
CONFIG_MEDIA_SUPPORT = y
#CONFIG_STOPWATCH_SUPPORT = y
CONFIG_MEDIA_PIPE_NUM = 1
#CONFIG_MEDIA_SAMPLE_QUICKSTART = y
+7
View File
@@ -0,0 +1,7 @@
SRCS-y += timer/
SRCS-y += serial/
SRCS-y += gpio/
SRCS-y += stopwatch/
SRCS-$(CONFIG_I2C) += i2c/
SRCS-$(CONFIG_PWM) += pwm/
+1
View File
@@ -0,0 +1 @@
SRCS-y += gpio.c
+26
View File
@@ -0,0 +1,26 @@
/* #define REG_IORW_DEBUG */
#include <io.h>
#include <platform.h>
unsigned long get_gpio_base(int group)
{
return GPIO0_BASE + (group << 12);
}
void gpio_set_dir(int group, int bit, int dir)
{
unsigned long base = get_gpio_base(group);
unsigned int v = readl(base + GPIO_DIR);
v &= ~(1 << bit);
v |= dir << bit;
writel(v, base + GPIO_DIR);
}
void gpio_set_data(int group, int bit, int data)
{
unsigned long base = get_gpio_base(group);
unsigned long data_addr = (base + (1 << (bit + 2)));
writel(data << bit, data_addr);
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += i2c.c
+600
View File
@@ -0,0 +1,600 @@
#include <io.h>
#include <timer.h>
#include "i2c.h"
struct platform_i2c {
unsigned int msg_buf_ptr;
int status;
#define I2C_WAIT_RESPOND (1 << 0)
};
struct i2c_platform_data {
unsigned int freq;
unsigned int clk;
};
struct i2c_msg {
unsigned short addr; /* slave address */
unsigned short flags;
#define I2C_M_TEN 0x0010
#define I2C_M_RD 0x0001
#define I2C_M_STOP 0x8000
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000
#define I2C_M_IGNORE_NAK 0x1000
#define I2C_M_NO_RD_ACK 0x0800
#define I2C_M_RECV_LEN 0x0400
#define I2C_M_16BIT_DATA 0x0008
#define I2C_M_16BIT_REG 0x0002
unsigned short len; /* msg length */
unsigned char *buf; /* pointer to msg data */
};
struct i2c_driver_data {
unsigned int reg_base;
unsigned int freq;
unsigned int irq;
unsigned int clk;
struct i2c_msg *msgs;
unsigned int msg_num;
unsigned int msg_idx;
unsigned int lock;
void *private;
};
#ifdef CONFIG_LOTUS_FPGA
#define CLK_LIMIT_DEFAULT 40000
#else
#define CLK_LIMIT_DEFAULT 400000
#endif
#define write_reg_bit(value, offset, addr) ({ \
unsigned long t, mask; \
mask = 1 << (offset); \
t = readl(addr); \
t &= ~mask; \
t |= (value << (offset)) & mask; \
writel(t, addr); \
})
#define I2C_WAIT_TIMEOUT (100 * 3)
#define I2C_TIMEOUT_COUNT 0x10000
#define I2C_BUF_SIZE 8
#define I2C_INTERRUPT_NUM 0
#if defined(CONFIG_PLATFORM_XMFALCON) || defined(CONFIG_PLATFORM_XMORCA)
#ifdef CONFIG_LOTUS_FPGA
#define get_bus_clk() 25000000
#else
#define get_bus_clk() 50000000
#endif
#define get_host_clock(i2c_num) ({ get_bus_clk(); })
static struct platform_i2c g_i2c_platform_data[I2C_NUM] = {0};
static int g_i2c_host_cfg[I2C_NUM] = {0, 1, 2, 3, 4, 5, 6, 7}; /* i2c index */
static struct i2c_driver_data g_i2c_data[I2C_NUM] = {
{I2C0_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C1_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C2_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C3_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C4_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C5_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C6_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C7_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
};
#elif defined(CONFIG_TARGET_XM720XXX)
#define get_bus_clk() 50000000
#define get_host_clock(i2c_num) ({ get_bus_clk(); })
static struct platform_i2c g_i2c_platform_data[I2C_NUM] = {0};
static int g_i2c_host_cfg[I2C_NUM] = {0, 1, 2}; /* 0,1,2: i2c index */
static struct i2c_driver_data g_i2c_data[I2C_NUM] = {
{I2C0_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C1_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C2_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
};
#endif
static void i2c_disable(const struct i2c_driver_data *i2c);
static void i2c_cfg_irq(const struct i2c_driver_data *i2c, unsigned int flag);
static unsigned int i2c_clr_irq(const struct i2c_driver_data *i2c);
static void i2c_rescue(const struct i2c_driver_data *i2c)
{
i2c_disable(i2c);
i2c_cfg_irq(i2c, 0);
i2c_clr_irq(i2c);
unsigned int val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
unsigned int time_cnt = 0;
do {
for (int index = 0; index < 9; index++) { /* shift:9 */
val = (0x1 << GPIO_MODE_SHIFT) | 0x1;
writel(val, i2c->reg_base + I2C_CTRL2);
udelay(5); /* delay: 5 us */
val = (0x1 << GPIO_MODE_SHIFT) |
(0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
udelay(5); /* delay: 5 us */
}
time_cnt++;
if (time_cnt > I2C_WAIT_TIMEOUT) {
goto disable_rescue;
}
val = readl(i2c->reg_base + I2C_CTRL2);
} while (!(val & (0x1 << CHECK_SDA_IN_SHIFT)));
val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
udelay(10); /* delay: 10 us */
val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
disable_rescue:
val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1;
writel(val, i2c->reg_base + I2C_CTRL2);
}
static void i2c_disable(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_GLB);
val &= ~GLB_EN_MASK;
writel(val, i2c->reg_base + I2C_GLB);
}
static void i2c_disable_irq(const struct i2c_driver_data *i2c, unsigned int flag)
{
unsigned int val = readl(i2c->reg_base + I2C_INTR_EN);
val &= ~flag;
writel(val, i2c->reg_base + I2C_INTR_EN);
}
static unsigned int i2c_clr_irq(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_INTR_STAT);
writel(INTR_ALL_MASK, i2c->reg_base + I2C_INTR_RAW);
return val;
}
static void i2c_set_freq(struct i2c_driver_data *i2c)
{
unsigned int val;
unsigned int freq = i2c->freq;
unsigned int clk_rate = i2c->clk;
unsigned int max_freq = clk_rate >> 1;
if (freq > max_freq) {
i2c->freq = max_freq;
freq = i2c->freq;
}
if (freq <= 100000) { /* 100000:100KHz */
val = clk_rate / (freq * 2); /* 1/2:0.5 */
writel(val, i2c->reg_base + I2C_SCL_H);
writel(val, i2c->reg_base + I2C_SCL_L);
} else {
val = (clk_rate * 36) / (freq * 100); /* 36/100:0.36 */
writel(val, i2c->reg_base + I2C_SCL_H);
val = (clk_rate * 64) / (freq * 100); /* 64/100:0.64 */
writel(val, i2c->reg_base + I2C_SCL_L);
}
val = readl(i2c->reg_base + I2C_GLB);
val &= ~GLB_SDA_HOLD_MASK;
val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK);
writel(val, i2c->reg_base + I2C_GLB);
}
/*
* set i2c controller TX and RX FIFO water
*/
static void i2c_set_water(const struct i2c_driver_data *i2c)
{
writel(I2C_TXF_WATER, i2c->reg_base + I2C_TX_WATER);
writel(I2C_RXF_WATER, i2c->reg_base + I2C_RX_WATER);
}
static void i2c_enable_clk(unsigned char i2c_num)
{
const unsigned int clk_start_bit = 16 + i2c_num; /* 16: i2c clk start bit */
const unsigned int rst_start_bit = 24 + i2c_num; /* 24: i2c rst start bit */
const unsigned int enable_clck = 1;
const unsigned int enable_rst = 0;
write_reg_bit(enable_clck, clk_start_bit, (uintptr_t)I2C_CRG_REG_BASE);
write_reg_bit(enable_rst, rst_start_bit, (uintptr_t)I2C_CRG_REG_BASE);
}
/*
* initialise the controller, set i2c bus interface freq
*/
static void i2c_init_cfg(const struct i2c_driver_data *i2c, unsigned char i2c_num)
{
i2c_enable_clk(i2c_num);
i2c_disable(i2c);
i2c_disable_irq(i2c, INTR_ALL_MASK);
i2c_set_freq((struct i2c_driver_data *)i2c);
i2c_set_water(i2c);
}
static void i2c_cmdreg_set(const struct i2c_driver_data *i2c, unsigned int cmd,
unsigned int *offset)
{
writel(cmd, i2c->reg_base + I2C_CMD_BASE + (*offset) * 4); /* 4: bytes */
(*offset)++;
}
static void i2c_cfg_cmd(const struct i2c_driver_data *i2c)
{
struct i2c_msg *msg = i2c->msgs;
unsigned int offset = 0;
if (i2c->msg_idx == 0)
i2c_cmdreg_set(i2c, CMD_TX_S, &offset);
else
i2c_cmdreg_set(i2c, CMD_TX_RS, &offset);
if (msg->flags & I2C_M_TEN) {
if (i2c->msg_idx == 0) {
i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
} else {
i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
}
} else {
i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
}
if (msg->flags & I2C_M_IGNORE_NAK)
i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
else
i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
if (msg->flags & I2C_M_RD) {
if (msg->len >= 2) { /* msg len:2 */
writel(offset, i2c->reg_base + I2C_DST1);
writel(msg->len - 2, i2c->reg_base + I2C_LOOP1); /* 2: max len */
i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset);
i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
}
i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset);
} else {
writel(offset, i2c->reg_base + I2C_DST1);
writel(msg->len - 1, i2c->reg_base + I2C_LOOP1);
i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset);
i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset);
if (msg->flags & I2C_M_IGNORE_NAK) {
i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
}
else {
i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
}
i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
}
if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) {
i2c_cmdreg_set(i2c, CMD_TX_P, &offset);
}
i2c_cmdreg_set(i2c, CMD_EXIT, &offset);
}
static void i2c_enable(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_GLB);
val |= GLB_EN_MASK;
writel(val, i2c->reg_base + I2C_GLB);
}
/*
* config i2c slave addr
*/
static void i2c_set_addr(const struct i2c_driver_data *i2c)
{
struct i2c_msg *msg = i2c->msgs;
unsigned int addr;
if (msg->flags & I2C_M_TEN) {
/* first byte is 11110XX0 where XX is upper 2 bits */
addr = ((msg->addr & 0x300) << 1) | 0xf000;
if (msg->flags & I2C_M_RD) {
addr |= 1 << 8; /* shift:8 */
}
/* second byte is the remaining 8 bits */
addr |= msg->addr & 0xff;
} else {
addr = (msg->addr & 0x7f) << 1;
if (msg->flags & I2C_M_RD) {
addr |= 1;
}
}
writel(addr, i2c->reg_base + I2C_DATA1);
}
/*
* start command sequence
*/
static void i2c_start_cmd(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_CTRL1);
val |= CTRL1_CMD_START_MASK;
writel(val, i2c->reg_base + I2C_CTRL1);
}
static int i2c_wait_rx_noempty(const struct i2c_driver_data *i2c)
{
unsigned int time_cnt = 0;
unsigned int val;
do {
val = readl(i2c->reg_base + I2C_STAT);
if (val & STAT_RXF_NOE_MASK) {
return 0;
}
udelay(50); /* delay:50 us */
time_cnt++;
} while (time_cnt < I2C_TIMEOUT_COUNT);
i2c_rescue(i2c);
return -1;
}
static int i2c_wait_tx_nofull(const struct i2c_driver_data *i2c)
{
unsigned int time_cnt = 0;
unsigned int val;
do {
val = readl(i2c->reg_base + I2C_STAT);
if (val & STAT_TXF_NOF_MASK) {
return 0;
}
udelay(50); /* delay:50 us */
time_cnt++;
} while (time_cnt < I2C_TIMEOUT_COUNT);
i2c_rescue(i2c);
return -1;
}
static int i2c_wait_idle(const struct i2c_driver_data *i2c)
{
unsigned int time_cnt = 0;
unsigned int val;
do {
val = readl(i2c->reg_base + I2C_INTR_RAW);
if (val & (INTR_ABORT_MASK)) {
//printf("i2c wait idle 1,val==0x%x\n",val);
return -1;
}
if (val & INTR_CMD_DONE_MASK) {
return 0;
}
udelay(50); /* delay:50 us */
time_cnt++;
} while (time_cnt < I2C_WAIT_TIMEOUT);
i2c_rescue(i2c);
return -1;
}
static int i2c_polling_xfer_one_msg(const struct i2c_driver_data *i2c)
{
int status;
unsigned int val;
struct i2c_msg *msg = i2c->msgs;
unsigned int msg_buf_ptr = 0;
i2c_enable(i2c);
i2c_clr_irq(i2c);
i2c_set_addr(i2c);
i2c_cfg_cmd(i2c);
i2c_start_cmd(i2c);
if (msg->flags & I2C_M_RD) {
while (msg_buf_ptr < msg->len) {
status = i2c_wait_rx_noempty(i2c);
if (status) {
goto end;
}
val = readl(i2c->reg_base + I2C_RXF);
msg->buf[msg_buf_ptr] = val;
msg_buf_ptr++;
}
} else {
while (msg_buf_ptr < msg->len) {
status = i2c_wait_tx_nofull(i2c);
if (status) {
goto end;
}
val = msg->buf[msg_buf_ptr];
writel(val, i2c->reg_base + I2C_TXF);
msg_buf_ptr++;
}
}
status = i2c_wait_idle(i2c);
end:
i2c_disable(i2c);
return status;
}
static void i2c_cfg_irq(const struct i2c_driver_data *i2c, unsigned int flag)
{
writel(flag, i2c->reg_base + I2C_INTR_EN);
}
static int i2c_xfer(unsigned char i2c_num, const struct i2c_msg *msgs, int num)
{
int status = 0;
if (msgs == NULL) {
//printf("[error] msg pointer is null.\n");
return -1;
}
struct i2c_driver_data *i2c = &g_i2c_data[i2c_num];
struct platform_i2c *hpi = &g_i2c_platform_data[i2c_num];
i2c->clk = get_host_clock(0);
i2c->private = (void *)(hpi);
i2c->msgs = (struct i2c_msg *)msgs;
i2c->msg_num = (unsigned int)num;
i2c->msg_idx = 0;
while (i2c->msg_idx < i2c->msg_num) {
status = i2c_polling_xfer_one_msg(i2c);
if (status) {
break;
}
i2c->msgs++;
i2c->msg_idx++;
}
if (!status || i2c->msg_idx > 0) {
status = i2c->msg_idx;
}
return status;
}
static int i2c_check_enable(unsigned char i2c_num)
{
if (i2c_num >= I2C_NUM) {
return -1;
}
return g_i2c_host_cfg[i2c_num];
}
static int hal_i2c_recv_inner(const struct i2c_client *client, unsigned char *buf,
unsigned int count)
{
struct i2c_msg msg[I2C_BUF_SIZE] = {0};
unsigned char reg_addr[2] = {0};
if (client->reg_width == 2) { /* reg_width:2 */
reg_addr[0] = (client->reg_addr >> 8) & 0xff; /* shift:8 */
reg_addr[1] = client->reg_addr & 0xff;
} else {
reg_addr[0] = client->reg_addr & 0xff;
}
msg[0].addr = client->dev_addr;
msg[0].flags = 0;
msg[0].len = client->reg_width;
msg[0].buf = reg_addr;
msg[1].addr = client->dev_addr;
msg[1].flags = 0;
msg[1].flags |= I2C_M_RD;
msg[1].len = count;
msg[1].buf = buf;
return i2c_xfer(client->i2c_num, msg, 2); /* msg num:2 */
}
static int hal_i2c_send_inner(unsigned char i2c_num, unsigned short dev_addr, const char *buf,
unsigned int count)
{
struct i2c_msg msg = {0};
msg.addr = dev_addr;
msg.flags = 0;
msg.len = count;
msg.buf = (unsigned char *)buf;
int ret = i2c_xfer(i2c_num, &msg, 1);
return (ret == 1) ? count : ret;
}
static int hal_i2c_init_inner(unsigned char i2c_num)
{
struct i2c_driver_data *i2c = NULL;
struct platform_i2c *hpi = NULL;
int ret = i2c_check_enable(i2c_num);
if (ret < 0) {
return -1;
}
i2c = &g_i2c_data[i2c_num];
hpi = &g_i2c_platform_data[i2c_num];
i2c->clk = get_host_clock(i2c_num);
i2c->private = (void *)(hpi);
i2c->irq = 0;
i2c_init_cfg(i2c, i2c_num);
return 0;
}
int i2c_recv(const struct i2c_client *client, unsigned char *buf,
unsigned int count)
{
if ((client == NULL) || (buf == NULL)) {
return -1;
}
if (client->i2c_num >= I2C_NUM) {
return -1;
}
if (count > I2C_BUF_SIZE) {
return -1;
}
return hal_i2c_recv_inner(client, buf, count);
}
int i2c_send(unsigned char i2c_num, unsigned short dev_addr, const char *buf,
unsigned int count)
{
if (i2c_num >= I2C_NUM) {
return -1;
}
if (buf == NULL) {
return -1;
}
if (count > I2C_BUF_SIZE) {
return -1;
}
return hal_i2c_send_inner(i2c_num, dev_addr, buf, count);
}
int i2c_init(unsigned char i2c_num)
{
if (i2c_num >= I2C_NUM) {
return -1;
}
return hal_i2c_init_inner(i2c_num);
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += pwm.c
+80
View File
@@ -0,0 +1,80 @@
#include <io.h>
#include "pwm.h"
static void pwm_set_bits(void* base, u32 offset, unsigned int mask, u32 data)
{
void *address = base + offset;
unsigned int value;
value = readl(address);
value &= ~mask;
value |= (data & mask);
writel(value, address);
}
static void get_pwm_clk(unsigned int *clk)
{
void *pwm_clock_addr = (void *)PWM_CLOCK_ADDR_BASE;
unsigned int val = readl(pwm_clock_addr);
val = (val >> 8) & 0x3;
switch (val) {
case 0:
*clk = PWM_CLOCK_3M;
break;
case 1:
*clk = PWM_CLOCK_50M;
break;
default:
*clk = PWM_CLOCK_24M;
break;
}
}
int pwm_enable(int pwm_id)
{
if (pwm_id > PWM_MAX_NUM)
return -1;
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id), PWM_ENABLE_MASK, (0x1 << PWM_ENABLE_SHIFT));
return 0;
}
int pwm_disable(int pwm_id)
{
if (pwm_id > PWM_MAX_NUM)
return -1;
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id), PWM_ENABLE_MASK, (0x0 << PWM_ENABLE_SHIFT));
return 0;
}
int pwm_config(int pwm_id, int duty_cycle_us, int period_us)
{
unsigned int duty;
unsigned int period, freq;
unsigned int clk;
if ((pwm_id > PWM_MAX_NUM) || (duty_cycle_us > period_us))
return -1;
get_pwm_clk(&clk);
freq = clk/1000000;
period = freq * period_us;
duty = period * duty_cycle_us/period_us;
if ((period < 2) || (duty < 1))
return -1;
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CFG_CYCLE_ADDR(pwm_id), PWM_PERIOD_MASK, period);
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CFG_HLINT_ADDR(pwm_id), PWM_DUTY_MASK, duty);
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id),
PWM_KEEP_MASK, (0x1 << PWM_KEEP_SHIFT));
return 0;
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += serial.c
+199
View File
@@ -0,0 +1,199 @@
/* serial.c - print to uart */
#include <platform.h>
#include <serial.h>
#include <common.h>
static int serial_test_enable(void)
{
#ifdef CONFIG_SERIAL_DISABLE
return 0;
#else
return 1;
#endif
}
static void pl01x_putc(char c)
{
/* Wait until there is space in the FIFO */
while (readl(UART_PL01x_FR) & UART_PL01x_FR_TXFF);
/* Send the character */
writel(c, UART_PL01x_DR);
}
static u32 pl01x_getc(void)
{
u32 data;
while (readl(UART_PL01x_FR) & UART_PL01x_FR_RXFE) {
/* Wait until there is data in the FIFO */
}
data = readl(UART_PL01x_DR);
/* Check for an error flag */
if (data & 0xFFFFFF00) {
/* Clear the error */
writel(0xFFFFFFFF, UART_PL01x_ECR);
return 0;
}
return data;
}
void serial_putc(const char c)
{
if (!serial_test_enable())
return;
if (c == '\n')
pl01x_putc('\r');
pl01x_putc(c);
}
char serial_getc(void)
{
return (pl01x_getc() & 0xFF);
}
void serial_puts(const char *s)
{
if (!serial_test_enable())
return;
if (s == NULL)
return;
while (*s) {
serial_putc(*s);
s++;
}
}
void serial_puts_always(const char *s)
{
if (s == NULL)
return;
while (*s) {
if (*s == '\n')
pl01x_putc('\r');
pl01x_putc(*s);
s++;
}
}
void serial_put_dec(u32 dec)
{
u32 num = dec;
char c[20] = {0}; /* size 20 */
int i = 0;
if (!serial_test_enable())
return;
if (num == 0) {
pl01x_putc('0');
return;
}
while (num) {
c[i] = '0' + (num % 10); /* bit size 10 */
++i;
num /= 10; /* bit size 10 */
}
for (i -= 1; i >= 0; --i)
pl01x_putc(c[i]);
}
void serial_put_hex(u32 hex)
{
int i;
char c;
if (!serial_test_enable())
return;
for (i = 28; i >= 0; i -= 4) { /* bit size 28 4 */
c = ((unsigned int)hex >> (unsigned int)i) & 0x0F;
if (c < 10) /* bit size 10 */
c += '0';
else
c += 'A' - 10; /* bit size 10 */
pl01x_putc(c);
}
}
void serial_put_hex_always(u32 hex)
{
int i;
char c;
for (i = 28; i >= 0; i -= 4) { /* bit size 28 4 */
c = ((unsigned int)hex >> (unsigned int)i) & 0x0F;
if (c < 10) /* bit size 10 */
c += '0';
else
c += 'A' - 10; /* bit size 10 */
pl01x_putc(c);
}
}
static void _serial_crg_init(void)
{
u32 tmp;
/* configure pinmux of uart */
/* writel(0x1502, 0x112C00F0);
* writel(0x1402, 0x119800E0); */
/* enable uart clock */
tmp = readl(REG_PERI_CRG110);
tmp |= 1 << 3;
writel(tmp, REG_PERI_CRG110);
/* cancel uart reset */
tmp = readl(REG_PERI_CRG110);
tmp &= ~(1 << 11);
writel(tmp, REG_PERI_CRG110);
}
void serial_init(void)
{
u32 tmp;
u32 divider;
u32 remainder;
u32 fraction;
_serial_crg_init();
/* first, disable everything */
writel(0, UART_PL01x_CR);
/*
* Set baud rate
*
* IBRD = UART_CLK / (16 * BAUD_RATE)
* FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
* / (16 * BAUD_RATE))
*/
tmp = 16 * UART_BAUDRATE;
divider = UART_CLOCK / tmp;
remainder = UART_CLOCK % tmp;
tmp = (8 * remainder) / UART_BAUDRATE;
fraction = (tmp >> 1) + (tmp & 1);
writel(divider, UART_PL01x_IBRD);
writel(fraction, UART_PL01x_FBRD);
writel(UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN, UART_PL01x_LCRH);
/* Finally, enable the UART */
writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
UART_PL011_CR_RXE, UART_PL01x_CR);
return;
}
+2
View File
@@ -0,0 +1,2 @@
SRCS-y += stopwatch.c
+27
View File
@@ -0,0 +1,27 @@
#include <sys/types.h>
#include <platform.h>
#include <io.h>
typedef union {
u32 value;
struct {
/* [0] timer trigger */
u32 timer_trigger : 1;
/* [2] timer clear */
u32 timer_clear : 1;
/* [3] running timer trigger */
u32 running_timer_trigger : 1;
/* [3:31] reserved */
u32 reserved : 29;
};
} stopwatch_cfg;
void stopwatch_trigger(void)
{
stopwatch_cfg cfg = {0};
cfg.timer_clear = 0; /* false */
cfg.timer_trigger = 1; /* true */
writel(cfg.value, (STOPWATCH_CTRL_REG2));
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += timer.c
+78
View File
@@ -0,0 +1,78 @@
#include <common.h>
#include <timer.h>
#define TIMER_LOAD 0
#define TIMER_VALUE 0x4
#define TIMER_CONTROL 0x8
#define CFG_TIMER_CTRL 0xc0
#define TIMER_FEQ 24000000
#define TIMER_DIV 1
#define TIMER_NOR_DIVIDER_US (TIMER_FEQ / TIMER_DIV / 1000000)
#define UDELAY_US_MAX (61 * 1000 * 1000UL)
#define REG_TIMER_BASE TIMER3_REG_BASE
#define timer_reg_get(offset) readl(REG_TIMER_BASE + (offset))
#define timer_reg_set(offset, val) writel(val, REG_TIMER_BASE + (offset))
static u8 g_timer_init = 0;
ulong timer_get_val(void)
{
return ~1UL - timer_reg_get(TIMER_VALUE);
}
void udelay(ulong us)
{
ulong cur, start, end;
ulong count;
if (us == 0)
return;
assert(g_timer_init == 1);
start = timer_get_val();
if (us >= UDELAY_US_MAX) {
puts("WARNING: long udelay, use ");
putdec(UDELAY_US_MAX);
puts("us instead!\n");
count = UDELAY_US_MAX * TIMER_NOR_DIVIDER_US;
} else
count = us * TIMER_NOR_DIVIDER_US;
end = start + count;
while (1) {
cur = timer_get_val();
if ((end >= start && cur >= end ) ||
(end < start && cur >= end && cur < start))
break;
}
}
void mdelay(u32 msec)
{
assert(g_timer_init == 1);
udelay(msec * 1000);
}
void timer_init(void)
{
timer_reg_set(TIMER_CONTROL, 0);
timer_reg_set(TIMER_LOAD, 0xffffffff);
timer_reg_set(TIMER_CONTROL, CFG_TIMER_CTRL);
g_timer_init = 1;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _ASSERT_H_
#define _ASSERT_H_
#include <debug.h>
#define assert(x) ASSERT(x)
#endif /* _ASSERT_H_ */
+63
View File
@@ -0,0 +1,63 @@
#ifndef __COMMON_H_
#define __COMMON_H_
#include <config.h>
#include <sys/types.h>
#include <io.h>
#include <serial.h>
#include <stdio.h>
#include <compile.h>
#include <core.h>
#include <debug.h>
#include <assert.h>
#include <timer.h>
#include <string.h>
#include <reserved_mem.h>
extern char g_base_irqstack[];
extern char g_top_irqstack[];
extern u32 g_heap_start;
extern u32 g_heap_end;
extern char _start[];
extern char _end[];
extern char __text_start[];
extern char __text_end[];
extern char __rodata_start[];
extern char __rodata_end[];
extern char __data_start[];
extern char __data_end[];
extern char __text2_start[];
extern char __text2_end[];
extern char __rodata2_start[];
extern char __rodata2_end[];
extern char __data2_start[];
extern char __data2_end[];
extern char __bss_start[];
extern char __bss_end[];
extern char __bin_end_pad[];
extern char __bin_end[];
extern char __param_start[];
extern char __param_end[];
u32 start_shell(void);
int run_stage2_func(int (*func)(void));
u64 get_ddr_size(void);
ulong get_reserved_ddr(u32 size);
void stopwatch_trigger(void);
#endif /*__COMMON_H_*/
+45
View File
@@ -0,0 +1,45 @@
#ifndef _COMPILE_H_
#define _COMPILE_H_
#include <stddef.h>
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/')? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#define array_size(x) (sizeof(x) / sizeof(*(x)))
#define swap32(_x) ((uint32)( \
((((uint32)(_x)) & 0x000000FF) << 24) | \
((((uint32)(_x)) & 0x0000FF00) << 8) | \
((((uint32)(_x)) & 0xFF000000) >> 24) | \
((((uint32)(_x)) & 0x00FF0000) >> 8)))
#define swap16(_x) ((uint16)( \
((((uint16)(_x)) & 0xFF00) >> 8) | \
((((uint16)(_x)) & 0x00FF) << 8)))
#define around(size, align) (((size) + (align) - 1) & (~((align) - 1)))
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#define STAGE1_FUNC __attribute__((section(".text.stage1")))
#define STAGE1_GLOBAL __attribute__((section(".data.stage1")))
#define STAGE1_CONST_GLOBAL __attribute__((section(".rodata.stage1"))) const
#define STAGE1_STR(str) \
({ \
static const char _str_##__COUNTER__[] \
__attribute__((section(".rodata.stage1"))) = str; \
_str_##__COUNTER__; \
})
#define STAGE2_FUNC __attribute__((section(".text.stage2")))
#define STAGE2_GLOBAL __attribute__((section(".data.stage2")))
#define STAGE2_CONST_GLOBAL __attribute__((section(".rodata.stage2"))) const
#define STAGE2_STR(str) \
({ \
static const char _str_##__COUNTER__[] \
__attribute__((section(".rodata.stage2"))) = str; \
_str_##__COUNTER__; \
})
#endif /* _COMPILE_H_ */
+5
View File
@@ -0,0 +1,5 @@
#ifndef CONFIGH
#define CONFIGH
#include <autoconf.h>
#include <platform.h>
#endif
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _SYS_CTYPE_H_
#define _SYS_CTYPE_H_
#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
#define isascii(c) (((c) & ~0x7f) == 0)
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
#define islower(c) ((c) >= 'a' && (c) <= 'z')
#define isalpha(c) (isupper(c) || islower(c))
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define isxdigit(c) (isdigit(c) \
|| ((c) >= 'A' && (c) <= 'F') \
|| ((c) >= 'a' && (c) <= 'f'))
#define isprint(c) ((c) >= ' ' && (c) <= '~')
#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define min_t(t, x, y) ((t)((t)(x) < (t)(y) ? (x) : (y)))
#define tohex(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
(((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \
(((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : -1)))
#endif /* !_SYS_CTYPE_H_ */
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (c) XMEDIA 2021. All rights reserved.
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
/******************************************************************************/
#include <config.h>
#include <stdio.h>
#include <lib.h>
/* #define ASSERT(_p) if (!(_p)) { \
* printf("%s(%s,%d):assert:(%s)\n", __FILE__, __FUNCTION__, __LINE__, #_p);
*
* #define ASSERT1(_p, _fmt, args...) if (!(_p)) { \
* printf("%s(%s,%d):assert:(%s)\n" _fmt, __FILE__, __FUNCTION__, __LINE__, #_p, ##args); */
#define ASSERT(_condition) do { \
if (!(_condition)) { \
puts("ASSERT "); \
putchar('['); \
puts(__FILE__); \
putchar(','); \
putdec(__LINE__); \
puts("]: "); \
puts(#_condition); \
puts("\n"); \
} \
} while(0)
#define __PRINT_MACRO(x) #x
#define PRINT_MARCO(x) #x"="__PRINT_MACRO(x)
/* #pragma message(PRINT_MARCO(MACRO_NAME_XXX)) */
int dump_hex(u32 addr, char *buf, u32 sz_buf, u32 width);
/******************************************************************************/
#endif /* _DEBUG_H_ */
+20
View File
@@ -0,0 +1,20 @@
#ifndef _DIV64_H_
#define _DIV64_H_
#include <sys/types.h>
extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
#define do_div(n, base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
if (((n) >> 32) == 0) { \
__rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \
} else \
__rem = __div64_32(&(n), __base); \
__rem; \
})
#endif /* _DIV64_H_ */
+153
View File
@@ -0,0 +1,153 @@
#ifndef _ERRNO_H_
#define _ERRNO_H_
/****************************************************************************
* Error Number Definitions
****************************************************************************/
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Invalid system call number */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */
#define ENOTSUP 134 /* Not supported */
#endif /* _ERRNO_H_ */
+23
View File
@@ -0,0 +1,23 @@
#ifndef _FLOAT_H_
#define _FLOAT_H_
#undef FLT_MAX
#define FLT_MAX __FLT_MAX__
#undef DBL_MAX
#define DBL_MAX __DBL_MAX__
#undef FLT_MIN
#define FLT_MIN __FLT_MIN__
#undef DBL_MIN
#define DBL_MIN __DBL_MIN__
#undef FLT_EPSILON
#define FLT_EPSILON __FLT_EPSILON__
#undef DBL_EPSILON
#define DBL_EPSILON __DBL_EPSILON__
#endif /* ifndef _FLOAT_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef _GPIO_H_
#define _GPIO_H_
void gpio_set_dir(int group, int bit, int dir);
void gpio_set_data(int group, int bit, int data);
#endif /* _GPIO_H_ */
+147
View File
@@ -0,0 +1,147 @@
#ifndef _HLIST_H_
#define _HLIST_H_
#include <stddef.h>
/*
* 该结构体用于嵌入到业务数据结构体中(entry),用于实现链表
* 例:
* struct Entry { // 你的业务数据结构体
* ...
* struct node node; // 嵌入其中,位置任意
* ...
* };
*/
struct node {
struct node *next, *prev;
};
/*
* 由成员变量 node 地址获取结构体 entry 地址
* 例:
* struct Entry entry;
* struct node *n = &entry.node;
* struct Entry *p = node_entry(n, struct Entry, node);
* 此时 p 指向 entry
*/
#define node_entry(node, type, member) \
((type*)((char*)(node) - (size_t)&((type*)0)->member))
/* 带哨兵节点的双向链表 */
struct list {
struct node base;
};
static inline void list_init(struct list *list)
{
list->base.next = &list->base;
list->base.prev = &list->base;
}
static inline bool list_empty(const struct list *list)
{
return list->base.next == &list->base;
}
static inline bool list_is_head(const struct list *list, const struct node *node)
{
return list->base.next == node;
}
static inline bool list_is_tail(const struct list *list, const struct node *node)
{
return list->base.prev == node;
}
/* node 插入到 pos 后面 */
static inline void list_insert_backward(struct node *pos, struct node *node)
{
node->prev = pos;
node->next = pos->next;
node->prev->next = node;
node->next->prev = node;
}
/* node 插入到 pos 前面 */
static inline void list_insert(struct node *pos, struct node *node)
{
node->prev = pos->prev;
node->next = pos;
node->prev->next = node;
node->next->prev = node;
}
static inline void list_add_tail(struct list *list, struct node *node)
{
list_insert(&list->base, node);
}
static inline void list_add_head(struct list *list, struct node *node)
{
list_insert(list->base.next, node);
}
static inline void list_remove(struct node *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
static inline void list_remove_tail(struct list *list)
{
list_remove(list->base.prev);
}
static inline void list_remove_head(struct list *list)
{
list_remove(list->base.next);
}
static inline void list_replace(struct node *old, struct node *node)
{
node->next = old->next;
node->next->prev = node;
node->prev = old->prev;
node->prev->next = node;
}
#define list_for_each(node, list) \
for (node = (list)->base.next; node != &(list)->base; node = (node)->next)
#define list_for_each_safe(node, tmp, list) \
for (node = (list)->base.next, tmp = (node)->next; node != &(list)->base; node = tmp, tmp = (node)->next)
/* 获取头结点,或空 */
#define list_head_entry(list, type, member) \
(list_empty(list) ? NULL : node_entry((list)->base.next, type, member))
/* 获取尾结点,或空 */
#define list_tail_entry(list, type, member) \
(list_empty(list) ? NULL : node_entry((list)->base.prev, type, member))
/* 获取下一结点,或空 */
#define list_next_entry(entry, list, type, member) \
(list_is_tail(list, &(entry)->member) ? \
NULL : \
node_entry((entry)->member.next, type, member))
/* 获取上一结点,或空 */
#define list_prev_entry(entry, list, type, member) \
(list_is_head(list, &(entry)->member) ? \
NULL : \
node_entry((entry)->member.prev, type, member))
/* 遍历链表;过程中如需操作链表,请使用 _SAFE 版本 */
#define list_for_each_entry(entry, list, type, member) \
for (entry = node_entry((list)->base.next, type, member); \
&(entry)->member != &(list)->base; \
entry = node_entry((entry)->member.next, type, member))
#define list_for_each_entry_safe(entry, tmp, list, type, member) \
for (entry = node_entry((list)->base.next, type, member), \
tmp = node_entry((entry)->member.next, type, member); \
&(entry)->member != &(list)->base; \
entry = tmp, tmp = node_entry((entry)->member.next, type, member))
#endif /* _HLIST_H_ */
+21
View File
@@ -0,0 +1,21 @@
#ifndef _I2C_H_
#define _I2C_H_
#include <platform.h>
#include <sys/types.h>
#include <io.h>
#include <lib.h>
struct i2c_client {
unsigned char i2c_num;
unsigned short dev_addr;
unsigned long int reg_addr;
unsigned int reg_width;
};
int i2c_init(unsigned char i2c_num);
int i2c_recv(const struct i2c_client *client, unsigned char *buf, unsigned int count);
int i2c_send(unsigned char i2c_num, unsigned short dev_addr, const char *buf,unsigned int count);
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef _IMAGE_H_
#define _IMAGE_H_
#include <sys/types.h>
struct mcu_fw_head {
u32 j_instruction; /* Jump to real excutable entry */
u32 fw_magic; /* MCU Firmware magic */
u32 fw_ver; /* MCU Firmware version */
u32 fw_total_size; /* MCU Firmware total size */
u32 fw_stage1_size; /* MCU Stage1 size */
u8 resv[CONFIG_MCU_HEAD_SIZE - 20]; /* Reserved */
};
#endif /* _IMAGE_H_ */
+15
View File
@@ -0,0 +1,15 @@
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include <stdint.h>
#define ATTRIBUTE_ISR __attribute__ ((interrupt ("machine")))
void drv_irq_enable(uint32_t irq_num);
void drv_irq_disable(uint32_t irq_num);
int drv_irq_register(uint32_t irq_num, void *irq_handler);
void drv_irq_unregister(uint32_t irq_num);
int irq_init(void);
#endif /* ifndef _INTERRUPT_H_ */
+10
View File
@@ -0,0 +1,10 @@
#ifdef CONFIG_ARM_ARCH
#include <arm/include/io.h>
#endif
#ifdef CONFIG_RISCV_ARCH
#include <riscv/include/io.h>
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef __LIB_H__
#define __LIB_H__
#include <sys/types.h>
#include <config.h>
#define SECUREC_MEM_MAX_LEN (0x100000) //1MB
void reset_cpu(void);
int memset_s(void* dest, size_t destMax, unsigned char c, size_t count);
int memcpy_s(void* dest, size_t destMax, const void* src, size_t count);
unsigned short crc16(unsigned char *data, unsigned int length);
#endif /*__LIB_H__*/
+22
View File
@@ -0,0 +1,22 @@
#ifndef _MALLOC_H_
#define _MALLOC_H_
#include <config.h>
#include <stddef.h>
void malloc_init(uint32 start, uint32 len);
#ifdef CONFIG_MALLOC
void *malloc(uint32 bytes); /* not thread safe */
void *memalign(uint32 alignment, uint32 bytes);
void free(void *ptr);
void show_memnode(unsigned int);
#else
void *__malloc(uint32 bytes, const char *file, int line);
void *__memalign(uint32 alignment, uint32 bytes, const char *file, int line);
void __free(const void *mem, const char *file, int line);
#define malloc(bytes) __malloc(bytes, __FILE__, __LINE__)
#define memalign(alignment, bytes) __memalign(alignment, bytes, __FILE__, __LINE__)
#define free(mem) __free(mem, __FILE__, __LINE__)
#endif
#endif /* _MALLOC_H_ */
+61
View File
@@ -0,0 +1,61 @@
#ifndef _MATH_H_
#define _MATH_H_
#define FP_NAN 0
#define FP_INFINITE 1
#define FP_ZERO 2
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
# ifndef HUGE_VALF
# define HUGE_VALF (__builtin_huge_valf())
# endif
# ifndef INFINITY
# define INFINITY (__builtin_inff())
# endif
# ifndef NAN
# define NAN (__builtin_nanf(""))
# endif
#define fpclassify(__x) (__builtin_fpclassify (FP_NAN, FP_INFINITE, \
FP_NORMAL, FP_SUBNORMAL, \
FP_ZERO, __x))
#ifndef isfinite
#define isfinite(__x) (__builtin_isfinite (__x))
#endif
#ifndef isinf
#define isinf(__x) (__builtin_isinf_sign (__x))
#endif
#ifndef isnan
#define isnan(__x) (__builtin_isnan (__x))
#endif
#define isnormal(__x) (__builtin_isnormal (__x))
float logf(float x);
float sqrtf(float x);
float powf(float x, float y);
float fabsf(float x);
float sinf(float x);
float cosf(float x);
#undef log
#define log(x) logf(x)
#undef pow
#define pow(x, y) powf(x, y)
#undef abs
#define abs(x) fabsf(x)
#undef fabs
#define fabs(x) fabsf(x)
#undef sqrt
#define sqrt(x) sqrtf(x)
#undef sin
#define sin(x) sinf(x)
#undef cos
#define cos(x) cosf(x)
#endif /* _MATH_H_ */
+14
View File
@@ -0,0 +1,14 @@
#ifndef _PWM_H_
#define _PWM_H_
#include <platform.h>
#include <sys/types.h>
#include <io.h>
#include <lib.h>
int pwm_enable(int pwm_id);
int pwm_disable(int pwm_id);
int pwm_config(int pwm_id, int duty_cycle_us, int period_us);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _RESERVED_MEM_H_
#define _RESERVED_MEM_H_
#include <sys/types.h>
#include <compile.h>
void rsv_mem_init(uint32 start, uint32 len);
void *__rsv_mem_alloc(uint32 bytes, const char *file, int line);
#define reserved_mem_alloc(bytes) \
__rsv_mem_alloc(bytes, __FILENAME__, __LINE__)
void *__rsv_mem_align(uint32 alignment, uint32 bytes, const char *file, int line);
#define reserved_mem_align(alignment, bytes) \
__rsv_mem_align(alignment, bytes, __FILENAME__, __LINE__)
void dump_rsv_mem_info(void);
#endif /* ifndef _RESERVED_MEM_H_ */
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __SERIAL_H__
#define __SERIAL_H__
#include <sys/types.h>
/*-----------------------------------------------------------------
* serial interface
------------------------------------------------------------------*/
void serial_init(void);
void serial_putc(const char c);
void serial_puts(const char *s);
void serial_puts_always(const char *s);
void serial_put_dec(u32 dec);
void serial_put_hex(u32 hex);
void serial_put_hex_always(u32 hex);
char serial_getc(void);
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef _STDARG_H_
#define _STDARG_H_
/******************************************************************************/
typedef __builtin_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
/******************************************************************************/
#endif /* _STDARG_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
#define true 1
#define false 0
#endif /* ifndef _STDBOOL_H_ */
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __STDDEFH__
#define __STDDEFH__
#include <sys/types.h>
#include <ctype.h>
#define _1K (0x400)
#define _2K (0x800)
#define _4K (0x1000)
#define _8K (0x2000)
#define _16K (0x4000)
#define _32K (0x8000)
#define _64K (0x10000)
#define _128K (0x20000)
#define _256K (0x40000)
#define _512K (0x80000)
#define _1M (0x100000)
#define _2M (0x200000)
#define _4M (0x400000)
#define _8M (0x800000)
#define _16M (0x1000000)
#define _32M (0x2000000)
#define _64M (0x4000000)
#define _128M (0x8000000)
#define _256M (0x10000000)
#define _512M (0x20000000)
#define _1G (0x40000000)
#define _2G (0x80000000)
#define _3G (0xC0000000)
#define _4G (0x100000000ULL)
#define _8G (0x200000000ULL)
#define _16G (0x400000000ULL)
#define _32G (0x800000000ULL)
#define _64G (0x1000000000ULL)
#endif /* __STDDEFH__ */
+7
View File
@@ -0,0 +1,7 @@
#ifndef _STDINT_H_
#define _STDINT_H_
#include <sys/types.h>
#endif
+54
View File
@@ -0,0 +1,54 @@
#ifndef _STDIO_H_
#define _STDIO_H_
/******************************************************************************/
#include <config.h>
#include <stddef.h>
int sprintf(char *buf, const char *cfmt, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int getchar(void);
void puts_always(const char *s);
void puthex_always(unsigned int hex);
#ifdef CONFIG_PRINT
#ifdef CONFIG_PRINTF
int printf(const char *cfmt, ...);
#else
# define printf(_cfmt, ...)
#endif
int putchar(int c);
int puts(const char *s);
void puthex(unsigned int hex);
void putdec(unsigned int dec);
#else
# define printf(_cfmt, ...)
# define putchar(c)
# define puts(_s)
# define puthex(hex)
# define putdec(dec)
#endif
#ifndef MOULE_NAME
#define MOULE_NAME ""
#endif
#define pr_error(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#define pr_warn(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#define pr_info(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#ifdef PR_DEBUG
# define pr_debug(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#else
# define pr_debug(_fmt, args...)
#endif /* pr_debug */
#define bug(_fmt, args...) { \
printf(MOULE_NAME "%s(%d): "_fmt, __FILE__, __LINE__, ##args); \
while (1); }
/******************************************************************************/
#endif /* _STDIO_H_ */
+7
View File
@@ -0,0 +1,7 @@
#ifndef _STDLIB_H_
#define _STDLIB_H_
#include <malloc.h>
#endif /* _STDLIB_H_ */
+41
View File
@@ -0,0 +1,41 @@
#ifndef _STRING_H_
#define _STRING_H_
/******************************************************************************/
#include <stddef.h>
extern char const hex2ascii_data[];
#define hex2ascii(hex) (hex2ascii_data[hex])
#define imax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define bcpy(src, dst, len) memcpy((dst), (src), (len))
#define bzero(buf, size) memset((buf), 0, (size))
#define bcmp(b1, b2, len) (memcmp((b1), (b2), (len)) != 0)
void *memmove(void *dest, const void *src, size_t size);
void *memcpy(void *dst, const void *src, size_t len);
void *memset(void *b, int c, size_t len);
int memcmp(const void *b1, const void *b2, size_t len);
int strncmp(const char *s1, const char *s2, size_t len);
uint32_t strnlen(const char *s, uint32_t len);
unsigned long strtoul(const char *nptr, char **endptr, int base);
uint64_t strtoull(const char *nptr, char **endptr, int base);
char *strncpy(char * dst, const char * src, size_t n);
uint64_t memparse(const char *ptr, char **retptr);
char *strndup(const char *str, size_t n);
char *strtok(char *s, const char *delim);
int strcmp(const char *s1, const char *s2);
void strcpy(char *dst, const char *src);
void strcat(char *dst, const char *src);
char *strncat(char *dst, const char *src, size_t n);
char *strchr(const char *s, char ch);
char *strdup(const char *s);
size_t strlen(const char *s);
char *strstr(const char *s1, const char *s2);
/******************************************************************************/
#endif /* _STRING_H_ */
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __TYPES_H__
#define __TYPES_H__
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef long long intmax_t;
typedef unsigned long long uintmax_t;
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef unsigned int uint;
typedef unsigned char uint8;
typedef char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
typedef unsigned long uintptr_t;
typedef unsigned int size_t;
#define BITS_PER_LONG 32
#undef NULL
#define NULL ((void *)0)
typedef int bool;
#define true 1
#define false 0
#define ERROR -1
#define OK 0
#define SZ_4M 0x400000
#define SZ_8M 0x800000
#define SZ_16M 0x1000000
#define SZ_128M 0x8000000
#define SZ_256M 0x10000000
#define SZ_512M 0x20000000
#define SZ_750M 0x30000000
#define SZ_1G 0x40000000
#define SZ_2G 0x80000000
#define SZ_3G 0xc0000000
#define SZ_4G 0x100000000
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef _TIME_H_
#define _TIME_H_
#include <timer.h>
#endif /* _TIME_H_ */
+16
View File
@@ -0,0 +1,16 @@
#ifndef _TIMER_H_
#define _TIMER_H_
#include <sys/types.h>
#include <io.h>
#include <lib.h>
void timer_init(void);
void timer_start(void);
ulong timer_get_val(void);
void udelay(ulong us);
void mdelay(u32 msec);
#endif /* _TIMER_H_ */
+15
View File
@@ -0,0 +1,15 @@
#ifndef _UT_CASE_H_
#define _UT_CASE_H_
void test_math(void);
void test_libc(void);
void test_time(void);
void test_multi_stage_in_stage1(void);
void test_multi_stage_in_stage2(void);
void test_submakefile1(void);
void test_reserved_mem(void);
int run_ut_in_stage1(void);
int run_ut_in_stage2(void);
#endif /* ifndef _UT_CASE_H_ */
+7
View File
@@ -0,0 +1,7 @@
#ifndef __VERSION_H__
#define __VERSION_H__
#define MCU_VERSION "v1.00"
#endif
+3
View File
@@ -0,0 +1,3 @@
SRCS-y += main.c
SRCS-$(CONFIG_SIMPILE_SHELL) += shell.c
+63
View File
@@ -0,0 +1,63 @@
#include <platform.h>
#include <sys/types.h>
#include <common.h>
#include <version.h>
#include <timer.h>
#include <image.h>
#include <i2c.h>
#include <ut_case.h>
#include "media_sample.h"
int *__errno(void)
{
return NULL;
}
void show_version(void)
{
#ifdef CONFIG_DEBUG_INFO
puts("\nRISC-V MCU code - ");
puts(MCU_VERSION"\n");
puts("Build: ");
puts(__DATE__" - "__TIME__"\n");
puts("\n");
#endif
}
unsigned int main(void)
{
__attribute__((unused)) int ret;
show_version();
#ifdef CONFIG_MEDIA_SAMPLE_QUICKSTART
quickstart_media_preinit();
ret = run_stage2_func(quickstart_media_start);
if (ret != 0) {
puts("UT is Failed\n");
goto sleep;
}
#endif
#ifdef CONFIG_UT_ENABLE
ret = run_ut_in_stage1();
if (ret != 0) {
puts("UT in stage1 Failed\n");
goto sleep;
}
ret = run_stage2_func(run_ut_in_stage2);
if (ret != 0) {
puts("UT in stage2 Failed\n");
goto sleep;
}
#endif
#ifdef CONFIG_SIMPILE_SHELL
start_shell();
#endif
sleep: __attribute__((unused))
while(1) {
__WFI();
}
return 0;
}
+289
View File
@@ -0,0 +1,289 @@
#include <stdio.h>
#include <string.h>
#include <config.h>
#include <lib.h>
#include <timer.h>
#include <serial.h>
#define CMD_BUFF_LEN 16
#define REV_BUFF_LEN 128
typedef enum {
CMD_0 = 0,
CMD_1,
CMD_2,
CMD_3,
CMD_4,
CMD_5,
CMD_6,
CMD_7,
CMD_8,
CMD_9,
CMD_10,
CMD_11,
CMD_12,
CMD_13,
CMD_14,
CMD_15,
CMD_16
} cmd_len;
static void show_help(void)
{
puts("usage: \n");
puts(" help -- show command infomation \n");
puts(" mw [addr] [value] -- write [value] to [addr] \n");
puts(" both need be hex and start with 0x or 0X \n");
puts(" md [addr] [length] -- read from [addr] and print to the console \n");
puts(" total read [length] bytes data \n");
puts(" both need be hex and start with 0x or 0X \n");
}
static u32 read_line(u8 *buff, u32 buff_len)
{
u32 recv_len = 0;
char c = 0;
while (1) {
c = getchar();
if (c == '\n' || c == '\r') {
serial_putc('\n');
break;
}
if (recv_len < buff_len) {
serial_putc(c);
buff[recv_len++] = c;
} else {
return FAILURE;
}
}
if (recv_len < (buff_len - 1)) {
buff[recv_len + 1] = '\0';
}
return recv_len;
}
/* return value : index is started from 0 */
static u32 str_get_pos(u8 *buff, u32 buff_len, char c)
{
u32 index = 0;
for (; index < buff_len; index++) {
if (c == buff[index]) {
return index;
}
}
if (index == buff_len) {
return index;
}
return FAILURE;
}
/* find the cmd dilived by the space */
static u32 get_cmd(u8 *cmd, u32 cmd_buff_len, u8 *buff, u32 buff_len)
{
u32 cmd_len = 0;
/* the cmd is divided by space */
cmd_len = str_get_pos(buff, buff_len, ' ');
if (cmd_len == 0 || cmd_len == FAILURE || cmd_len > cmd_buff_len) {
return FAILURE;
}
for (u32 i = 0; i < cmd_len; i++) {
cmd[i] = buff[i];
}
if (cmd_len < (cmd_buff_len - 1)) {
cmd[cmd_len + 1] = '\0';
}
return cmd_len;
}
static u8 char_to_hex(u8 value)
{
if((value <= '9') && (value >= '0')) {
return (value - '0');
} else if ((value <= 'f') && ((value >= 'a'))) {
return (value - 'a' + 0x0a);
} else if ((value <= 'F') && (value >= 'A')) {
return (value - 'A' + 0x0a);
} else {
puts("Data format error!\n");
return -1;
}
}
static u32 pow_t(u32 v, u32 n)
{
u32 value = v;
if (n == 0) {
return 1;
} else if (n == 1) {
return v;
}
for (u32 i = 1; i < n; i++) {
value = value * v;
}
return value;
}
static u32 str_to_hex(u8 *str, u32 str_len)
{
u32 hex = 0;
for (int i = 0; i < str_len; i++) {
hex += char_to_hex(str[i]) * pow_t(16, (str_len - i - 1));
}
return hex;
}
static u32 get_params(u8 * buff, u32 buff_Len, u32 *param_len)
{
u8 param_s[10];
*param_len = get_cmd(param_s, 10, buff, buff_Len);
if (*param_len < 2 || *param_len == FAILURE) {
puts("command error, too few params!\n");
return FAILURE;
}
if (param_s[0] != '0' && (param_s[1] != 'x' || param_s[1] != 'X')) {
puts("command error, params should start with 0x or 0X\n");
return FAILURE;
}
return str_to_hex(param_s + 2, *param_len - 2);
}
/*
* input: [addr] [value]
*/
void memory_write(u8 *buff, u32 buff_Len)
{
u32 addr_len = 0;
u32 value_len = 0;
u32 addr = 0;
u32 value = 0;
/* get address */
addr = get_params(buff, buff_Len, &addr_len);
if (addr == FAILURE) {
return;
}
/* get value */
value = get_params(buff + addr_len + 1, buff_Len - addr_len - 1, &value_len);
if (value == FAILURE) {
return;
}
puts("write address=0x");
serial_put_hex(addr);
puts(" value=0x");
serial_put_hex(value);
puts("\n");
writel(value, addr);
}
/*
* input: [addr] [length]
*/
void memory_read(u8 *buff, u32 buff_Len)
{
u32 addr_len = 0;
u32 length_len = 0;
u32 addr = 0;
u32 length = 0;
u32 value = 0;
/* get address */
addr = get_params(buff, buff_Len, &addr_len);
if (addr == FAILURE) {
return;
}
/* get length */
length = get_params(buff + addr_len + 1, buff_Len - addr_len - 1, &length_len);
if (length == FAILURE) {
return;
}
if (length % 4 != 0) {
puts("error: length should be align with 4\n");
return;
}
/* read and print */
for (u32 i = 0; i < length / 4; i++) {
value = readl(addr + i * 4);
if (i % 4 == 0) {
serial_put_hex(addr + i * 4);
puts(": ");
}
serial_put_hex(value);
puts(" ");
if (i % 4 == 3) {
puts("\n");
}
}
puts("\n");
}
u32 start_shell(void)
{
u8 buff[REV_BUFF_LEN];
u32 recv_len = 0;
u8 cmd[CMD_BUFF_LEN];
u32 cmd_len = 0;
puts("\n## Micro shell ##\n");
/* cmd [param1] [param2] ... */
while (1) {
puts("# ");
memset_s(buff, REV_BUFF_LEN, 0, REV_BUFF_LEN);
memset_s(cmd, CMD_BUFF_LEN, 0, CMD_BUFF_LEN);
recv_len = read_line(buff, REV_BUFF_LEN);
if (recv_len == 0 || recv_len == FAILURE) {
continue;
}
cmd_len = get_cmd(cmd, CMD_BUFF_LEN, buff, recv_len);
if (cmd_len == FAILURE) {
continue;
}
switch (cmd_len) {
case CMD_2:
if (memcmp(cmd, "mw", CMD_2) == SUCCESS) {
/* mw [addr] [value]; addr and value should start with 0x/0X */
memory_write(buff + cmd_len + 1, recv_len - cmd_len - 1);
} else if (memcmp(cmd, "md", CMD_2) == SUCCESS) {
/* md [addr] [length]; addr and length should start with 0x/0X */
memory_read(buff + cmd_len + 1, recv_len - cmd_len - 1);
}
break;
case CMD_4:
if (memcmp(cmd, "help", CMD_4) == SUCCESS) {
show_help();
}
default:
puts("Unknown command!\n");
break;
}
}
return SUCCESS;
}
+8
View File
@@ -0,0 +1,8 @@
SRCS-y += lib.c stdio.c div64.c
SRCS-$(CONFIG_PRINTF) += printf.c
ifdef CONFIG_MALLOC
SRCS-y += malloc.c memlib.c
else
SRCS-y += simple_malloc.c
endif
SRCS-y += reserved_mem.c
+34
View File
@@ -0,0 +1,34 @@
#include <sys/types.h>
uint32_t __div64_32(uint64_t *n, uint32_t base)
{
uint64_t rem = *n;
uint64_t b = base;
uint64_t res, d = 1;
uint32_t high = rem >> 32;
res = 0;
if (high >= base) {
high /= base;
res = (uint64_t) high << 32;
rem -= (uint64_t) (high * base) << 32;
}
while ((int64_t)b > 0 && b < rem) {
b = b + b;
d = d + d;
}
do {
if (rem >= b) {
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);
*n = res;
return rem;
}
+216
View File
@@ -0,0 +1,216 @@
#include <stdio.h>
#include <lib.h>
#include <serial.h>
int memset_s(void* dest, size_t destMax, unsigned char c, size_t count)
{
unsigned char *__dest = (unsigned char *)dest;
if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
return FAILURE;
}
if (__dest == NULL) {
return FAILURE;
}
if (count > destMax) {
while (destMax--)
*__dest++ = (unsigned char)c; /*set entire buffer to value c*/
return FAILURE;
}
while (count--)
*__dest++ = (unsigned char)c;
return SUCCESS;
}
int memset(void* dest, unsigned char c, size_t count)
{
return memset_s(dest, SECUREC_MEM_MAX_LEN, c, count);
}
int memcpy_s(void* dest, size_t destMax, const void* src, size_t count)
{
unsigned char *__dest = (unsigned char *)dest;
unsigned char *__src = (unsigned char *)src;
if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN ) {
return FAILURE;
}
if (__dest == NULL || __src == NULL) {
if (__dest != NULL ) {
while (destMax--)
*__dest++ = 0; /*set entire buffer to value 0 */
return FAILURE;
}
return FAILURE;
}
if (count > destMax) {
while (destMax--)
*__dest++ = 0; /*set entire buffer to value 0 */
return FAILURE;
}
if (__dest == __src) {
return SUCCESS;
}
if ((__dest > __src && __dest < ((u8*)__src + count)) ||
(__src > __dest && __src < ((u8*)__dest + count)) ) {
while (destMax--)
*__dest++ = 0; /*set entire buffer to value 0 */
return FAILURE;
}
while (count--)
*__dest++ = *__src++;
return SUCCESS;
}
void *memcpy(void *dst, const void *src, size_t len)
{
if(SUCCESS == memcpy_s(dst, len, src, len))
return dst;
return NULL;
}
int memcmp(const void *b1, const void *b2, size_t len)
{
int res = 0;
const char *d = b1;
const char *s = b2;
if (b1 == NULL || b2 == NULL) {
puts("memcmp : Invalid args\n");
return res;
}
while (len > 0) {
res = *d - *s;
if (res != 0)
break;
d++;
s++;
len--;
}
return res;
}
u32 strlen(const char * s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
char *strcat(char *dest, const char *src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0')
;
return tmp;
}
char *strcpy(char *dest, const char*src)
{
char *tmp = dest;
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return tmp;
}
char *strncpy(char *dest, char *src, size_t n)
{
char *tmp = dest;
while (n > 0 && *src != '\0') {
*dest = *src;
dest++;
src++;
n--;
}
while (n > 0) {
*dest = '\0';
dest++;
n--;
}
return tmp;
}
int strcmp(const char *s1, const char *s2) {
while (*s1 && (*s1 == *s2)) {
s1++;
s2++;
}
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}
int strncmp(const char *s1, const char *s2, size_t n) {
if (n == 0)
return 0;
do {
if (*s1 != *s2++)
return *(const unsigned char*)s1 - *(const unsigned char*)--s2;
if (*s1++ == 0)
break;
} while (--n != 0);
return 0;
}
/*****************************************************************************/
/* for gcc -fstack-protector-all */
unsigned long __stack_chk_guard = 0x000a0dff;
void __stack_chk_fail(void)
{
serial_puts("Stack is corrupted\n");
while (1) {
reset_cpu();
}
}
unsigned short crc16(unsigned char *data, unsigned int length)
{
unsigned int i;
unsigned short crc_table;
unsigned short crc = 0xffff;
unsigned char inter1;
unsigned char inter2;
if (data == NULL)
return (crc);
for (i = 0; i < length; ++i) {
inter1 = data[i] ^ ((unsigned char) crc);
inter2 = (unsigned char) (inter1 ^ (inter1 << 4)); /* bit size 4 */
crc_table = (inter2 << 8) ^ (inter2 << 3) ^ (inter2 >> 4); /* bit size 8 3 4 */
crc = (crc >> 8) ^ crc_table; /* bit size 8 */
}
crc ^= 0xffff;
return (crc);
}
+46
View File
@@ -0,0 +1,46 @@
#include <stddef.h>
#include <hlist.h>
#include "memlib.h"
static struct list g_malloc_list = {0};
void malloc_init(unsigned int base, unsigned int size)
{
if ((g_malloc_list.base.next != NULL) && (g_malloc_list.base.prev != NULL)) {
return;
}
memlib_init(&g_malloc_list, base, size);
}
void *malloc(uint32 bytes)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return NULL;
}
return memlib_malloc(&g_malloc_list, bytes);
}
void *memalign(uint32 alignment, uint32 bytes)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return NULL;
}
return memlib_memalign(&g_malloc_list, alignment, bytes);
}
void free(void *ptr)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return;
}
memlib_free(&g_malloc_list, ptr);
}
void show_memnode(unsigned int cnt)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return;
}
memlib_show_memnode(&g_malloc_list, cnt);
}
+205
View File
@@ -0,0 +1,205 @@
#include <stddef.h>
#include <hlist.h>
#include <stdio.h>
#define MEM_ALLOC_MAGIC_NUM 0xACCA5995
typedef struct _mem_node {
uint32 magicnum;
struct node nodeinfo;
/* Size & flag of the current node (the high two bits represent a flag,and the rest bits specify the size) */
uint32 size_flag;
}mem_node;
uint32 g_heap_start = 0;
uint32 g_heap_end = 0;
#define around(size, align) (((size) + (align) - 1) & (~((align) - 1)))
#define MEM_NODE_HEAD_SIZE sizeof(struct _mem_node)
#define MEM_ALIGN_SIZE 4
#define MEM_NODE_USED_FLAG 0x80000000U
#define MEM_NODE_ALIGNED_FLAG 0x40000000U
#define MEM_NODE_ALIGNED_AND_USED_FLAG (MEM_NODE_USED_FLAG | MEM_NODE_ALIGNED_FLAG)
#define mem_node_get_used_flag(size_flag) ((size_flag) & MEM_NODE_USED_FLAG)
#define mem_node_set_used_flag(size_flag) ((size_flag) = ((size_flag) | MEM_NODE_USED_FLAG))
#define mem_node_get_aligned_gapsize(sizeAndFlag) ((sizeAndFlag) & ~MEM_NODE_ALIGNED_FLAG)
#define mem_node_get_aligned_flag(size_flag) ((size_flag) & MEM_NODE_ALIGNED_FLAG)
#define mem_node_set_aligned_flag(size_flag) ((size_flag) = ((size_flag) | MEM_NODE_ALIGNED_FLAG))
#define mem_node_get_size(size_flag) ((size_flag) & ~MEM_NODE_ALIGNED_AND_USED_FLAG)
#define mem_node_clear_used_aligned_flag(size_flag) ((size_flag) = (size_flag) & (~ (MEM_NODE_ALIGNED_AND_USED_FLAG)))
#define is_pow_two(value) ((((uintptr_t)(value)) & ((uintptr_t)(value) - 1)) == 0)
#define is_aligned(value, alignSize) ((((uintptr_t)(value)) & ((uintptr_t)((alignSize) - 1))) == 0)
void memlib_init(struct list *listhead, unsigned int base, unsigned int size)
{
mem_node *firstnode = (mem_node *)(uintptr_t)(base);
if (mem_node_get_used_flag(size) || mem_node_get_aligned_flag(size)) {
printf("malloc init failed, size:0x%x\n", size);
return;
}
list_init(listhead);
firstnode->magicnum = MEM_ALLOC_MAGIC_NUM;
firstnode->size_flag = size;
list_add_tail(listhead, &firstnode->nodeinfo);
g_heap_start = base;
g_heap_end = base + size;
#ifdef CONFIG_DEBUG_INFO
puts("malloc init,base: 0x");puthex(g_heap_start);puts(", size: ");putdec(size);puts("\n");
#endif
}
static void *mem_find_freeblock(struct list *listhead, uint32 allocsize)
{
mem_node *entry = NULL;
mem_node *tmp = NULL;
mem_node *newnode = NULL;
unsigned int nodesize;
list_for_each_entry_safe(entry, tmp, listhead, mem_node, nodeinfo) {
nodesize = mem_node_get_size(entry->size_flag);
if ((!mem_node_get_used_flag(entry->size_flag)) && nodesize >= allocsize) {
if ((nodesize - allocsize) < (MEM_NODE_HEAD_SIZE + MEM_ALIGN_SIZE)) {
mem_node_set_used_flag(entry->size_flag);
return entry + 1;
} else {
newnode = (mem_node *)((uintptr_t)entry + allocsize);
newnode->magicnum = MEM_ALLOC_MAGIC_NUM;
newnode->size_flag = entry->size_flag - allocsize;
entry->size_flag = allocsize;
mem_node_set_used_flag(entry->size_flag);
list_insert_backward(&entry->nodeinfo, &newnode->nodeinfo); /* newnode 插入到 entry 后面 */
return entry + 1;
}
}
}
printf("no suitable free mem block\n");
return NULL;
}
void *memlib_malloc(struct list *listhead, uint32 bytes)
{
void *ptr = NULL;
if (bytes == 0) {
return NULL;
}
uint32 allocsize = around(bytes + MEM_NODE_HEAD_SIZE, MEM_ALIGN_SIZE);
ptr = mem_find_freeblock(listhead, allocsize);
return ptr;
}
void *memlib_memalign(struct list *listhead, uint32 alignment, uint32 bytes)
{
uint32 gap_size;
uint32 use_size;
void *ptr = NULL;
void *align_ptr = NULL;
mem_node *node = NULL;
if (bytes == 0 || alignment == 0 || !is_pow_two(alignment) || !is_aligned(alignment, sizeof(void*))) {
return NULL;
}
/*
* sizeof(gap_size) bytes stores offset between align_ptr and ptr,
* the ptr has been OS_MEM_ALIGN_SIZE(4 or 8) aligned, so maximum
* offset between alignedPtr and ptr is alignment - OS_MEM_ALIGN_SIZE
*/
if ((alignment - sizeof(gap_size)) > ((uint32)(-1) - bytes)) {
return NULL;
}
use_size = around(bytes + MEM_NODE_HEAD_SIZE + alignment - sizeof(gap_size), MEM_ALIGN_SIZE);
if (mem_node_get_used_flag(use_size) || mem_node_get_aligned_flag(use_size)) {
printf("size is too large:0x%x\n", use_size);
return NULL;
}
ptr = mem_find_freeblock(listhead, use_size);
if (ptr == NULL) {
return NULL;
}
align_ptr = (void *)around((uintptr_t)ptr, alignment);
if (ptr == align_ptr) {
return ptr;
}
gap_size = (uintptr_t)align_ptr - (uintptr_t)ptr;
mem_node_set_aligned_flag(gap_size);
node = (mem_node *)ptr - 1;
mem_node_set_aligned_flag(node->size_flag);
*(uint32 *)((uintptr_t)align_ptr - sizeof(gap_size)) = gap_size;
ptr = align_ptr;
return ptr;
}
void *memptr_to_node(void *ptr)
{
uint32 gapsize;
if (((uintptr_t)ptr) & (MEM_ALIGN_SIZE - 1)) {
printf("ptr not align by 4byte\n");
return NULL;
}
gapsize = *(uint32 *)((uintptr_t)ptr - sizeof(uint32));
if (mem_node_get_aligned_flag(gapsize) && mem_node_get_used_flag(gapsize)) {
printf("gapsize:0x%x error\n", gapsize);
return NULL;
}
if (mem_node_get_aligned_flag(gapsize)) {
gapsize = mem_node_get_aligned_gapsize(gapsize);
if ((gapsize & (MEM_ALIGN_SIZE - 1)) || (gapsize > ((uintptr_t)ptr - MEM_NODE_HEAD_SIZE))) {
return NULL;
}
ptr = (void *)((uintptr_t)ptr - gapsize);
}
return (void *)((uintptr_t)ptr - MEM_NODE_HEAD_SIZE);
}
void memlib_free(struct list *listhead, void *ptr)
{
mem_node *entry = NULL;
mem_node *next_entry = NULL;
mem_node *pre_entry = NULL;
if (ptr == NULL) {
return;
}
entry = (mem_node *)memptr_to_node(ptr);
if (entry == NULL) {
return;
}
if (entry->magicnum != MEM_ALLOC_MAGIC_NUM) {
printf("MAGIC NUM is wrong! magicnum:0x%x\n", entry->magicnum);
return;
}
if (!mem_node_get_used_flag(entry->size_flag)) {
return;
}
mem_node_clear_used_aligned_flag(entry->size_flag);
next_entry = list_next_entry(entry, listhead, mem_node, nodeinfo);
if (next_entry != NULL) {
if (!mem_node_get_used_flag(next_entry->size_flag)) {
entry->size_flag += next_entry->size_flag;
next_entry->magicnum = 0;
list_remove(&next_entry->nodeinfo);
}
}
pre_entry = list_prev_entry(entry, listhead, mem_node, nodeinfo);
if (pre_entry != NULL) {
if (!mem_node_get_used_flag(pre_entry->size_flag)) {
pre_entry->size_flag += entry->size_flag;
entry->magicnum = 0;
list_remove(&entry->nodeinfo);
}
}
}
void memlib_show_memnode(struct list *listhead, unsigned int cnt)
{
mem_node *entry = NULL;
uint32 i = 0;
list_for_each_entry(entry, listhead, mem_node, nodeinfo) {
printf("%d:entry, magic:0x%x, size: %d, used:0x%x, aligned:0x%x\n", i++, entry->magicnum,
mem_node_get_size(entry->size_flag), mem_node_get_used_flag(entry->size_flag),
mem_node_get_aligned_flag(entry->size_flag));
if (cnt != 0 && i == cnt) {
break;
}
}
}

Some files were not shown because too many files have changed in this diff Show More