精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)核之ISP驅(qū)動(dòng)流程分析

冬至配餃子 ? 來(lái)源:嵌入式軟件開(kāi)發(fā)交流 ? 作者:young ? 2022-08-07 16:13 ? 次閱讀

ISP驅(qū)動(dòng)分析

Linux版本: 4.19

芯片平臺(tái): RK3399/RK3288

源碼路徑:

drivers/media/platform/rk-isp10/cif_isp10_v4l2.c

drivers/media/platform/rk-isp10/cif_isp10.c

(1)裝載和卸載函數(shù)

//DTS匹配

static const struct of_device_id cif_isp10_v4l2_of_match[] = {

{.compatible = "rockchip,rk3288-cif-isp",

.data = (void *)&rk3288_cfg},

{.compatible = "rockchip,rk3399-cif-isp",

.data = (void *)&rk3399_cfg},

{},

};

static struct platform_driver cif_isp10_v4l2_plat_drv = {

.driver = {

.name = DRIVER_NAME,

.of_match_table = of_match_ptr(cif_isp10_v4l2_of_match),

.pm = &cif_isp10_dev_pm_ops,

},

.probe = cif_isp10_v4l2_drv_probe,

.remove = cif_isp10_v4l2_drv_remove,

.suspend = cif_isp10_v4l2_drv_suspend,

.resume = cif_isp10_v4l2_drv_resume,

};

static int cif_isp10_v4l2_init(void)

{

int ret;

g_cif_isp10_v4l2_dev_cnt = 0;

ret = platform_driver_register(&cif_isp10_v4l2_plat_drv); //注冊(cè)platform_driver

if (ret) {

cif_isp10_pltfrm_pr_err(NULL,

"cannot register platform driver, failed with %d\n",

ret);

return -ENODEV;

}

return ret;

}

static void __exit cif_isp10_v4l2_exit(void)

{

platform_driver_unregister(&cif_isp10_v4l2_plat_drv);

}

上面就是簡(jiǎn)單地注冊(cè)了一個(gè)platform設(shè)備。

(2)probe()

static int cif_isp10_v4l2_drv_probe(struct platform_device *pdev)

{

const struct of_device_id *match;

struct device_node *node = pdev->dev.of_node;

struct cif_isp10_device *dev = NULL;

struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev;

int ret;

//........

//分配cif_isp10_v4l2_device

cif_isp10_v4l2_dev = devm_kzalloc(

&pdev->dev,

sizeof(struct cif_isp10_v4l2_device),

GFP_KERNEL);

//.....

match = of_match_node(cif_isp10_v4l2_of_match, node); //獲取匹配的是RK3288還是RK3399

dev = cif_isp10_create(&pdev->dev, //創(chuàng)建cif_isp10_device

cif_isp10_v4l2_event,

cif_isp10_v4l2_requeue_bufs,

(struct pltfrm_soc_cfg *)match->data);

//......

dev->dev_id = g_cif_isp10_v4l2_dev_cnt;

dev->isp_dev.dev_id = &dev->dev_id;

dev->nodes = (void *)cif_isp10_v4l2_dev;

dev->isp_state = CIF_ISP10_STATE_IDLE;

spin_lock_init(&dev->vbq_lock);

spin_lock_init(&dev->vbreq_lock);

spin_lock_init(&dev->iowrite32_verify_lock);

spin_lock_init(&dev->isp_state_lock);

init_waitqueue_head(&dev->isp_stop_wait);

mutex_init(&dev->api_mutex);

ret = v4l2_device_register(dev->dev, &dev->v4l2_dev); //注冊(cè)v4l2_device

//......

ret = cif_isp10_v4l2_register_video_device( //注冊(cè)video_device, 即生成/dev/videox節(jié)點(diǎn),該節(jié)點(diǎn)具有VIDEO_OVERLAY功能

dev,

&cif_isp10_v4l2_dev->node[SP_DEV].vdev, //SP:selfpath

SP_VDEV_NAME,

V4L2_CAP_VIDEO_OVERLAY,

CIF_ISP10_V4L2_SP_DEV_MAJOR,

&cif_isp10_v4l2_fops,

&cif_isp10_v4l2_sp_ioctlops);

if (ret)

goto err;

ret = register_cifisp_device(&dev->isp_dev, //注冊(cè)ISP video_device

&cif_isp10_v4l2_dev->node[ISP_DEV].vdev,

&dev->v4l2_dev,

dev->config.base_addr);

if (ret)

goto err;

ret = cif_isp10_v4l2_register_video_device( //注冊(cè)video_device, 即生成/dev/videox節(jié)點(diǎn),該節(jié)點(diǎn)具有VIDEO_CAPTURE功能

dev,

&cif_isp10_v4l2_dev->node[MP_DEV].vdev, //MP:mainpath

MP_VDEV_NAME,

V4L2_CAP_VIDEO_CAPTURE,

CIF_ISP10_V4L2_MP_DEV_MAJOR,

&cif_isp10_v4l2_fops,

&cif_isp10_v4l2_mp_ioctlops);

if (ret)

goto err;

ret = cif_isp10_v4l2_register_video_device( //注冊(cè)video_device, 即生成/dev/videox節(jié)點(diǎn),該節(jié)點(diǎn)具有VIDEO_OUTPUT功能

dev,

&cif_isp10_v4l2_dev->node[DMA_DEV].vdev,

DMA_VDEV_NAME,

V4L2_CAP_VIDEO_OUTPUT,

CIF_ISP10_V4L2_DMA_DEV_MAJOR,

&cif_isp10_v4l2_fops,

&cif_isp10_v4l2_dma_ioctlops);

if (ret)

goto err;

cif_isp10_v4l2_register_imgsrc_subdev( //注冊(cè)v4l2_subdev,關(guān)聯(lián)v4l2_device和v4l2_subdev

dev);

pm_runtime_enable(&pdev->dev);

g_cif_isp10_v4l2_dev[g_cif_isp10_v4l2_dev_cnt] =

cif_isp10_v4l2_dev;

g_cif_isp10_v4l2_dev_cnt++;

return 0;

err:

cif_isp10_destroy(dev);

return ret;

}

上面主要做了:

(1)創(chuàng)建和初始化cif_isp10_device,該結(jié)構(gòu)體中保存著從DTS中解析出來(lái)的信息

(2)注冊(cè)v4l2_device

(3)注冊(cè)了4個(gè)video_device:

rkisp1_ispdev:ISP設(shè)備

rkisp1_selfpath: 圖像捕獲設(shè)備

rkisp1_mainpath: 圖像捕獲設(shè)備,用于高分辨率

rkisp1_dmapath: DMA設(shè)備

(4)注冊(cè)v4l2_subdev, 將v4l2_device和v4l2_subdev關(guān)聯(lián)到一起。

*注意: 應(yīng)用層就是通過(guò)訪問(wèn)video_device生成的節(jié)點(diǎn)來(lái)進(jìn)行操作Camera,所以video_device注冊(cè)時(shí)指定了很多ioctl函數(shù)。

(3)創(chuàng)建cif_isp10_device

struct cif_isp10_device *cif_isp10_create(

CIF_ISP10_PLTFRM_DEVICE pdev,

void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence),

void (*requeue_bufs)(struct cif_isp10_device *dev,

enum cif_isp10_stream_id stream_id),

struct pltfrm_soc_cfg *soc_cfg)

{

int ret;

struct cif_isp10_device *dev;

cif_isp10_pltfrm_pr_dbg(NULL, "\n");

//分配結(jié)構(gòu)體

dev = kzalloc(sizeof(*dev), GFP_KERNEL);

//......

dev->sof_event = sof_event;

dev->requeue_bufs = requeue_bufs;

ret = cif_isp10_pltfrm_dev_init(dev,

&pdev, &dev->config.base_addr); //平臺(tái)初始化(重映射寄存器地址,申請(qǐng)中斷等)

cif_isp10_pltfrm_soc_init(dev, soc_cfg); //soc相關(guān)初始化(ISP,DPHY等時(shí)鐘初始化)

ret = cif_isp10_img_srcs_init(dev); //初始化圖像源,即ISP連接的Camera

ret = cif_isp10_register_isrs(dev); //注冊(cè)中斷處理函數(shù) (ISR, Interrupt Service Routine),

//......

dev->pm_state = CIF_ISP10_PM_STATE_OFF;

dev->sp_stream.state = CIF_ISP10_STATE_DISABLED;

dev->sp_stream.id = CIF_ISP10_STREAM_SP;

dev->mp_stream.state = CIF_ISP10_STATE_DISABLED;

dev->mp_stream.id = CIF_ISP10_STREAM_MP;

dev->dma_stream.state = CIF_ISP10_STATE_DISABLED;

dev->dma_stream.id = CIF_ISP10_STREAM_DMA;

dev->config.mi_config.async_updt = 0;

(void)cif_isp10_init(dev, CIF_ISP10_ALL_STREAMS); //初始化所有的流(SP,MP,DMA)

cif_isp10_pltfrm_event_init(dev->dev, &dev->dma_stream.done);

cif_isp10_pltfrm_event_init(dev->dev, &dev->sp_stream.done);

cif_isp10_pltfrm_event_init(dev->dev, &dev->mp_stream.done);

dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] = 4;

dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX] = 4;

dev->img_src_exps.inited = false;

mutex_init(&dev->img_src_exps.mutex);

memset(&dev->img_src_exps.data, 0x00, sizeof(dev->img_src_exps.data));

spin_lock_init(&dev->img_src_exps.lock);

INIT_LIST_HEAD(&dev->img_src_exps.list);

dev->vs_wq = alloc_workqueue("cif isp10 vs workqueue",

WQ_UNBOUND | WQ_MEM_RECLAIM, 1);

/* TBD: clean this up */

init_output_formats();

return dev;

//省略異常處理.....

}

上面是主要的初始化,包括dts解析,時(shí)鐘設(shè)置,關(guān)聯(lián)Camera等配置。

主要的幾個(gè)初始化函數(shù)就是上面注釋的位置,我們分析一下 cif_isp10_img_srcs_init,它會(huì)獲取ISP上關(guān)聯(lián)的Camera。

static int cif_isp10_img_srcs_init(

struct cif_isp10_device *dev)

{

int ret = 0;

memset(dev->img_src_array, 0x00, sizeof(dev->img_src_array));

dev->img_src_cnt = cif_isp10_pltfrm_get_img_src_device(dev->dev, //獲取ISP上的Camera,最多10個(gè)

dev->img_src_array, CIF_ISP10_NUM_INPUTS);

if (dev->img_src_cnt > 0)

return 0;

dev->img_src_cnt = 0;

ret = -EFAULT;

cif_isp10_pltfrm_pr_err(dev->dev,

"failed with error %d\n", ret);

return ret;

}

int cif_isp10_pltfrm_get_img_src_device(

struct device *dev,

struct cif_isp10_img_src **img_src_array,

unsigned int array_len)

{

struct device_node *node = NULL;

struct device_node *camera_list_node = NULL;

struct i2c_client *client = NULL;

int ret = 0;

int index, size = 0;

const __be32 *phandle;

int num_cameras = 0;

struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);

node = of_node_get(dev->of_node);

//.......

//獲取ISP上關(guān)聯(lián)的Camera

phandle = of_get_property(node,

"rockchip,camera-modules-attached", &size);

//.......

for (index = 0; index < size / sizeof(*phandle); index++) {

camera_list_node = of_parse_phandle(node,

"rockchip,camera-modules-attached", index);

of_node_put(node);

//......

//判斷是不是I2C subdev,是的話就加入到數(shù)組中

if (!strcmp(camera_list_node->type,

"v4l2-i2c-subdev")) {

client = of_find_i2c_device_by_node(

camera_list_node);

//......

} else {

//......

continue;

}

//加到數(shù)組中

img_src_array[num_cameras] =

cif_isp10_img_src_to_img_src(

&client->dev,

&(cif_isp10_dev->soc_cfg));

if (!IS_ERR_OR_NULL(img_src_array[num_cameras])) {

cif_isp10_pltfrm_pr_info(dev,

"%s attach to cif isp10 img_src_array[%d]\n",

cif_isp10_img_src_g_name(

img_src_array[num_cameras]),

num_cameras);

num_cameras++;

if (num_cameras >= array_len) {

cif_isp10_pltfrm_pr_err(dev,

"cif isp10 isn't support > %d 'camera modules attached'\n",

array_len);

break;

}

}

}

return num_cameras;

//省略異常處理.....

}

上面就是獲取DTS中的如下定義:

&cif_isp0 {

rockchip,camera-modules-attached = <&camera0>;

status = "okay";

};

獲取完后保存在數(shù)組中,cif_isp10_v4l2_register_imgsrc_subdev函數(shù)中會(huì)將這些v4l2_subdev和v4l2_device關(guān)聯(lián)。

(4)ioctl

應(yīng)用層調(diào)用ioctl會(huì)先調(diào)用到v4l2_file_operations中的unlocked_ioctl或compat_ioctl32,然后最終會(huì)調(diào)用到v4l2_ioctl_ops中的各個(gè)ioctl。

所以應(yīng)用層對(duì)Camera的控制主要就是通過(guò)ioctl,我們隨便找兩個(gè)看看:

查詢V4L2功能

static int v4l2_querycap(struct file *file,

void *priv, struct v4l2_capability *cap)

{

struct vb2_queue *queue = to_vb2_queue(file);

struct video_device *vdev = video_devdata(file);

struct cif_isp10_device *dev = to_cif_isp10_device(queue);

u32 stream_ids = to_stream_id(file); //獲取id

strcpy(cap->driver, DRIVER_NAME);

strlcpy(cap->card, vdev->name, sizeof(cap->card));

snprintf(cap->bus_info, sizeof(cap->bus_info),

"platform:" DRIVER_NAME "-%03i",

dev->dev_id);

//根據(jù)ID(SP,MP,DMA)返回對(duì)應(yīng)的功能

if (stream_ids == CIF_ISP10_STREAM_SP) {

cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |

V4L2_CAP_STREAMING;

cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE |

V4L2_CAP_STREAMING;

} else if (stream_ids == CIF_ISP10_STREAM_MP) {

cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |

V4L2_CAP_STREAMING;

cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE |

V4L2_CAP_STREAMING;

}

else if (stream_ids == CIF_ISP10_STREAM_DMA)

cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE |

V4L2_CAP_VIDEO_M2M;

cap->capabilities |= V4L2_CAP_DEVICE_CAPS;

cap->device_caps |= V4L2_CAP_DEVICE_CAPS;

return 0;

}

這只是某個(gè)ioctl的處理函數(shù),在內(nèi)部還有非常多,我們就不一一舉例了。因?yàn)镮SP和Camera已經(jīng)關(guān)聯(lián)在一起了,所以ISP中的ioctl會(huì)去調(diào)用Camera驅(qū)動(dòng)中的ioctl。這也就串聯(lián)起來(lái)了!

建議大家可以去網(wǎng)上找個(gè)Camera拍照的應(yīng)用demo,就會(huì)清楚為什么驅(qū)動(dòng)會(huì)分析到ioctl了。

2. 打開(kāi)數(shù)據(jù)流

static int cif_isp10_v4l2_streamon(

struct file *file,

void *priv,

enum v4l2_buf_type buf_type)

{

//......

//打開(kāi)buffer, 準(zhǔn)備接收數(shù)據(jù)流

ret = vb2_streamon(queue, buf_type);

//開(kāi)啟Camera數(shù)據(jù)流。讓數(shù)據(jù)流從Camera流到ISP

ret = cif_isp10_streamon(dev, stream_ids);

if (IS_ERR_VALUE(ret)) {

goto err;

}

return 0;

//......

}

開(kāi)啟隊(duì)列中的buffer,然后調(diào)用Camera中的接口開(kāi)啟數(shù)據(jù)流,讓數(shù)據(jù)流從Camera流到ISP。

int cif_isp10_streamon(

struct cif_isp10_device *dev,

u32 stream_ids)

{

int ret = 0;

bool streamon_sp = stream_ids & CIF_ISP10_STREAM_SP;

bool streamon_mp = stream_ids & CIF_ISP10_STREAM_MP;

bool streamon_dma = stream_ids & CIF_ISP10_STREAM_DMA;

//......

stream_ids = 0;

if (streamon_mp && dev->mp_stream.updt_cfg)

stream_ids |= CIF_ISP10_STREAM_MP;

if (streamon_sp && dev->sp_stream.updt_cfg)

stream_ids |= CIF_ISP10_STREAM_SP;

ret = cif_isp10_config_cif(dev, stream_ids);

if (IS_ERR_VALUE(ret))

goto err;

//開(kāi)啟數(shù)據(jù)傳輸

ret = cif_isp10_start(dev, streamon_sp, streamon_mp);

if (IS_ERR_VALUE(ret))

goto err;

//......

}

static int cif_isp10_start(

struct cif_isp10_device *dev,

bool start_sp,

bool start_mp)

{

if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {

//調(diào)用Camera中的ioctl開(kāi)啟數(shù)據(jù)流

mutex_lock(&dev->img_src_exps.mutex);

cif_isp10_img_src_ioctl(dev->img_src,

RK_VIDIOC_SENSOR_MODE_DATA,

&dev->img_src_exps.data[0].data);

cif_isp10_img_src_ioctl(dev->img_src,

RK_VIDIOC_SENSOR_MODE_DATA,

&dev->img_src_exps.data[1].data);

dev->img_src_exps.data[0].v_frame_id = 0;

dev->img_src_exps.data[1].v_frame_id = 0;

mutex_unlock(&dev->img_src_exps.mutex);

//.......

}

//.......

return ret;

}

long cif_isp10_img_src_ioctl(

struct cif_isp10_img_src *img_src,

unsigned int cmd,

void *arg)

{

if (!img_src) {

cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");

return -EINVAL;

}

//調(diào)用Camera的ioctl

return img_src->ops->ioctl(img_src->img_src, cmd, arg);

}

通過(guò)上面的一些列調(diào)用關(guān)系可以看出,最終調(diào)用了Camera的ioctl。這里img_src指的就是sensor。數(shù)據(jù)就開(kāi)始從Camera一直流向ISP。

總結(jié)

我們分析了ISP驅(qū)動(dòng)的一個(gè)大致流程,Camera的很多核心算法不是放在驅(qū)動(dòng)上的,大部分都是放在應(yīng)用層上面的。所以我們?cè)隍?qū)動(dòng)上看到的更多是一些控制,參數(shù)配置等接口。



審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11125

    瀏覽量

    207932
  • ISP
    ISP
    +關(guān)注

    關(guān)注

    6

    文章

    473

    瀏覽量

    51563
  • Linux驅(qū)動(dòng)
    +關(guān)注

    關(guān)注

    0

    文章

    43

    瀏覽量

    9922
  • RK3399
    +關(guān)注

    關(guān)注

    2

    文章

    210

    瀏覽量

    24611
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux編譯驅(qū)動(dòng)內(nèi)核及應(yīng)用程序分析

    作為一名嵌入式Linux新手,在學(xué)習(xí)的過(guò)程中會(huì)遇到很多問(wèn)題。寫了一個(gè)驅(qū)動(dòng)程序怎么編譯?怎么加載進(jìn)內(nèi)核
    的頭像 發(fā)表于 01-17 13:46 ?6501次閱讀
    <b class='flag-5'>Linux</b>編譯<b class='flag-5'>驅(qū)動(dòng)</b>、<b class='flag-5'>內(nèi)核</b>及應(yīng)用程序<b class='flag-5'>分析</b>

    Linux驅(qū)動(dòng)分析input子系統(tǒng)

    Linux內(nèi)核為了能夠處理各種不同類型的輸入設(shè)備,比如: 觸摸屏 ,鼠標(biāo) , 鍵盤 , 操縱桿等設(shè)備 ,設(shè)計(jì)并實(shí)現(xiàn)了Linux 輸入子系統(tǒng) ,它為驅(qū)動(dòng)和應(yīng)用提供了統(tǒng)一的接口函數(shù),方便實(shí)
    發(fā)表于 02-01 10:38 ?478次閱讀

    Linux內(nèi)核分析筆記總結(jié)

    孟寧老師這門課并沒(méi)有完整的分析Linux內(nèi)核中代碼,而是針對(duì)關(guān)鍵部分進(jìn)行了講解分析,個(gè)人認(rèn)為內(nèi)核代碼也是存在二八定律的情況,少部分關(guān)鍵代碼經(jīng)
    發(fā)表于 07-18 06:00

    基于Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究

    Linux因其完全開(kāi)放的特性和穩(wěn)定優(yōu)良的性能深受歡迎,當(dāng)推出了內(nèi)核輸入子系統(tǒng)后,更方便了嵌入式領(lǐng)域的驅(qū)動(dòng)開(kāi)放。介紹了Linux的設(shè)備驅(qū)動(dòng)基礎(chǔ)
    發(fā)表于 09-12 16:38 ?23次下載

    linux內(nèi)核啟動(dòng)內(nèi)核解壓過(guò)程分析

    linux啟動(dòng)時(shí)內(nèi)核解壓過(guò)程分析,一份不錯(cuò)的文檔,深入了解內(nèi)核必備
    發(fā)表于 03-09 13:39 ?1次下載

    linux2.6內(nèi)核設(shè)備驅(qū)動(dòng)模型精華

    linux 內(nèi)核驅(qū)動(dòng)部分詳解
    發(fā)表于 04-27 10:43 ?20次下載

    基于Linux 2.6內(nèi)核Makefile分析

    基于2.4內(nèi)核的,可以說(shuō)關(guān)于2.6內(nèi)核Makefile相關(guān)的文章鳳毛麟角,筆者抽時(shí)間完成了這篇分析文章,讓讀者迅速熟悉Linux最新Makefile體系,從而加深對(duì)
    發(fā)表于 09-18 19:09 ?0次下載
    基于<b class='flag-5'>Linux</b> 2.6<b class='flag-5'>內(nèi)核</b>Makefile<b class='flag-5'>分析</b>

    Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究

    Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究
    發(fā)表于 10-31 14:41 ?14次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>輸入子系統(tǒng)的<b class='flag-5'>驅(qū)動(dòng)</b>研究

    關(guān)于Linux 2.6內(nèi)核Makefile的分析

    的介紹文章都是基于2.4內(nèi)核的,可以說(shuō)關(guān)于2.6內(nèi)核Makefile相關(guān)的文章鳳毛麟角,筆者抽時(shí)間完成了這篇分析文章,讓讀者迅速熟悉Linux最新Makefile體系,從而加深對(duì)
    發(fā)表于 11-02 10:12 ?1次下載

    linux內(nèi)核啟動(dòng)流程

    Linux的啟動(dòng)代碼真的挺大,從匯編到C,從Makefile到LDS文件,需要理解的東西很多。畢竟Linux內(nèi)核是由很多人,花費(fèi)了巨大的時(shí)間和精力寫出來(lái)的。而且直到現(xiàn)在,這個(gè)世界上仍然有成千上萬(wàn)的程序員在不斷完善
    發(fā)表于 11-14 16:19 ?4285次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>啟動(dòng)<b class='flag-5'>流程</b>

    基于Linux與Busybox的Reboot命令流程分析

    busybox是如何運(yùn)行這個(gè)命令,同時(shí)又是如何調(diào)用到Linux內(nèi)核中的mach_reset中的arch_reset,當(dāng)針對(duì)不同的ARM芯片時(shí),作為Linux內(nèi)核開(kāi)發(fā)和
    發(fā)表于 05-05 14:31 ?2444次閱讀
    基于<b class='flag-5'>Linux</b>與Busybox的Reboot命令<b class='flag-5'>流程</b><b class='flag-5'>分析</b>

    如何使用Linux內(nèi)核實(shí)現(xiàn)USB驅(qū)動(dòng)程序框架

    Linux內(nèi)核提供了完整的USB驅(qū)動(dòng)程序框架。USB總線采用樹(shù)形結(jié)構(gòu),在一條總線上只能有唯一的主機(jī)設(shè)備。 Linux內(nèi)核從主機(jī)和設(shè)備兩個(gè)角度
    發(fā)表于 11-06 17:59 ?19次下載
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>實(shí)現(xiàn)USB<b class='flag-5'>驅(qū)動(dòng)</b>程序框架

    Linux內(nèi)核SoftIrq源代碼分析

    我們?cè)?b class='flag-5'>分析linux內(nèi)核中斷剖析時(shí),簡(jiǎn)單的聊了一下SOFTIRQ, 而沒(méi)有進(jìn)行深入分析. Linux內(nèi)核
    發(fā)表于 06-23 15:22 ?459次閱讀

    Linux內(nèi)核代碼60%都是驅(qū)動(dòng)

    為什么Linux內(nèi)核代碼60%都是驅(qū)動(dòng)? 如果每支持新的設(shè)備就加入驅(qū)動(dòng)內(nèi)核會(huì)不會(huì)變得越來(lái)越臃腫?
    的頭像 發(fā)表于 07-11 11:48 ?729次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>代碼60%都是<b class='flag-5'>驅(qū)動(dòng)</b>?

    linux驅(qū)動(dòng)程序如何加載進(jìn)內(nèi)核

    Linux系統(tǒng)中,驅(qū)動(dòng)程序是內(nèi)核與硬件設(shè)備之間的橋梁。它們?cè)试S內(nèi)核與硬件設(shè)備進(jìn)行通信,從而實(shí)現(xiàn)對(duì)硬件設(shè)備的控制和管理。 驅(qū)動(dòng)程序的編寫
    的頭像 發(fā)表于 08-30 15:02 ?198次閱讀