为什么说fb_info->node 是设备的次设备号

本文详细介绍了Linux系统中帧缓冲设备注册的过程。包括struct fb_info结构体各成员的作用,如设备次设备号的自动分配机制及其与registered_fb数组的关系;通过register_framebuffer函数注册framebuffer设备的具体步骤;以及如何在类下创建设备。



struct fb_info
{
    int node;  //设备的次设备号

    int flags;
    struct mutex lock;
    struct mutex mm_lock;

    struct fb_var_screeninfo var; //可变参数
    struct fb_fix_screeninfo fix; //固定参数
    ......
};

成员 : 
        int node; 设备的次设备号

        次设备号由系统自动分配,递增的。实际上就是registered_fb[]中第一个空缺项的索引值。
        #define FB_MAX 32
        struct fb_info *registered_fb[FB_MAX]
        所以,最大不会超过31 

        /*
            向核心层注册一个framebuffer设备。
            fb_info 每一个帧缓冲设备都对应一个fb_info
        */
        int register_framebuffer(struct fb_info *fb_info)
        {
            int i; 
            /*
                这个i,就是次设备号,
                下面的代码会将registered_fb[]中第一个空缺项的索引值 赋值给这个i,
                而这个索引值就是设备的次设备号
            */
            ...
            /**
                FB_MAX : 32
                每注册一个framebuffer设备,num_registered_fb就递增一次。
            */
            if (num_registered_fb == FB_MAX)
            {
                return -ENXIO;
            }
            ....

            /**
                递增
            */
            num_registered_fb++;

            /**
                找到registered_fb[]中第一个空缺项
                为把fb_info放进去做准备
                struct fb_info *registered_fb[32];
                /dev/fb0 /dev/fb1 ..... /dev/fb31。
            */
            for (i = 0 ; i < FB_MAX; i++)
            {
                if (!registered_fb[i])
                {
                    break;
                }
            }
            /*
                【将次设备号赋值给node】
            */
            fb_info->node = i;  

            ....
            /**
                在类下创建设备。

                在fbmem_init()中创建的类。
                static int __init fbmem_init(void)
                {
                    ...
                    fb_class = class_create(THIS_MODULE, "graphics");
                    ...
                }
                看这里的 MKDEV(FB_MAJOR, i)
            */
            fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
            if (IS_ERR(fb_info->dev))
            {
                ... 
            }
            .....
        }
请根据我的代码帮我分析设备树信息 pcie@d8900000 { compatible = "hisilicon,udrv-pcie-ecam-dt"; reg = <0x0b 0x00 0x00 0x400000 0x00 0xd8900000 0x00 0x80000 0x00 0x700000 0x00 0x00>; reg-names = "config\0dbi\0msi"; bus-range = <0x00 0x03>; ranges = <0x82000000 0x00 0x00 0x0b 0x800000 0x00 0x1f800000>; #address-cells = <0x03>; #size-cells = <0x02>; device_type = "pci"; dma-coherent; msi-trans-type = <0x01>; interrupts = <0x00 0x1f7 0x04>; #interrupt-cells = <0x01>; interrupt-map-mask = <0xf800 0x00 0x00 0x07>; interrupt-map = <0x00 0x00 0x00 0x01 0x01 0x00 0x1f9 0x04 0x00 0x00 0x00 0x02 0x01 0x00 0x1fa 0x04 0x00 0x00 0x00 0x03 0x01 0x00 0x1fb 0x04 0x00 0x00 0x00 0x04 0x01 0x00 0x1fc 0x04>; linux,pci-domain = <0x00>; core-version = <0x00>; clocks_num = <0x02>; clocks = <0x09 0x00 0x09 0x01>; clock-names = "CLK_PCIE_CLK0\0CLK_PCIE_CLK1"; resets_num = <0x01>; resets = <0x09 0x00>; reset-names = "RST_PCIE_RST0"; status = "okay"; port@0 { lanes-nums = <0x01>; max-lanes = <0x01>; max-speed = <0x03>; port-id = <0x00>; lport-id = <0x00>; core-id = <0x00>; port-type = <0x01>; target-speed = <0x01>; probe = <0x01>; 中的reg = <0x0b 0x00 0x00 0x400000 0x00 0xd8900000 0x00 0x80000 0x00 0x700000 0x00 0x00>;是在代码中哪部分解析的,接着按照 依次表示配置空间、寄存器、msi的基地址及大小,配置格式为linux通用的reg格式,64位。<addr_h addr_l size_h size_l>, <addr_h addr_l size_h size_l>, <addr_h addr_l size_h size_l> addr_h: 寄存器空间基址高32bit addr_l: 寄存器空间基址低32bit size_h: 寄存器空间大小高32bit size_l: 寄存器空间大小低32bit 来给我解释这几个数值是什么意思 另外帮我分析原本单板接pcie siwtch设备后,挂在switch上的pcie网卡设备lspci只能识别一个(实际挂载不止一个), 为什么将reg = <0x0b 0x00 0x00 0x400000 0x00 0xd8900000 0x00 0x80000 0x00 0x700000 0x00 0x00>;中的0x400000改成0x800000,以及bus-range = <0x00 0x03>中的0x3改大之后 lspci就能识别剩下的挂载的pcie设备了呢 代码部分: #include <linux/module.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/of_address.h> #include <linux/of_pci.h> #include <linux/platform_device.h> #include <linux/of_device.h> #include <linux/pci.h> #include <linux/pci-ecam.h> #include <linux/kallsyms.h> #include <linux/err.h> #include <linux/irqchip/chained_irq.h> #include <linux/irq.h> #include <linux/msi.h> #include <linux/fwnode.h> #include <linux/acpi.h> #include <linux/idr.h> #include <linux/version.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) #include <linux/reset-controller.h> #include <linux/reset.h> #else #include "../subctrl/include.linux/reset-controller.h" #include "../subctrl/include.linux/reset.h" #endif #include <linux/clk.h> #include <linux/version.h> #include "pcie_udrv.h" #define MSI_ADDR_DEST_ID_SHIFT 4 #define MSI_ADDR_HEADER 0xfee00000 #define MSI_ADDR_DEST_ID_MASK 0xfff0000f #define MSI_ADDR_DEST_ID_CPU(cpu) ((cpu) << MSI_ADDR_DEST_ID_SHIFT) LIST_HEAD(pcie_host_list); static int udrv_pcie_host_ep_init(struct platform_device *pdev); #define copy_resource(dst, src, name_) do { \ (dst)->start = (src)->start; \ (dst)->end = (src)->end; \ (dst)->flags = (src)->flags; \ (dst)->name = name_; \ } while (0) #define UDRV_MAX_PCIE_HOST_NUM 16 #define PCIE_DP_PORT 2 #define PCIE_UP_PORT 3 #define PCIE_MAX_FMEA_DEV_NUM 12 DEFINE_IDR(pcie_idr); static void udrv_pcie_msi_mask_irq(struct irq_data *data) { pci_msi_mask_irq(data); irq_chip_mask_parent(data); } static void udrv_pcie_msi_unmask_irq(struct irq_data *data) { pci_msi_unmask_irq(data); irq_chip_unmask_parent(data); } static struct irq_chip udrv_pcie_msi_irq_chip = { .name = "udrv_msi", .irq_mask = udrv_pcie_msi_mask_irq, .irq_unmask = udrv_pcie_msi_unmask_irq, }; static struct msi_domain_info udrv_pcie_msi_domain_info = { .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI), .chip = &udrv_pcie_msi_irq_chip, }; static void udrv_pcie_handle_msi_irq(struct udrv_pcie_host *pcie) { uint32_t status = 0; unsigned long bit_pos = 0, status_u64 = 0; uint32_t irq; handle pf_handle = pcie->host_info.pf_handle; uint32_t ret = ndrv_pcie_host_get_msi_status(pf_handle, &status); if ((ret != 0) || (status == 0)) { return; } status_u64 = (unsigned long)status; (void)ndrv_pcie_host_msi_mask_all(pf_handle, 0xFFFFFFFF); while ((bit_pos = find_next_bit(&status_u64, UDRV_MAX_MSI_IRQS, bit_pos)) != UDRV_MAX_MSI_IRQS) { irq = irq_find_mapping(pcie->msi.irq_domain, bit_pos); (void)ndrv_pcie_host_msi_clear(pf_handle, (u32)bit_pos); generic_handle_irq(irq); bit_pos++; } (void)ndrv_pcie_host_msi_mask_all(pf_handle, 0); } static void udrv_pcie_handle_chained_msi_irq(struct irq_desc *desc) { struct udrv_pcie_host *pcie = NULL; struct irq_chip *chip = irq_desc_get_chip(desc); chained_irq_enter(chip, desc); pcie = irq_desc_get_handler_data(desc); udrv_pcie_handle_msi_irq(pcie); chained_irq_exit(chip, desc); } static void udrv_pcie_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) { struct udrv_pcie_host *pcie = irq_data_get_irq_chip_data(data); struct udrv_pcie_host_msi_info *msi = &pcie->msi; msg->address_lo = lower_32_bits(msi->msi_addr); msg->address_hi = upper_32_bits(msi->msi_addr); msg->data = (u32)data->hwirq; dev_info(pcie->dev, "[iWare][Info] msi#%d address_hi %#x address_lo %#x\n", (int)data->hwirq, msg->address_hi, msg->address_lo); } static int udrv_pcie_msi_set_affinity(struct irq_data *irq_data, const struct cpumask *mask, bool force) { struct udrv_pcie_host *pcie; struct msi_desc *desc; struct msi_msg msg; int cpu; /* 检查 irq_data 和 mask 是否为 NULL */ if (!irq_data || !mask) { return -EINVAL; } /* 获取 irq_data 中的数据 */ pcie = irq_data_get_irq_chip_data(irq_data); desc = irq_data_get_msi_desc(irq_data); /* 检查 pcie 和 desc 是否为 NULL */ if (!pcie || !desc) { return -EINVAL; } msg = desc->msg; /* 1. 获取有效的目标 CPU */ cpu = cpumask_first_and(mask, cpu_online_mask); if (cpu >= nr_cpu_ids) { return -EINVAL; } /* 2. 更新 MSI 消息目标 ID */ msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu); /* 3. 写入新的 MSI 消息 */ pci_write_msi_msg(irq_data->irq, &msg); /* 4. 更新父中断控制器 */ if (irq_data->parent_data && irq_data->parent_data->chip && irq_data->parent_data->chip->irq_set_affinity) { return irq_data->parent_data->chip->irq_set_affinity(irq_data->parent_data, mask, force); } return IRQ_SET_MASK_OK_DONE; } static void udrv_pcie_bottm_mask(struct irq_data *data) { struct udrv_pcie_host *pcie = irq_data_get_irq_chip_data(data); struct udrv_pcie_host_msi_info *msi = &pcie->msi; handle pf_handle = pcie->host_info.pf_handle; unsigned long flags; raw_spin_lock_irqsave(&msi->lock, flags); ndrv_pcie_host_msi_mask_one(pf_handle, (u32)data->hwirq, 1); raw_spin_unlock_irqrestore(&msi->lock, flags); } static void udrv_pcie_bottm_unmask(struct irq_data *data) { struct udrv_pcie_host *pcie = irq_data_get_irq_chip_data(data); struct udrv_pcie_host_msi_info *msi = &pcie->msi; handle pf_handle = pcie->host_info.pf_handle; unsigned long flags; raw_spin_lock_irqsave(&msi->lock, flags); ndrv_pcie_host_msi_mask_one(pf_handle, (u32)data->hwirq, 0); raw_spin_unlock_irqrestore(&msi->lock, flags); } static struct irq_chip udrv_pcie_msi_bottom_irq_chip = { .name = "udrv_bottom_msi", .irq_compose_msi_msg = udrv_pcie_compose_msi_msg, .irq_set_affinity = udrv_pcie_msi_set_affinity, .irq_mask = udrv_pcie_bottm_mask, .irq_unmask = udrv_pcie_bottm_unmask, }; static int dw_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int num_irqs, void *args) { unsigned long flags; struct udrv_pcie_host *pcie = domain->host_data; struct udrv_pcie_host_msi_info *msi = &pcie->msi; int bit; uint32_t i; raw_spin_lock_irqsave(&msi->lock, flags); bit = bitmap_find_free_region(msi->msi_irq_in_use_bits, UDRV_MAX_MSI_IRQS, order_base_2(num_irqs)); raw_spin_unlock_irqrestore(&msi->lock, flags); if (bit < 0) { return -ENOSPC; } for (i = 0; i < num_irqs; i++) { irq_domain_set_info(domain, virq + i, bit + i, &udrv_pcie_msi_bottom_irq_chip, pcie, handle_level_irq, NULL, NULL); } return 0; } static void udrv_pcie_irq_domain_free(struct irq_domain *domain, unsigned int virq, unsigned int num_irqs) { unsigned long flags; struct udrv_pcie_host *pcie = domain->host_data; struct udrv_pcie_host_msi_info *msi = &pcie->msi; struct irq_data *data = irq_domain_get_irq_data(domain, virq); uint32_t i; raw_spin_lock_irqsave(&msi->lock, flags); bitmap_release_region(msi->msi_irq_in_use_bits, (u32)data->hwirq, order_base_2(num_irqs)); raw_spin_unlock_irqrestore(&msi->lock, flags); for (i = 0; i < num_irqs; i++) { data = irq_domain_get_irq_data(domain, virq + i); irq_domain_reset_irq_data(data); } } static const struct irq_domain_ops udrv_pcie_msi_domain_ops = { .alloc = dw_pcie_irq_domain_alloc, .free = udrv_pcie_irq_domain_free, }; static void udrv_pcie_remove_msi(struct udrv_pcie_host *pcie) { handle pf_handle = pcie->host_info.pf_handle; struct udrv_pcie_host_msi_info *msi = &pcie->msi; (void)ndrv_pcie_host_msi_mask_all(pf_handle, 0xFFFFFFFF); if (msi->msi_trans_type == MSI_ITS) { return; } irq_set_chained_handler((u32)msi->irq, NULL); irq_set_handler_data((u32)msi->irq, NULL); irq_domain_remove(msi->msi_domain); irq_domain_remove(msi->irq_domain); } static int udrv_pcie_allocate_msi_domains(struct udrv_pcie_host *pcie) { struct udrv_pcie_host_msi_info *msi = &pcie->msi; struct fwnode_handle *fwnode = of_node_to_fwnode(pcie->dev->of_node); msi->irq_domain = irq_domain_create_linear(fwnode, UDRV_MAX_MSI_IRQS, &udrv_pcie_msi_domain_ops, pcie); if (!msi->irq_domain) { dev_err(pcie->dev, "[iWare][Error] irq_domain_create_linear fail\n"); return -ENOMEM; } msi->msi_domain = pci_msi_create_irq_domain(fwnode, &udrv_pcie_msi_domain_info, msi->irq_domain); if (!msi->msi_domain) { irq_domain_remove(msi->irq_domain); dev_err(pcie->dev, "[iWare][Error] pci_msi_create_irq_domain fail\n"); return -ENOMEM; } return 0; } static int udrv_pcie_get_msi_info_from_dt(struct udrv_pcie_host *pcie) { struct device *dev = pcie->dev; struct udrv_pcie_host_msi_info *msi = &pcie->msi; struct resource *res = NULL; struct platform_device *pdev = to_platform_device(dev); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "msi"); if (!res) { dev_err(dev, "[iWare][Error] get msi address fail\n"); return -EINVAL; } if (of_property_read_u32(dev->of_node, "msi-trans-type", (u32 *)(uintptr_t)(&msi->msi_trans_type)) != 0) { msi->msi_trans_type = MSI_ITS; } msi->msi_addr = res->start; if (msi->msi_trans_type == MSI_ITS) { return 0; } msi->irq = platform_get_irq(pdev, 0); if (msi->irq <= 0) { dev_info(dev, "[iWare][Info] no msi irq,now jump\n"); return 0; } return 0; } static void udrv_pcie_free_atu_info(struct udrv_pcie_host *pcie) { struct list_head *head = &pcie->host_info.atu_info.entry; struct udrv_pcie_atu_info *tmp = NULL; struct udrv_pcie_atu_info *pos = NULL; list_for_each_entry_safe(pos, tmp, head, entry) { list_del(&pos->entry); kfree(pos); } } static void udrv_pcie_free_port_info(struct udrv_pcie_host *pcie) { struct list_head *head = &pcie->port_info.entry; struct udrv_pcie_port_info *tmp = NULL; struct udrv_pcie_port_info *pos = NULL; list_for_each_entry_safe(pos, tmp, head, entry) { if (pos->idr >= 0) { idr_remove(&pcie_idr, pos->idr); } list_del(&pos->entry); kfree(pos); } } static int udrv_pcie_get_atu_info_from_dt(struct udrv_pcie_host *pcie) { struct device *dev = pcie->dev; struct udrv_pcie_atu_info *atu_info = NULL; struct list_head *head = &pcie->host_info.atu_info.entry; struct of_pci_range_parser parser; struct of_pci_range range; int ret = of_pci_range_parser_init(&parser, dev->of_node); if (ret != 0) { dev_err(dev, "[iWare][Error] parser range failed\n"); goto err_range; } for_each_of_pci_range(&parser, &range) { if (((range.flags & IORESOURCE_TYPE_BITS) != IORESOURCE_IO) && ((range.flags & IORESOURCE_TYPE_BITS) != IORESOURCE_MEM)) { continue; } atu_info = kzalloc(sizeof(struct udrv_pcie_atu_info), GFP_KERNEL); if (atu_info == NULL) { ret = -ENOMEM; goto fail; } atu_info->cpu_addr = range.cpu_addr; atu_info->pcie_addr = range.pci_addr; atu_info->size = range.size; atu_info->atu_mode = ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM) ? 0 : 1; list_add_tail(&atu_info->entry, head); } return 0; fail: udrv_pcie_free_atu_info(pcie); err_range: ndrv_pcie_close_pf(pcie->host_info.pf_handle, pcie->host_info.core_version); return ret; } static int udrv_pcie_get_host_property_info_from_dt(struct device *dev, struct udrv_pcie_host_info *host_info) { if (of_property_read_u32(dev->of_node, "type-support", (u32 *)(uintptr_t)(&host_info->type_support_mask)) != 0) { dev_info(dev, "[iWare] no declare type support, default rp mode\n"); set_bit(NDRV_PCIE_RP_MODE, &(host_info->type_support_mask)); } if (of_property_read_u32(dev->of_node, "clocks_num", &host_info->clk_num) != 0) { dev_err(dev, "[iWare][Error] Faild read clk_num\n"); return -EINVAL; } if (of_property_read_u32(dev->of_node, "resets_num", &host_info->rst_num) != 0) { dev_err(dev, "[iWare][Error] Faild read rsts_num\n"); return -EINVAL; } if (of_property_read_u32(dev->of_node, "core-version", &host_info->core_version) != 0) { dev_err(dev, "[iWare][Error] Faild to read core version\n"); return -EINVAL; } if (of_property_read_u32(dev->of_node, "rc_mode", (u32 *)(uintptr_t)(&host_info->rc_mode)) != 0) { host_info->rc_mode = NDRV_PCIE_RC_NORMAL; } return 0; } static int udrv_pcie_get_host_info_from_dt(struct udrv_pcie_host *pcie) { struct device *dev = pcie->dev; struct platform_device *pdev = to_platform_device(dev); struct udrv_pcie_host_info *host_info = &pcie->host_info; struct resource *apb_res = NULL; struct io_region region; int ret; if (of_property_read_u32(dev->of_node, "linux,pci-domain", &host_info->host_id) != 0) { dev_err(dev, "[iWare][Error] Faild read pci-domain\n"); return -EINVAL; } if (host_info->host_id >= UDRV_MAX_PCIE_HOST_NUM) { dev_err(dev, "[iWare][Error] Invalid domain nr = 0x%x\n", host_info->host_id); return -EINVAL; } ret = udrv_pcie_get_host_property_info_from_dt(dev, host_info); if (ret != 0) { return ret; } apb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); if (apb_res == NULL) { dev_err(dev, "[iWare][Error] Faild to get dbi address\n"); return -EINVAL; } host_info->apb_base = devm_pci_remap_cfgspace(dev, apb_res->start, resource_size(apb_res)); host_info->apb_paddr = apb_res->start; host_info->apb_size = (u32)resource_size(apb_res); if (IS_ERR(host_info->apb_base)) { dev_err(dev, "[iWare][Error] Faild to remap apb_base\n"); return -EINVAL; } region.io_base = host_info->apb_base; region.io_size = host_info->apb_size; host_info->pf_handle = ndrv_pcie_open_pf(&region, host_info->core_version, host_info->rc_mode); if (host_info->pf_handle == NULL) { dev_err(pcie->dev, "[iWare][Error] ndrv pcie_open_pf fail\n"); return -EINVAL; } return udrv_pcie_get_atu_info_from_dt(pcie); } static int udrv_pcie_host_init(struct udrv_pcie_host *pcie) { u32 ret; u32 atu_id = 0; struct ndrv_pcie_ecam_cfg_info ecam_cfg; struct ndrv_pcie_atu_cfg_info atu_cfg; struct udrv_pcie_host_info *host_info = &pcie->host_info; struct udrv_pcie_atu_info *pos = NULL; struct list_head *head = &pcie->host_info.atu_info.entry; /* 仅支持RP的host,需要初始化TX atu和ecam */ if (test_bit(NDRV_PCIE_RP_MODE, &(host_info->type_support_mask)) != 0) { list_for_each_entry(pos, head, entry) { atu_cfg.tx_src_base_addr = pos->cpu_addr; atu_cfg.tx_dst_base_addr = pos->pcie_addr; atu_cfg.tx_region_size = pos->size; atu_cfg.atu_mode = pos->atu_mode; ret = ndrv_pcie_host_ap_atu_init(host_info->pf_handle, &atu_cfg, atu_id); ++atu_id; if (ret != 0) { pr_err("[iWare][Error] init atu:0x%x failed, ret=%u\n", atu_id, ret); return -EINVAL; } } ecam_cfg.ecam_base_addr_l = (u32)(host_info->ecam_res.start); ecam_cfg.ecam_base_addr_h = (u32)(host_info->ecam_res.start >> 32); /* 高32bit */ ecam_cfg.ecam_base_size = (u32)resource_size(&host_info->ecam_res); ecam_cfg.ecam_start_bus_no = (u32)host_info->bus_res.start; ret = ndrv_pcie_host_ap_ecam_init(host_info->pf_handle, &ecam_cfg); if (ret != 0) { pr_err("[iWare][Error] init ap ecam failed, ret=%u\n", ret); return -EINVAL; } } ret = ndrv_pcie_host_ap_enable(host_info->pf_handle, 1); if (ret != 0) { pr_err("[iWare][Error] ap enable failed, ret=%u\n", ret); return -EINVAL; } return 0; } #ifdef CONFIG_UDRV_FMEA static int pcie_fmea_init(struct udrv_pcie_host *pcie) { int ret; struct fmea_dev_info dev_info; const struct ndrv_fmea_item_info *item_table; struct ndrv_pcie_fmea_open_cfg cfg; dev_info.dev = pcie->dev; dev_info.pdev_id = pcie->host_info.host_id; dev_info.name = FMEA_MODULE_NAME(pcie); cfg.paddr = pcie->host_info.apb_paddr; item_table = ndrv_pcie_pf_get_fmea_table(pcie->host_info.pf_handle, &cfg); if (item_table == NULL) { dev_err(pcie->dev, "[iWare][Error] pcie get_fmea_table fail\n"); return -EINVAL; } ret = kdrv_fmea_iomm_unit_list_init(&dev_info, item_table, &pcie->iomm_info); if (ret != 0) { dev_err(pcie->dev, "[iWare][Error] kdrv fmea_iomm_unit_list_init fail\n"); return -EINVAL; } return 0; } static void pcie_fmea_deinit(struct udrv_pcie_host *pcie) { kdrv_fmea_iomm_unit_list_deinit(&pcie->iomm_info); } int kdrv_pcie_fmea_entry(u32 pcie_id, u32 group_id, u64 *err_info, u32 *alm_flg, char *buf, u32 size) { struct udrv_pcie_host *pcie = NULL; struct fmea_iomm_unit *pcie_fmobj = NULL; pcie = hisi_pcie_get_by_host_id(pcie_id); if (pcie == NULL) { pr_err("[iWare][Error] [pcie fmea entry], get pcie failed\n"); return -ENODEV; } if (group_id >= pcie->iomm_info.group_num) { return -ERANGE; } pcie_fmobj = &pcie->iomm_info.iomms[group_id]; if (!pcie_fmobj) { return -ENODEV; } return kdrv_fmea_entry(pcie_fmobj, err_info, alm_flg, buf, size); } EXPORT_SYMBOL(kdrv_pcie_fmea_entry); int kdrv_pcie_get_fmea_group_num_(struct udrv_pcie_host *pcie, uint32_t *num) { if (pcie == NULL || num == NULL) { return -EINVAL; } *num = pcie->iomm_info.group_num; return 0; } int kdrv_pcie_get_fmea_dev_num_(struct udrv_pcie_host *pcie, uint32_t *num) { if (pcie == NULL || num == NULL) { return -EINVAL; } *num = PCIE_MAX_FMEA_DEV_NUM; return 0; } #endif static int udrv_pcie_host_ecam_init(struct pci_config_window *cfg_w) { int ret; struct platform_device *pdev = to_platform_device(cfg_w->parent); struct udrv_pcie_host *pcie = platform_get_drvdata(pdev); struct udrv_pcie_host_info *host_info = &pcie->host_info; struct resource *cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); if (!cfg_res) { pr_err("[iWare]cfg_res is null\n"); return -EINVAL; } copy_resource(&host_info->ecam_res, cfg_res, "config"); copy_resource(&host_info->bus_res, &cfg_w->busr, "bus"); #ifdef CONFIG_UDRV_DEBUG udrv_pcie_show_host_info(pcie); #endif ret = pcie->ops->port_ops->init(pcie); if (ret != 0) { pr_err("[iWare][Error] port init failed,ret=%d\n", ret); return ret; } ret = pcie->ops->host_ops->init(pcie); if (ret != 0) { pr_err("[iWare][Error] host init failed,ret=%d\n", ret); return ret; } ret = pcie->ops->msi_ops->init(pcie); if (ret != 0) { pr_err("[iWare][Error] msi init failed,ret=%d\n", ret); } return ret; } /* host仅支持ep场景,仅初始化芯片 */ static int udrv_pcie_host_ep_init(struct platform_device *pdev) { int ret; struct udrv_pcie_host *pcie = platform_get_drvdata(pdev); #ifdef CONFIG_UDRV_DEBUG udrv_pcie_show_host_info(pcie); #endif ret = pcie->ops->port_ops->init(pcie); if (ret != 0) { return ret; } ret = pcie->ops->host_ops->init(pcie); if (ret != 0) { return ret; } ret = pcie->ops->msi_ops->init(pcie); return ret; } static int udrv_pcie_get_switch_info(struct device *dev, struct device_node *child, struct udrv_pcie_port_info *port_info) { if (of_property_read_u32(child, "switch-core-id", &port_info->switch_core_id) != 0) { dev_err(dev, "[iWare][Error] Faild to read switch-core-id\n"); return -EINVAL; } if (of_property_read_u32(child, "core-0-1-dp-bitmap", &port_info->core_0_1_dp_bitmap) != 0) { dev_err(dev, "[iWare][Error] Faild to read core-0-1-dp-bitmap\n"); return -EINVAL; } if (of_property_read_u32(child, "core-2-3-dp-bitmap", &port_info->core_2_3_dp_bitmap) != 0) { dev_err(dev, "[iWare][Error] Faild to read core-2-3-dp-bitmap\n"); return -EINVAL; } if (of_property_read_u32(child, "up-core-id", &port_info->up_core_id) != 0) { dev_err(dev, "[iWare][Error] Faild to read up-core-id\n"); return -EINVAL; } return 0; } static int udrv_pcie_get_port_info_from_dts(struct device *dev, struct device_node *child, struct udrv_pcie_port_info *port_info) { if (of_property_read_u32(child, "port-type", &port_info->port_type) != 0) { dev_err(dev, "[iWare][Error] Faild to read port-type\n"); return -EINVAL; } if (port_info->port_type == NDRV_PCIE_EP_MODE) { if (of_property_read_u64(child, "ep-addr", &port_info->ep_addr) != 0) { dev_err(dev, "[iWare][Error] Faild to read ep_addr\n"); return -EINVAL; } if (of_property_read_u32(child, "ep-size", &port_info->ep_size) != 0) { dev_err(dev, "[iWare][Error] Faild to read ep_size\n"); return -EINVAL; } } if (of_property_read_u32(child, "port-id", &port_info->port_id) != 0) { dev_err(dev, "[iWare][Error] Faild to read port-id\n"); return -EINVAL; } if (of_property_read_u32(child, "lport-id", &port_info->lport_id) != 0) { dev_err(dev, "[iWare][Error] Faild to read lport-id\n"); return -EINVAL; } if (of_property_read_u32(child, "pri_bus", &port_info->pri_bus) != 0) { port_info->pri_bus = 0; } if (of_property_read_u32(child, "sec_bus", &port_info->sec_bus) != 0) { port_info->sec_bus = 0; } if (of_property_read_u32(child, "sub_bus", &port_info->sub_bus) != 0) { port_info->sub_bus = 0; } return 0; } static int udrv_pcie_get_port_info_child_dt(struct device *dev, struct device_node *child, struct udrv_pcie_port_info *port_info) { int ret; ret = udrv_pcie_get_port_info_from_dts(dev, child, port_info); if (ret != 0) { return ret; } if (of_property_read_u32(child, "lanes-nums", &port_info->lane_num) != 0) { dev_err(dev, "[iWare][Error] Faild to read lanes\n"); return -EINVAL; } if (of_property_read_u32(child, "max-lanes", &port_info->max_lanes) != 0) { port_info->max_lanes = port_info->lane_num; } if (of_property_read_u32(child, "max-speed", &port_info->max_speed) != 0) { dev_err(dev, "[iWare][Error] Faild to read max-speed\n"); return -EINVAL; } if (of_property_read_u32(child, "target-speed", &port_info->target_speed) != 0) { port_info->target_speed = port_info->max_speed; } if (of_property_read_u32(child, "payload", &port_info->payload) != 0) { port_info->payload = NDRV_PCIE_PAYLOAD_128B; } if (of_property_read_u32(child, "read_req", &port_info->read_req) != 0) { port_info->read_req = NDRV_PCIE_PAYLOAD_512B; } if (of_property_read_u32(child, "pcs_clk", &port_info->pcs_clk) != 0) { port_info->pcs_clk = NDRV_PCIE_PCS_CLK_100M; } if (of_property_read_u32(child, "core-id", &port_info->core_id) != 0) { port_info->core_id = 0; } if (of_property_read_u32(child, "probe", &port_info->is_probe) != 0) { port_info->is_probe = 0; } if (of_property_read_u32(child, "aer_en", &port_info->aer_en) != 0) { port_info->aer_en = 0; } if (port_info->port_type == PCIE_DP_PORT || port_info->port_type == PCIE_UP_PORT) { return udrv_pcie_get_switch_info(dev, child, port_info); } return 0; } static int udrv_pcie_get_port_info_from_dt(struct udrv_pcie_host *pcie) { struct device *dev = pcie->dev; struct device_node *child = NULL; struct udrv_pcie_port_info *port_info = NULL; struct list_head *head = &pcie->port_info.entry; int ret; for_each_child_of_node(dev->of_node, child) { port_info = kzalloc(sizeof(struct udrv_pcie_port_info), GFP_KERNEL); if (!port_info) { ret = -ENOMEM; goto get_port_fail; } list_add_tail(&port_info->entry, head); ret = udrv_pcie_get_port_info_child_dt(dev, child, port_info); if (ret != 0) { dev_err(dev, "[iWare][Error] get child dt failed,ret:%d\n", ret); goto get_port_fail; } port_info->idr = (u32)idr_alloc(&pcie_idr, pcie, (int)port_info->lport_id, (int)port_info->lport_id + 1, GFP_KERNEL); if ((port_info->idr < 0) || (port_info->idr != port_info->lport_id)) { dev_err(dev, "[iWare][Error] idr_alloc fail, port_id:%d, idr:%d\n", port_info->port_id, port_info->idr); ret = -ENOSPC; goto get_port_fail; } } return 0; get_port_fail: udrv_pcie_free_port_info(pcie); return ret; } static int udrv_pcie_subctrl_dereset(struct udrv_pcie_host *pcie) { struct device *dev = pcie->dev; struct reset_control *rst = NULL; struct clk *clk = NULL; struct device_node *node = dev->of_node; int ret, i; u32 clk_num = pcie->host_info.clk_num; u32 rst_num = pcie->host_info.rst_num; for (i = 0; i < (int)rst_num; i++) { rst = of_reset_control_get_by_index(node, i); if (IS_ERR(rst)) { dev_err(dev, "[iWare][Error] [udrv pcie_subctrl_dereset] get rst failed\n"); return -EFAULT; } ret = reset_control_deassert(rst); if (ret != 0) { dev_err(dev, "[iWare][Error] [udrv pcie_subctrl_dereset] soft rst failed, ret=%d\n", ret); return ret; } reset_control_put(rst); } for (i = 0; i < (int)clk_num; i++) { clk = of_clk_get(node, i); if (IS_ERR(clk)) { dev_err(dev, "[iWare][Error] [udrv pcie_subctrl_dereset] get clk failed\n"); return -EFAULT; } ret = clk_prepare_enable(clk); if (ret != 0) { dev_err(dev, "[iWare][Error] [udrv pcie_subctrl_dereset] open clk failed, ret=%d\n", ret); return ret; } clk_put(clk); } return 0; } static void udrv_pcie_convert_port_cfg(struct ndrv_pcie_port_cfg_info *cfg, struct udrv_pcie_port_info *pos) { cfg->phy_port_id = pos->port_id; cfg->mode = pos->port_type; cfg->ep_addr = pos->ep_addr; cfg->ep_size = pos->ep_size; cfg->lane_num = pos->lane_num; cfg->target_speed = pos->target_speed; cfg->max_lane = pos->max_lanes; cfg->max_speed = pos->max_speed; cfg->core_id = pos->core_id; cfg->payload = pos->payload; cfg->read_req = pos->read_req; cfg->pcs_clk = pos->pcs_clk; cfg->switch_info.switch_core_id = pos->switch_core_id; cfg->switch_info.core0_1_dp_bitmap = pos->core_0_1_dp_bitmap; cfg->switch_info.core2_3_dp_bitmap = pos->core_2_3_dp_bitmap; cfg->switch_info.up_core_id = pos->up_core_id; cfg->pri_bus = pos->pri_bus; cfg->sec_bus = pos->sec_bus; cfg->sub_bus = pos->sub_bus; cfg->aer_en = pos->aer_en; } static int udrv_pcie_port_init(struct udrv_pcie_host *pcie) { u32 u_ret; int ret; struct udrv_pcie_host_info *host_info = &pcie->host_info; struct udrv_pcie_port_info *pos = NULL; struct list_head *head = &pcie->port_info.entry; struct ndrv_pcie_port_cfg_info cfg; /* 打开时钟和解复位 */ ret = udrv_pcie_subctrl_dereset(pcie); if (ret != 0) { dev_err(pcie->dev, "[iWare][Error] host_id = %u, subctrl failed, ret = 0x%x\n", host_info->host_id, ret); return ret; } list_for_each_entry(pos, head, entry) { udrv_pcie_convert_port_cfg(&cfg, pos); u_ret = ndrv_pcie_host_port_init(host_info->pf_handle, &cfg); if (u_ret != 0) { dev_err(pcie->dev, "[iWare][Error] port_init fail, host_id = %u, ret = 0x%x\n", host_info->host_id, u_ret); return -EINVAL; } if (pos->is_probe != 0) { u_ret = ndrv_pcie_set_port_enable(host_info->pf_handle, pos->core_id, pos->port_id, 1); if (u_ret != 0) { return -EINVAL; } } } return 0; } static int udrv_pcie_msi_init(struct udrv_pcie_host *pcie) { struct udrv_pcie_host_msi_info *msi = &pcie->msi; handle pf_handle = pcie->host_info.pf_handle; u32 u_ret; int ret; u_ret = ndrv_pcie_host_set_msi_addr(pf_handle, msi->msi_addr); if (u_ret != 0) { return -EINVAL; } u_ret = ndrv_pcie_host_set_msi_enable(pf_handle, msi->msi_trans_type); if (u_ret != 0) { return -EINVAL; } if (msi->msi_trans_type == MSI_ITS) { return 0; } raw_spin_lock_init(&msi->lock); ret = udrv_pcie_allocate_msi_domains(pcie); if (ret != 0) { dev_err(pcie->dev, "[iWare][Error] allocate_msi_domains fail, ret = %d\n", ret); return ret; } irq_set_chained_handler_and_data((u32)msi->irq, udrv_pcie_handle_chained_msi_irq, pcie); return 0; } static void __iomem *udrv_pcie_ecam_map_bus(struct pci_bus *bus, unsigned int devfn, int where) { u32 bus_no = bus->number; void __iomem *base = NULL; struct pci_config_window *config = bus->sysdata; u32 devfn_shift = config->ops->bus_shift - 8; // dev + func = 5 + 3 = 8 if ((bus_no < config->busr.start) || (bus_no > config->busr.end)) { return NULL; } bus_no -= (u32)config->busr.start; base = config->win + (bus_no << config->ops->bus_shift); return base + (devfn << devfn_shift) + where; } static int udrv_pcie_host_common_probe(struct platform_device *pdev, struct pci_ecam_ops *ops) { #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) return pci_host_common_probe(pdev, ops); #else struct udrv_pcie_host *pcie = platform_get_drvdata(pdev); int ret; ret = pci_host_common_probe(pdev); // 5.10调用完内核的probe之后drvdata会被设成bridge,需要设回来,同时保存bridge以便remove时使用 pcie->bridge = platform_get_drvdata(pdev); platform_set_drvdata(pdev, pcie); return ret; #endif } static int udrv_pcie_host_common_remove(struct platform_device *pdev) { #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) return 0; // 早期版本的内核没有提供remove接口 #else struct udrv_pcie_host *pcie = platform_get_drvdata(pdev); // 调用内核的remove之前需要将drvdata设成框架要求的bridge platform_set_drvdata(pdev, pcie->bridge); return pci_host_common_remove(pdev); #endif } static int udrv_pcie_host_probe_for_dt(struct udrv_pcie_host *pcie) { struct platform_device *pdev = to_platform_device(pcie->dev); struct udrv_pcie_host_info *host_info = &pcie->host_info; /* host支持RC模式时,需要通过内核接口触发probe */ if (test_bit(NDRV_PCIE_RP_MODE, &(host_info->type_support_mask)) != 0) { return udrv_pcie_host_common_probe(pdev, &pcie->ops->host_ops->ecam_ops); } else { /* 不支持rc的host(ep or switch),不调用内核接口创建host,直接初始化芯片 */ return udrv_pcie_host_ep_init(pdev); } } static struct udrv_pcie_host_ops g_pcie_host_ops_for_dt = { .ecam_ops = { .bus_shift = 20, /* 20bus的起始bit */ .init = udrv_pcie_host_ecam_init, .pci_ops = { .map_bus = udrv_pcie_ecam_map_bus, .read = pci_generic_config_read, .write = pci_generic_config_write, } }, .probe = udrv_pcie_host_probe_for_dt, .get_info = udrv_pcie_get_host_info_from_dt, .init = udrv_pcie_host_init, }; static struct udrv_pcie_port_ops g_pcie_port_ops_for_dt = { .get_info = udrv_pcie_get_port_info_from_dt, .init = udrv_pcie_port_init, }; static struct udrv_pcie_msi_ops g_pcie_msi_ops_for_dt = { .get_info = udrv_pcie_get_msi_info_from_dt, .init = udrv_pcie_msi_init, }; static const struct udrv_pcie_ops g_pcie_ops_for_dt = { .port_ops = &g_pcie_port_ops_for_dt, .host_ops = &g_pcie_host_ops_for_dt, .msi_ops = &g_pcie_msi_ops_for_dt, }; static const struct of_device_id g_udrv_pcie_of_match[] = { { .compatible = "hisilicon,udrv-pcie-ecam-dt", .data = &g_pcie_host_ops_for_dt.ecam_ops, }, {}, }; MODULE_DEVICE_TABLE(of, g_udrv_pcie_of_match); static const struct udrv_pcie_ops *udrv_pcie_get_host_ops(struct device *dev) { return &g_pcie_ops_for_dt; } static int udrv_pcie_probe(struct platform_device *pdev) { int ret = 0; struct device *dev = &pdev->dev; struct udrv_pcie_host *pcie = NULL; const struct udrv_pcie_ops *ops = udrv_pcie_get_host_ops(dev); if (!ops) { dev_err(dev, "[iWare][Error] get ops fail\n"); return -EINVAL; } pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); if (!pcie) { dev_err(dev, "[iWare][Error] devm_kzalloc fail\n"); return -ENOMEM; } INIT_LIST_HEAD(&pcie->host_info.atu_info.entry); INIT_LIST_HEAD(&pcie->port_info.entry); pcie->ops = ops; pcie->dev = dev; platform_set_drvdata(pdev, pcie); list_add_tail(&pcie->node, &pcie_host_list); if ((ops->host_ops) && (ops->host_ops->get_info(pcie) != 0)) { pr_err("[iWare][Error] get host dts info failed \n"); ret = -EINVAL; goto err_host; } if ((ops->port_ops) && (ops->port_ops->get_info(pcie) != 0)) { pr_err("[iWare][Error] get port dts info failed \n"); ret = -EINVAL; goto err_port; } if ((ops->msi_ops) && (ops->msi_ops->get_info(pcie) != 0)) { pr_err("[iWare][Error] get msi dts info failed \n"); ret = -EINVAL; goto err_msi; } if ((ops->host_ops) && (ops->host_ops->probe(pcie) != 0)) { pr_err("[iWare][Error] pcie probe failed \n"); ret = -EINVAL; goto err_probe; } #ifdef CONFIG_UDRV_FMEA ret = pcie_fmea_init(pcie); if (ret != 0) { pr_err("[iWare][Error] fmea init failed,ret=%d\n", ret); goto err_fmea; } #endif #ifdef CONFIG_UDRV_KDRV_INFECTED ret = kdrv_pcie_probe_infected_callback(pcie); if (ret != 0) { pr_err("[iWare][Error] kdrv_pcie_probe_infected_callback fail %d\n", ret); goto err_infected_callback; } #endif return 0; #ifdef CONFIG_UDRV_KDRV_INFECTED err_infected_callback: #endif #ifdef CONFIG_UDRV_FMEA pcie_fmea_deinit(pcie); err_fmea: #endif /* 调用框架和probe对等的remove */ if (test_bit(NDRV_PCIE_RP_MODE, &(pcie->host_info.type_support_mask)) != 0) { (void)udrv_pcie_host_common_remove(pdev); } udrv_pcie_remove_msi(pcie); err_probe: err_msi: udrv_pcie_free_port_info(pcie); err_port: udrv_pcie_free_atu_info(pcie); ndrv_pcie_close_pf(pcie->host_info.pf_handle, pcie->host_info.core_version); err_host: list_del(&pcie->node); return ret; } static int udrv_pcie_remove(struct platform_device *pdev) { struct udrv_pcie_host *pcie = platform_get_drvdata(pdev); struct udrv_pcie_host_info *host_info = &pcie->host_info; #ifdef CONFIG_UDRV_KDRV_INFECTED kdrv_pcie_remove_infected_callback(pcie); #endif #ifdef CONFIG_UDRV_FMEA pcie_fmea_deinit(pcie); #endif /* 调用框架和probe对等的remove */ if (test_bit(NDRV_PCIE_RP_MODE, &(host_info->type_support_mask)) != 0) { (void)udrv_pcie_host_common_remove(pdev); } udrv_pcie_remove_msi(pcie); udrv_pcie_free_port_info(pcie); udrv_pcie_free_atu_info(pcie); ndrv_pcie_close_pf(pcie->host_info.pf_handle, pcie->host_info.core_version); list_del(&pcie->node); return 0; } static struct platform_driver g_udrv_pcie_dt_driver = { .probe = udrv_pcie_probe, .remove = udrv_pcie_remove, .driver = { .name = "udrv-pcie", .of_match_table = g_udrv_pcie_of_match, }, }; struct platform_driver *udrv_get_pcie_dt_driver(void) { return &g_udrv_pcie_dt_driver; } static struct platform_driver * const drivers[] = { &g_udrv_pcie_dt_driver, }; int find_pcie_host_by_id(struct device *dev, void *data) { struct pcie_find_data *pcie_search_info = (struct pcie_find_data *)data; struct udrv_pcie_host *pcie = dev_get_drvdata(dev); if (pcie->host_info.host_id == pcie_search_info->host_id) { pcie_search_info->pcie = pcie; return 1; // 找到了退出遍历dev } return 0; } struct udrv_pcie_host *hisi_pcie_get_by_host_id(uint32_t host_id) { int ret; struct pcie_find_data pcie_search_info = { 0 }; pcie_search_info.host_id = host_id; ret = driver_for_each_device(&g_udrv_pcie_dt_driver.driver, NULL, &pcie_search_info, find_pcie_host_by_id); if (pcie_search_info.pcie == NULL) { // 找没找到直接判断返回的hipcie,不依赖driver_for_each_device返回值 pr_err("[iWare][Error] find pcie fail: host_id = %u\n", host_id); return NULL; } return pcie_search_info.pcie; } static int __init udrv_pcie_init(void) { return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); } static void __exit udrv_pcie_exit(void) { platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); } module_init(udrv_pcie_init); module_exit(udrv_pcie_exit); MODULE_LICENSE("Dual BSD/GPL");
最新发布
10-24
/* * SEMIDRIVE Copyright Statement * Copyright (c) SEMIDRIVE. All rights reserved * This software and all rights therein are owned by SEMIDRIVE, * and are protected by copyright law and other relevant laws, regulations and protection. * Without SEMIDRIVE’s prior written consent and /or related rights, * please do not use this software or any potion thereof in any form or by any means. * You may not reproduce, modify or distribute this software except in compliance with the License. * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * You should have received a copy of the License along with this program. * If not, see <http://www.semidrive.com/licenses/>. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/component.h> #include <linux/fs.h> #include <linux/dma-buf.h> #include <linux/interrupt.h> #include <linux/iommu.h> #include <linux/pm_runtime.h> #include <linux/bitops.h> #include <linux/uaccess.h> #include <linux/list.h> #include <linux/string.h> #include <linux/bug.h> #include <linux/errno.h> #include <asm/current.h> #ifdef CONFIG_OF #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_device.h> #include <linux/of_platform.h> #else #include <linux/slab.h> #include <linux/io.h> #include <linux/irq.h> #endif #include "sdrv_g2d.h" #include "g2d_common.h" static DEFINE_MUTEX(m_init); extern const struct g2d_ops g2d_normal_ops; extern const struct g2d_ops g2d_lite_ops; extern struct ops_entry spipe_g2d_entry; extern struct ops_entry gpipe_mid_g2d_entry; extern struct ops_entry gpipe_high_g2d_entry; extern int g2d_dump_registers(struct sdrv_g2d *dev); extern int g2d_post_config(struct sdrv_g2d *dev, struct g2d_input *ins); extern int g2d_fastcopy_set(struct sdrv_g2d *dev, addr_t iaddr, u32 width, u32 height, u32 istride, addr_t oaddr, u32 ostride); extern int g2d_fill_rect(struct sdrv_g2d *dev, struct g2d_bg_cfg *bgcfg, struct g2d_output_cfg *output); extern int g2d_set_coefficients_table(struct sdrv_g2d *gd, struct g2d_coeff_table *table); extern struct attribute *sdrv_g2d_attrs[]; static const struct attribute_group *sdrv_g2d_groups[]; ATTRIBUTE_GROUPS(sdrv_g2d); static int wait_timeout = 500; module_param(wait_timeout, int, 0660); MODULE_PARM_DESC(wait_timeout, "wait timeout (ms)"); static int dump_register_g2d = 0; module_param(dump_register_g2d, int, 0660); MODULE_PARM_DESC(dump_register_g2d, "dump register g2d 0:off 1:on"); int debug_g2d = 0; EXPORT_SYMBOL(debug_g2d); module_param(debug_g2d, int, 0660); MODULE_PARM_DESC(debug_g2d, "debug g2d 0:off 1:on"); static char *version = KO_VERSION; module_param(version, charp, S_IRUGO); LIST_HEAD(g2d_pipe_list_head); int g2d_major = 227; int g2d_minor = -1; static struct sdrv_g2d *g_g2d[G2D_NR_DEVS]; const char *PIPE_TYPE_STRING[] = { GP_ECHO_NAME, GP_MID_NAME, GP_HIGH_NAME, SPIPE_NAME }; struct sdrv_g2d_data g2d_data[] = { {.version = "g2dlite-r0p0", .ops = &g2d_lite_ops}, {.version = "g2d-r0p1", .ops = &g2d_normal_ops}, {}, }; static void dump_input(struct g2d_input *input) { struct g2d_output_cfg *output = &input->output; struct g2d_layer *layer; struct g2d_bg_cfg *bg = &input->bg_layer; int i = 0; if (bg->en) { G2D_ERROR("[dump bg layer] en:%d, color:0x%x, g_alpha:0x%x, zorder:%d, bpa:0x%x, \ astride:%d, rect(%d, %d, %d, %d), pd_type:%d, fd:%d \n", bg->en, bg->color, bg->g_alpha, bg->zorder, bg->bpa, bg->astride, bg->x, bg->y, bg->width, bg->height, bg->pd_type, bg->abufs.fd); } for (i = 0; i < input->layer_num; i++) { layer = &input->layer[i]; G2D_ERROR("[dumplayer] index = %d, *ENABLE = %d*, format: %c%c%c%c source (%d, %d, %d, %d) => dest (%d, %d, %d, %d)\n", layer->index, layer->enable, layer->format & 0xff, (layer->format >> 8) & 0xff, (layer->format >> 16) & 0xff, (layer->format >> 24) & 0xff, layer->src_x, layer->src_y, layer->src_w, layer->src_h, layer->dst_x, layer->dst_y, layer->dst_w, layer->dst_h); } G2D_ERROR("[dump output]: w,h(%d,%d) format:%c%c%c%c rota:%d nplanes:%d\n", output->width, output->height, output->fmt & 0xff, (output->fmt >> 8) & 0xff, (output->fmt >> 16) & 0xff, (output->fmt >> 24) & 0xff, output->rotation, output->nplanes); return; } struct sdrv_g2d *get_g2d_by_id(int id) { return g_g2d[id]; } int g2d_ops_register(struct ops_entry *entry, struct list_head *head) { struct ops_list *list; list = kzalloc(sizeof(struct ops_list), GFP_KERNEL); if (!list) return -ENOMEM; list->entry = entry; list_add(&list->head, head); return 0; } void *g2d_ops_attach(const char *str, struct list_head *head) { struct ops_list *list; const char *ver; list_for_each_entry(list, head, head) { ver = list->entry->ver; if (!strcmp(str, ver)) return list->entry->ops; } G2D_ERROR("attach disp ops %s failed\n", str); return NULL; } irqreturn_t sdrv_g2d_irq_handler(int irq, void *data) { struct sdrv_g2d *gd = data; uint32_t val; if (!gd->du_inited) { G2D_ERROR("g2d du_inited does not init\n"); return IRQ_HANDLED; } val = gd->ops->irq_handler(gd); if (val & G2D_INT_MASK_FRM_DONE) { G2D_DBG("frame done\n"); gd->frame_done = true; wake_up(&gd->wq); } return IRQ_HANDLED; } int g2d_choose_pipe(struct sdrv_g2d *gd, int hwid, int type, uint32_t offset) { struct g2d_pipe *p = NULL; p = devm_kzalloc(&gd->pdev->dev, sizeof(struct g2d_pipe), GFP_KERNEL); if (!p) return -ENOMEM; p->type = type; p->name = PIPE_TYPE_STRING[type]; p->ops = (struct pipe_operation*)g2d_pipe_ops_attach(p->name); if (!p->ops) { G2D_ERROR("error ops attached\n"); return -EINVAL; } p->regs = gd->regs + (ulong)offset; p->iomem_regs = gd->iomem_regs + (ulong)offset; p->reg_offset = offset; p->id = hwid; p->gd = gd; gd->pipes[gd->num_pipe] = p; gd->num_pipe++; p->ops->init(p); G2D_DBG("pipe %d name %s registered\n", p->id, p->name); return 0; } #ifdef CONFIG_OF int sdrv_g2d_init(struct sdrv_g2d *gd, struct device_node *np) { int i, ret; int irq_num; struct resource res; const char *str; const struct sdrv_g2d_data *data; static int g2d_cnt = 0; if (!np || !gd) return -ENODEV; if(!of_device_is_available(np)) { G2D_ERROR("OF node %s not available or match\n", np->name); return -ENODEV; } if (!of_property_read_string(np, "sdrv,ip", &str)) { gd->name = str; } else { G2D_ERROR("sdrv,ip can not found\n"); return -ENODEV; } if (of_address_to_resource(np, 0, &res)) { G2D_ERROR("parse dt base address failed\n"); return -ENODEV; } G2D_INFO("got %s res 0x%lx\n", gd->name, (unsigned long)res.start); gd->regs = (void *)res.start; gd->iomem_regs = devm_ioremap_nocache(&gd->pdev->dev, res.start, resource_size(&res)); if(IS_ERR(gd->iomem_regs)) { G2D_ERROR("Cannot find g2d regs 001\n"); return PTR_ERR(gd->regs); } irq_num = irq_of_parse_and_map(np, 0); if (!irq_num) { G2D_ERROR("error: g2d parse irq num failed\n"); return -EINVAL; } G2D_INFO("g2d irq_num = %d\n", irq_num); data = of_device_get_match_data(&gd->pdev->dev); for (i = 0; i < 3; i++) { if (!strcmp(gd->name, data[i].version)) { gd->ops = data[i].ops; G2D_INFO("%s ops[%d] attached\n", gd->name, i); break; } } if (gd->ops == NULL) { G2D_ERROR("core ops attach failed, have checked %d times\n", i); return -1; } gd->num_pipe = 0; // g2d init gd->ops->init(gd); gd->irq = irq_num; gd->cap.num_pipe = gd->num_pipe; for (i = 0; i < gd->num_pipe; i++) { memcpy(&gd->cap.pipe_caps[i], gd->pipes[i]->cap, sizeof(struct g2d_pipe_capability)); } gd->id = g2d_cnt; irq_set_status_flags(gd->irq, IRQ_NOAUTOEN); ret = devm_request_irq(&gd->pdev->dev, gd->irq, sdrv_g2d_irq_handler, 0, dev_name(&gd->pdev->dev), gd); //IRQF_SHARED if(ret) { G2D_ERROR("Failed to request DC IRQ: %d\n", gd->irq); return -ENODEV; } //wait queue init_waitqueue_head(&gd->wq); gd->frame_done = false; g2d_cnt++; return 0; } #else int sdrv_g2d_init(struct sdrv_g2d *gd, struct platform_device *pdev) { int i, ret; int irq_num; struct device *dev = &pdev->dev; struct resource *res; const char *str; const struct sdrv_g2d_data *data; struct g2d_platform_data *pdata; static int g2d_cnt = 0; if (!pdev || !gd) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); gd->regs = (void *)res->start; gd->iomem_regs = devm_ioremap_nocache(&gd->pdev->dev, res->start, resource_size(res)); if(IS_ERR(gd->iomem_regs)) { G2D_ERROR("Cannot find g2d regs 001\n"); return PTR_ERR(gd->regs); } pdata = (struct g2d_platform_data *)platform_get_drvdata(pdev); gd->name = "g2d-r0p1"; if (!gd->name) { G2D_ERROR("sdrv,ip can not found\n"); return -ENODEV; } G2D_INFO("got %s res 0x%lx\n", gd->name, (unsigned long)gd->regs); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq_num = (int) res->start; if (!irq_num) { G2D_ERROR("error: g2d parse irq num failed\n"); return -EINVAL; } G2D_INFO("g2d irq_num = %d\n", irq_num); data = g2d_data; for (i = 0; i < 16; i++) { if (!strcmp(gd->name, data[i].version)) { gd->ops = data[i].ops; G2D_DBG("%s ops[%d] attached\n", gd->name, i); break; } } if (gd->ops == NULL) { G2D_ERROR("core ops attach failed, have checked %d times\n", i); return -1; } gd->num_pipe = 0; // g2d init gd->ops->init(gd); gd->irq = irq_num; gd->cap.num_pipe = gd->num_pipe; for (i = 0; i < gd->num_pipe; i++) { memcpy(&gd->cap.pipe_caps[i], gd->pipes[i]->cap, sizeof(struct g2d_pipe_capability)); } gd->id = g2d_cnt; irq_set_status_flags(gd->irq, IRQ_NOAUTOEN); ret = devm_request_irq(&gd->pdev->dev, gd->irq, sdrv_g2d_irq_handler, 0, dev_name(&gd->pdev->dev), gd); //IRQF_SHARED if(ret) { G2D_ERROR("Failed to request DC IRQ: %d\n", gd->irq); return -ENODEV; } //wait queue init_waitqueue_head(&gd->wq); gd->frame_done = false; g2d_cnt++; return 0; } #endif static void sdrv_g2d_unit(struct sdrv_g2d *gd) { if (!gd) return; // if (gd->ops->uninit) // gd->ops->uninit(gd); } static int sdrv_g2d_open(struct inode *node, struct file *file) { int i; struct sdrv_g2d *gd = NULL; int num = MINOR(node->i_rdev); if (num < 0) return -ENODEV; for (i = 0; i < G2D_NR_DEVS; i++){ gd = get_g2d_by_id(i); if (gd->mdev.minor == num) break; } file->private_data = gd; G2D_DBG("open node %s\n", gd->name); return 0; } static int sdrv_init_iommu(struct sdrv_g2d *gd) { struct device *dev = &gd->pdev->dev; struct device_node *iommu = NULL; struct property *prop = NULL; struct iommu_domain_geometry *geometry; u64 start, end; int ret = 0; gd->iommu_enable = false; iommu = of_parse_phandle(dev->of_node, "iommus", 0); if(!iommu) { G2D_DBG("iommu not specified\n"); return ret; } if (!of_device_is_available(iommu)) { G2D_DBG("smmu disabled\n"); return ret; } prop = of_find_property(dev->of_node, "smmu", NULL); if(!prop) { G2D_DBG("smmu bypassed\n"); return ret; } gd->domain = iommu_get_domain_for_dev(dev); if(!gd->domain) { ret = -ENOMEM; goto err_free_mm;; } geometry = &gd->domain->geometry; start = geometry->aperture_start; end = GENMASK(37, 0);// 38 bits address for KUNLUN G2D rdma G2D_DBG("IOMMU context initialized: %#llx - %#llx\n", start, end); gd->iommu_enable = true; of_node_put(iommu); return ret; err_free_mm: of_node_put(iommu); return ret; } static void sdrv_iommu_cleanup(struct sdrv_g2d *gd) { if(!gd->iommu_enable) return; iommu_domain_free(gd->domain); } static unsigned long _get_contiguous_size(struct sg_table *sgt) { struct scatterlist *s; dma_addr_t expected = sg_dma_address(sgt->sgl); unsigned int i; unsigned long size = 0; for_each_sg(sgt->sgl, s, sgt->nents, i) { if (sg_dma_address(s) != expected) break; expected = sg_dma_address(s) + sg_dma_len(s); size += sg_dma_len(s); } return size; } static int g2d_dmabuf_import(struct sdrv_g2d *gd, struct g2d_buf *buf) { struct dma_buf_attachment *attach; struct sg_table *sgt; struct dma_buf *dmabuf; int ret = 0; if (buf->fd < 0) { G2D_ERROR("dmabuf handle invalid: %d\n", buf->fd); return -EINVAL; } buf->vaddr = (unsigned long)NULL; dmabuf = dma_buf_get(buf->fd); if (IS_ERR_OR_NULL(dmabuf)) { G2D_ERROR("g2d get dmabuf err from buf fd %d\n", buf->fd); return PTR_ERR(dmabuf); } attach = dma_buf_attach(dmabuf, &gd->pdev->dev); if (IS_ERR(attach)) { G2D_ERROR("dma buf attach devices faild\n"); goto out_put; } sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); if (IS_ERR(sgt)) { ret = PTR_ERR(sgt); G2D_ERROR("Error getting dmabuf scatterlist: errno %ld\n", PTR_ERR(sgt)); goto fail_detach; } buf->attach = attach; buf->size = _get_contiguous_size(sgt); buf->dma_addr = sg_dma_address(sgt->sgl); buf->sgt = sgt; buf->vaddr = (unsigned long)NULL; G2D_DBG("buf->size = 0x%llx \n", buf->size); if (!buf->size) { G2D_ERROR("dma buf map attachment faild, buf->size = %lld \n", buf->size); ret = -EINVAL; goto fail_unmap; } goto out_put; fail_unmap: dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); fail_detach: dma_buf_detach(dmabuf, attach); out_put: dma_buf_put(dmabuf); return ret; } static void g2d_dmabuf_release(struct sdrv_g2d *gd, struct g2d_buf *buf) { struct sg_table *sgt = buf->sgt; struct dma_buf *dmabuf; if (IS_ERR_OR_NULL(sgt)) { G2D_ERROR("dmabuf buffer is already unpinned \n"); return; } if (IS_ERR_OR_NULL(buf->attach)) { G2D_ERROR("trying to unpin a not attached buffer\n"); return; } dmabuf = dma_buf_get(buf->fd); if (IS_ERR_OR_NULL(dmabuf)) { G2D_ERROR("invalid dmabuf from dma_buf_get: %d", buf->fd); return; } G2D_DBG("buf->vaddr = 0x%ld\n", (unsigned long)buf->vaddr); if (buf->vaddr) { dma_buf_vunmap(dmabuf, (void *)buf->vaddr); buf->vaddr = (unsigned long)NULL; } dma_buf_unmap_attachment(buf->attach, sgt, 0); buf->dma_addr = 0; buf->sgt = NULL; dma_buf_detach(dmabuf, buf->attach); dma_buf_put(dmabuf); } static int g2d_alph_layer_mmap(struct sdrv_g2d *gd, struct g2d_bg_cfg *bgcfg) { int ret = 0; struct g2d_buf *buf = &bgcfg->abufs; if (buf->fd > 0) { ret = g2d_dmabuf_import(gd, buf); if (ret) { G2D_ERROR("g2d alph layer mmap faild \n"); return ret; } bgcfg->aaddr = buf->dma_addr; G2D_DBG("alph layer used, fd is valid: fd = %d , phy addr = 0x%llx\n", buf->fd, bgcfg->aaddr); } else { G2D_DBG("alph layer used, fd is invalid, aaddr = 0x%llx \n", bgcfg->aaddr); } return ret; } static int g2d_layer_mmap(struct sdrv_g2d *gd, struct g2d_layer *layer) { int ret, i, j; struct g2d_buf *buf = &layer->bufs[0]; uint32_t tmp_addr_h; uint32_t tmp_addr_l; if (buf->fd <= 0) { G2D_ERROR("input layer buf fd invaild, fd(%d) <= 0\n", buf->fd); return -EINVAL; } ret = g2d_dmabuf_import(gd, buf); if (ret) { G2D_ERROR("g2d input layer mmap faild \n"); return ret; } G2D_DBG("layer->nplanes = %d\n", layer->nplanes); for (i = 0; i < layer->nplanes; i++) { unsigned long addr = buf->dma_addr + layer->offsets[i]; layer->addr_l[i] = get_l_addr(addr); layer->addr_h[i] = get_h_addr(addr); G2D_DBG("layer[%d] addr_l[%d] = 0x%x addr_h[%d] = 0x%x\n", layer->index, i, layer->addr_l[i], i, layer->addr_h[i]); } if(layer->format == DRM_FORMAT_BGR888_PLANE) { if (layer->nplanes != 3) { G2D_ERROR("format set : DRM_FORMAT_BGR888_PLANE, but nplanes(%d) != 3 \n", layer->nplanes); return -1; } tmp_addr_l = layer->addr_l[0]; tmp_addr_h = layer->addr_h[0]; layer->addr_l[0] = layer->addr_l[2]; layer->addr_h[0] = layer->addr_h[2]; layer->addr_l[2] = tmp_addr_l; layer->addr_h[2] = tmp_addr_h; for (j = 0; j < layer->nplanes; j++) { G2D_DBG("layer[%d] addr_l[%d] = 0x%x addr_h[%d] = 0x%x\n", layer->index, j, layer->addr_l[j], j, layer->addr_h[j]); } } return 0; } int g2d_output_layer_mmap(struct sdrv_g2d *gd, struct g2d_output_cfg *layer) { int ret; int j; uint64_t tmp_addr; struct g2d_buf *buf = &layer->bufs[0]; if (buf->fd <= 0) { G2D_ERROR("output layer buf fd invaild, fd(%d) <= 0\n", buf->fd); return -EINVAL; } ret = g2d_dmabuf_import(gd, buf); if (ret) { G2D_ERROR("g2d output layer mmap faild \n"); return ret; } for (j = 0; j < layer->nplanes; j++) { layer->addr[j] = buf->dma_addr + layer->offsets[j]; G2D_DBG("layer->addr[%d] = 0x%llx \n", j, layer->addr[j]); } if(layer->fmt == DRM_FORMAT_BGR888_PLANE) { if (layer->nplanes != 3) { G2D_ERROR("fmt set : DRM_FORMAT_BGR888_PLANE, but nplanes(%d) != 3 \n", layer->nplanes); return -1; } tmp_addr = layer->addr[0]; layer->addr[0] = layer->addr[2]; layer->addr[2] = tmp_addr; for (j = 0; j < layer->nplanes; j++) { G2D_DBG("fmt == DRM_FORMAT_BGR888_PLANE : layer->addr[%d] = 0x%llx \n", j, layer->addr[j]); } } return 0; } void g2d_alph_layer_unmap(struct sdrv_g2d *gd, struct g2d_bg_cfg *bgcfg) { struct g2d_buf *buf = &bgcfg->abufs; G2D_DBG("g2d dmabuf:%d\n", buf->fd); if (buf->fd <= 0) return; g2d_dmabuf_release(gd, buf); } void g2d_layer_unmap(struct sdrv_g2d *gd, struct g2d_layer *layer) { struct g2d_buf *buf = &layer->bufs[0]; G2D_DBG("g2d dmabuf:%d\n", buf->fd); if (buf->fd <= 0) return; g2d_dmabuf_release(gd, buf); } void g2d_output_layer_unmap(struct sdrv_g2d *gd, struct g2d_output_cfg *layer) { struct g2d_buf *buf = &layer->bufs[0]; G2D_DBG("g2d dmabuf:%d\n", buf->fd); if (buf->fd <= 0) return; g2d_dmabuf_release(gd, buf); } static int g2d_ioctl_begin(struct sdrv_g2d *gd, struct g2d_input *input) { int i; int ret; set_user_nice(current, -12); /*bg layer*/ if (input->bg_layer.en) { ret = g2d_alph_layer_mmap(gd, &input->bg_layer); if (ret) { return ret; } } /*input layer*/ for (i = 0; i < input->layer_num; i++) { struct g2d_layer *l = &input->layer[i]; if (!l->enable) continue; ret = g2d_layer_mmap(gd, l); if (ret) { return ret; } } /*output layer*/ ret = g2d_output_layer_mmap(gd, &input->output); if (ret) { return ret; } return 0; } static void g2d_ioctl_finish(struct sdrv_g2d *gd, struct g2d_input *input) { int i; /*bg layer*/ if (input->bg_layer.en) { g2d_alph_layer_unmap(gd, &input->bg_layer); } /*input layer*/ for (i = 0; i < input->layer_num; i++) { struct g2d_layer *l = &input->layer[i]; if (!l->enable) continue; g2d_layer_unmap(gd, l); } /*output layer*/ g2d_output_layer_unmap(gd, &input->output); } static int g2d_wait(struct sdrv_g2d *gd) { int status = 0; int rc; //g2d_dump_registers(gd); /* wait for stop done interrupt wait_event_timeout */ rc = wait_event_timeout(gd->wq, (gd->frame_done == true), msecs_to_jiffies(wait_timeout)); gd->frame_done = false; if (!rc) { status = -1; G2D_ERROR("g2d operation wait timeout %d\n", wait_timeout); g2d_dump_registers(gd); } else { if (dump_register_g2d == 1) { g2d_dump_registers(gd); } G2D_DBG("wait time %d\n", rc); } if (gd->ops->reset) gd->ops->reset(gd); return status; } static int g2d_fill_rect_ioctl(struct sdrv_g2d *gd, struct g2d_input *input) { int ret; ret = g2d_fill_rect(gd, &input->bg_layer, &input->output); if (ret < 0) { G2D_ERROR("g2d fill rect set register err \n"); goto OUT; } ret = g2d_wait(gd); OUT: if (ret < 0) dump_input(input); return ret; } static int g2d_fastcopy_dmabuf(struct sdrv_g2d *gd, struct g2d_input *input) { int ret = -1; addr_t iaddr, oaddr; struct g2d_output_cfg *out_layer = &input->output; struct g2d_bg_cfg *bg_layer = &input->bg_layer; struct g2d_buf *buf; if (!bg_layer->en) { G2D_ERROR("bg_layer en is %d, fast copy cannot be used\n", bg_layer->en); return ret; } iaddr = bg_layer->aaddr; buf = &out_layer->bufs[0]; oaddr = buf->dma_addr + out_layer->offsets[0]; if (iaddr % 4) { G2D_ERROR("The phy-addr(0x%lx) of the input needs to be 4-byte aligned\n", iaddr); return ret; } if (oaddr % 4) { G2D_ERROR("The phy-addr(0x%lx) of the output needs to be 4-byte aligned\n", oaddr); return ret; } if ((iaddr <= 0) || (oaddr <= 0)) { G2D_ERROR("input iaddr(0x%lx) or oaddr(0x%lx) = null\n", iaddr, oaddr); return ret; } ret = g2d_fastcopy_set(gd, iaddr, out_layer->width, out_layer->height, bg_layer->astride, oaddr, out_layer->stride[0]); if (ret < 0) { G2D_ERROR("g2d_fastcopy set register err \n"); goto OUT; } ret = g2d_wait(gd); OUT: if (ret < 0) dump_input(input); return ret; } static int sdrv_g2d_post_config(struct sdrv_g2d *gd, struct g2d_input *input) { int ret = 0; ret = g2d_post_config(gd, input); if(ret < 0) goto OUT; ret = g2d_wait(gd); OUT: if (ret < 0) dump_input(input); return ret; } static int sdrv_g2d_tasks(struct sdrv_g2d *gd, unsigned int cmd, struct g2d_input *input) { int ret; mutex_lock(&gd->m_lock);/*加锁确保原子操作*/ if (gd->monitor.is_monitor) gd->monitor.g2d_on_task = true; if (input->tables.set_tables) {//set filter tables g2d_set_coefficients_table(gd, &input->tables); } switch (cmd) { case G2D_IOCTL_POST_CONFIG:/*多层合成*/ ret = sdrv_g2d_post_config(gd, input); G2D_DBG(" G2D_IOCTL_POST_CONFIG ret = %d\n", ret); break; case G2D_IOCTL_FAST_COPY:/*快速内存拷贝*/ ret = g2d_fastcopy_dmabuf(gd, input); G2D_DBG("G2D_IOCTL_FAST_COPY end ret = %d\n", ret); break; case G2D_IOCTL_FILL_RECT:/*矩形填充*/ ret = g2d_fill_rect_ioctl(gd, input); G2D_DBG("G2D_IOCTL_FILL_RECT end ret = %d\n", ret); break; default: G2D_ERROR("Invalid ioctl cmd: 0x%x\n", cmd); ret = -EINVAL; break; } if (input->tables.set_tables) {//reset filter tables input->tables.set_tables = false; g2d_set_coefficients_table(gd, &input->tables); } if (gd->monitor.is_monitor) gd->monitor.g2d_on_task = false; mutex_unlock(&gd->m_lock);/*释放锁*/ return ret; } void sdrv_dpc_to_g2d_layer(struct dpc_layer *int_layer, struct g2d_layer *out_layer) { out_layer->index = int_layer->index; //plane index out_layer->enable = int_layer->enable; out_layer->nplanes = int_layer->nplanes; out_layer->src_x = int_layer->src_x; out_layer->src_y = int_layer->src_y; out_layer->src_w = int_layer->src_w; out_layer->src_h = int_layer->src_h; out_layer->dst_x = int_layer->dst_x; out_layer->dst_y = int_layer->dst_y; out_layer->dst_w = int_layer->dst_w; out_layer->dst_h = int_layer->dst_h; out_layer->format = int_layer->format; out_layer->alpha = int_layer->alpha; out_layer->blend_mode = int_layer->blend_mode; out_layer->rotation = int_layer->rotation; out_layer->zpos = int_layer->zpos; out_layer->xfbc = int_layer->xfbc; out_layer->modifier = int_layer->modifier; out_layer->width = int_layer->width; out_layer->height = int_layer->height; memcpy(out_layer->addr_l, int_layer->addr_l, sizeof(out_layer->addr_l)); memcpy(out_layer->addr_h, int_layer->addr_h, sizeof(out_layer->addr_h)); memcpy(out_layer->pitch, int_layer->pitch, sizeof(out_layer->pitch)); memcpy(&out_layer->comp, &int_layer->comp, sizeof(struct pix_g2dcomp)); memcpy(&out_layer->ctx, &int_layer->ctx, sizeof(struct tile_ctx)); } int sdrv_g2d_convert_format(struct dpc_layer *layer, uint32_t g2d_out_format) { int ret = 0, i = 0; struct sdrv_g2d *gd = g_g2d[0]; struct g2d_input *input = NULL; uint32_t size = 0; static dma_addr_t paddr[2]; static void *vaddr[2]; static uint8_t index = 0; if (!gd) { G2D_ERROR("g2d hasn't exist\n"); return -ENODEV; } input = kzalloc(sizeof(struct g2d_input), GFP_KERNEL); if (!input) { G2D_ERROR("alloc input error\n"); return -ENOMEM; } size = layer->src_w * layer->src_h * 2; size = round_up(size, PAGE_SIZE); if (!vaddr[0]) { for (i = 0; i < 2; i++) { vaddr[i] = dma_alloc_wc(&gd->pdev->dev, size, &paddr[i], GFP_KERNEL | __GFP_NOWARN); if(!vaddr[i]) { G2D_ERROR("failed to allocate buffer of size %u\n", size); goto alloc_dma_err; } pr_info("dma addr[%d]:0x%llx vaddr[%d]:0x%p\n", i ,paddr[i], i, vaddr[i]); } } input->layer_num = 1; memcpy(&input->layer[0], layer, sizeof(struct g2d_layer)); sdrv_dpc_to_g2d_layer(layer, &input->layer[0]); pr_debug("format:%x, w:%d, h:%d s:%d al:%x\n", layer->format, layer->src_w, layer->src_h, layer->pitch[0], layer->addr_l[0]); input->output.width = layer->dst_w; input->output.height = layer->dst_h; input->output.stride[0] = layer->dst_w * 2; input->output.fmt = g2d_out_format; input->output.nplanes = 1; input->output.addr[0] = paddr[index]; pr_debug("o format:%x, w:%d, h:%d s:%d a:%llx\n", input->output.fmt, input->output.width, input->output.height, input->output.stride[0], input->output.addr[0]); mutex_lock(&gd->m_lock); ret = sdrv_g2d_post_config(gd, input); if (ret) { mutex_unlock(&gd->m_lock); goto out; } mutex_unlock(&gd->m_lock); layer->addr_l[0] = get_l_addr(input->output.addr[0]); layer->addr_h[0] = get_h_addr(input->output.addr[0]); layer->src_h = input->output.height; layer->src_w = input->output.width; layer->dst_h = input->output.height; layer->dst_w = input->output.width; layer->pitch[0] = input->output.stride[0]; index ++; if (index >= 2) index = 0; out: kfree(input); return ret; alloc_dma_err: while (i) { dma_free_wc(&gd->pdev->dev, size, vaddr[i], paddr[i]); i--; } kfree(input); return -ENOMEM; } EXPORT_SYMBOL(sdrv_g2d_convert_format); static int sdrv_g2d_func_work(struct sdrv_g2d *gd, unsigned int cmd, struct g2d_input *input) { int ret; if (!gd || !input) { G2D_ERROR("dev or input isn't inited.[dev:%p, ins:%p]\n", gd, input); return -EINVAL; } if ((input->output.height <= 0) || (input->output.width <= 0)) { G2D_ERROR("output input->output.height = %d, input->output.width = %d\n", input->output.height, input->output.width); return -EINVAL; } G2D_DBG("\r\n"); ret = g2d_ioctl_begin(gd, input); if (ret) { G2D_ERROR("input parameter err\n"); goto finish_out; } ret = sdrv_g2d_tasks(gd, cmd, input); finish_out: g2d_ioctl_finish(gd, input); return ret; } int sdrv_g2d_dma_copy(dma_addr_t dst, dma_addr_t src, size_t data_size) { int ret = 0; struct g2d_input *input; struct sdrv_g2d *gd = g_g2d[0]; int width, height, stride; width = 32; stride = width * 4; height = (data_size / stride) + ((data_size % stride) ? 1 : 0); G2D_DBG("data_size, width, stride, height : (%ld, %d, %d, %d)\n", data_size, width, stride, height); input = kzalloc(sizeof(struct g2d_input), GFP_ATOMIC | GFP_DMA); if (!input) { G2D_ERROR("kzalloc input failed\n"); return -EFAULT; } input->bg_layer.en = 1; input->bg_layer.width = width; input->bg_layer.height = height; input->bg_layer.astride = stride; input->bg_layer.aaddr = (uint64_t)src; input->output.bufs[0].dma_addr = (uint64_t)dst; input->output.width = width; input->output.height = height; input->output.stride[0] = stride; ret = sdrv_g2d_tasks(gd, G2D_IOCTL_FAST_COPY, input); kfree(input); return ret; } EXPORT_SYMBOL(sdrv_g2d_dma_copy); static long sdrv_g2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -1; int i=0, n = 0; struct sdrv_g2d *gd = file->private_data; struct g2d_input *input; struct g2d_inputx *inputx; if (_IOC_TYPE(cmd) != G2D_IOCTL_BASE) return -EINVAL; if (_IOC_NR(cmd) > 4) return -EINVAL; if (_IOC_DIR(cmd) & _IOC_READ) { ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); if (ret) return -EFAULT; } if (_IOC_DIR(cmd) & _IOC_WRITE) { ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); if (ret) return -EFAULT; } inputx = kzalloc(sizeof(struct g2d_inputx), GFP_ATOMIC | GFP_DMA); if (!inputx) { G2D_ERROR("kzalloc input failed\n"); return -EFAULT; } input = kzalloc(sizeof(struct g2d_input), GFP_ATOMIC | GFP_DMA); if (!input) { G2D_ERROR("kzalloc input failed\n"); if (inputx) kfree(inputx); return -EFAULT; } memset(inputx,0,sizeof(struct g2d_inputx)); memset(input,0,sizeof(struct g2d_input)); if (cmd == G2D_IOCTL_GET_CAPABILITIES) { ret = copy_to_user((struct g2d_capability __user *)arg, &gd->cap, sizeof(struct g2d_capability)); if (ret) { G2D_ERROR("get capabilities err \n"); ret = -EFAULT; } } else { ret = copy_from_user(inputx, (struct g2d_inputx __user *)arg, sizeof(struct g2d_inputx)); if (ret) { G2D_ERROR("copy_from_user failed\n"); ret = -EFAULT; goto unlock_out; } //for 32bit and 64 bit capibility; input->layer_num = inputx->layer_num; memcpy((void *)(&input->bg_layer),(void *)(&inputx->bg_layer),sizeof(struct g2d_bg_cfg_x)); input->bg_layer.abufs.dma_addr = input->bg_layer.cfg_buf.dma_addr; input->bg_layer.abufs.fd = input->bg_layer.cfg_buf.fd; input->bg_layer.abufs.size = input->bg_layer.cfg_buf.size; input->bg_layer.abufs.vaddr = input->bg_layer.cfg_buf.vaddr; memcpy((void *)(&input->output), (void *)(&inputx->output),sizeof(struct g2d_output_cfg_x)); for (i = 0; i < 4; i++) { input->output.bufs[i].dma_addr = input->output.out_buf[i].dma_addr; input->output.bufs[i].fd = input->output.out_buf[i].fd; input->output.bufs[i].size = input->output.out_buf[i].size; input->output.bufs[i].vaddr = input->output.out_buf[i].vaddr; } memcpy((void *)(&input->tables), (void *)(&inputx->tables),sizeof(struct g2d_coeff_table)); for (n = 0; n < G2D_LAYER_MAX_NUM;n ++) { memcpy((void *)(&input->layer[n]),(void *)(&inputx->layer[n]),sizeof(struct g2d_layer_x)); for (i = 0; i < 4; i++) { input->layer[n].bufs[i].dma_addr = input->layer[n].in_buf[i].dma_addr; input->layer[n].bufs[i].fd = input->layer[n].in_buf[i].fd; input->layer[n].bufs[i].size = input->layer[n].in_buf[i].size; input->layer[n].bufs[i].vaddr = input->layer[n].in_buf[i].vaddr; } } ret = sdrv_g2d_func_work(gd, cmd, input); } unlock_out: if (input) kfree(input); if (inputx) kfree(inputx); return (long)ret; } #if defined(CONFIG_COMPAT) static long sdrv_g2d_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return sdrv_g2d_ioctl(file, cmd, arg); } #endif /* defined(CONFIG_COMPAT) */ ssize_t sdrv_g2d_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { struct sdrv_g2d *gd = file->private_data; char str[64] = {0}; ssize_t sz = sprintf(str, "read from %s\n", gd->name); if (copy_to_user(buf, str, sz)){ G2D_ERROR("copy to user failed: %s\n", gd->name); } return sz; } static const struct file_operations g2d_fops = { .owner = THIS_MODULE, .open = sdrv_g2d_open, .read = sdrv_g2d_read, .unlocked_ioctl = sdrv_g2d_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = sdrv_g2d_compat_ioctl, #endif }; static int g2d_misc_init(struct sdrv_g2d *gd) { int ret; struct miscdevice *m = &gd->mdev;; m->minor = MISC_DYNAMIC_MINOR; m->name = kasprintf(GFP_KERNEL, "g2d%d", gd->id); m->fops = &g2d_fops; m->parent = NULL; m->groups = sdrv_g2d_groups; ret = misc_register(m); if (ret) { G2D_ERROR("failed to register miscdev\n"); return ret; } G2D_INFO("%s misc register \n", m->name); return ret; } static int sdrv_g2d_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct sdrv_g2d *gd = NULL; static int pipe_registered = 0; dma_addr_t dma_handle; int ret = 0, i; mutex_lock(&m_init); G2D_INFO("G2D BUILD VERSION : %s \n", version); // 38 bits address for KUNLUN G2D rdma,use G2D_CPU_WRITE config 38bit; use G2D_CMD_WRITE config 32bit dma_set_mask(dev, DMA_BIT_MASK(32)); dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); gd = devm_kzalloc(&pdev->dev, sizeof(struct sdrv_g2d), GFP_KERNEL);/*分配设备结构体*/ if (!gd) { G2D_ERROR("kalloc sdrv_g2d failed\n"); ret = -1; goto OUT; } gd->du_inited = false; gd->pdev = pdev; if (!pipe_registered) { pipe_registered++; g2d_pipe_ops_register(&spipe_g2d_entry);/*注册标准管道*/ g2d_pipe_ops_register(&gpipe_high_g2d_entry);/*注册高性能管道*/ g2d_pipe_ops_register(&gpipe_mid_g2d_entry); } /*cmdfile init*//*分配DMA命令缓冲区*/ gd->cmd_info[0].arg = (unsigned int*)dma_alloc_coherent(dev, G2D_CMDFILE_MAX_MEM * sizeof(unsigned int), &dma_handle, GFP_KERNEL); gd->dma_buf = (unsigned long)dma_handle; if (gd->cmd_info[0].arg == NULL) { G2D_ERROR("malloc cmd_info failed\n"); goto OUT; } G2D_INFO("gd->cmd_info[0].arg virtual address = 0x%lx, phy address 0x%lx,dma alloc coherent len = %ld\n", (unsigned long)gd->cmd_info[0].arg, gd->dma_buf, G2D_CMDFILE_MAX_MEM * sizeof(unsigned int)); for (i = 1 ; i < G2D_CMDFILE_MAX_NUM; i++) { gd->cmd_info[i].arg = gd->cmd_info[i - 1].arg + G2D_CMDFILE_MAX_MEM / G2D_CMDFILE_MAX_NUM; } #ifdef CONFIG_OF G2D_INFO("CONFIG_OF scope\n"); sdrv_init_iommu(gd); ret = sdrv_g2d_init(gd, dev->of_node); #else G2D_INFO("CONFIG_OF is closed\n"); ret = sdrv_g2d_init(gd, pdev); #endif if (ret) goto OUT; mutex_init(&gd->m_lock); gd->monitor.sampling_time = 5; ret = g2d_misc_init(gd);/*创建/dev/g2dX设备节点*/ if (ret) goto OUT; else printk("%s : semidrive g2d driver registered.\n", __func__); platform_set_drvdata(pdev, gd); g_g2d[gd->id] = gd; gd->du_inited = true; enable_irq(gd->irq);/*启用中断*/ ret = 0; OUT: mutex_unlock(&m_init); return ret; } static int sdrv_g2d_remove(struct platform_device *pdev) { struct sdrv_g2d *gd = platform_get_drvdata(pdev); G2D_DBG("remove g2d %s\n", gd->name); if (gd) { sdrv_iommu_cleanup(gd); sdrv_g2d_unit(gd); misc_deregister(&gd->mdev); } return 0; } #ifdef CONFIG_OF static const struct of_device_id g2d_of_table[] = { {.compatible = "semidrive,g2d", .data = g2d_data}, {.compatible = "semidrive,g2d_lite", .data = g2d_data}, {}, }; #endif static int sdrv_g2d_suspend(struct device *dev) { struct sdrv_g2d *gd = dev_get_drvdata(dev); G2D_INFO("%s start\n", __func__); gd->ops->reset(gd); G2D_INFO("gd->du_inited = %d, gd->num_pipe = %d\n", gd->du_inited, gd->num_pipe); G2D_INFO("%s end\n", __func__); return 0; } static int sdrv_g2d_resume(struct device *dev) { struct sdrv_g2d *gd = dev_get_drvdata(dev); struct g2d_pipe *p = NULL; int i; G2D_INFO("%s start\n", __func__); G2D_INFO("gd->du_inited = %d, gd->num_pipe = %d\n", gd->du_inited, gd->num_pipe); gd->ops->init(gd); for (i = 0; i < gd->num_pipe; i++) { p = gd->pipes[i]; if (p && p->ops->init) p->ops->init(p); else G2D_ERROR("p or p->ops->init is null\n"); } gd->ops->reset(gd); G2D_INFO("%s end\n", __func__); return 0; } static const struct dev_pm_ops sdrv_g2d_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(sdrv_g2d_suspend, sdrv_g2d_resume) }; static struct platform_driver g2d_driver = { .probe = sdrv_g2d_probe, .remove = sdrv_g2d_remove, .driver = { .name = "semidrive-g2d", .owner = THIS_MODULE, #ifdef CONFIG_OF .of_match_table = g2d_of_table, #endif .pm = &sdrv_g2d_pm_ops, }, }; module_platform_driver(g2d_driver); MODULE_AUTHOR("Semidrive Semiconductor"); MODULE_DESCRIPTION("Semidrive g2d"); MODULE_LICENSE("GPL"); 以上是芯驰SemDrive提供的Linux内核G2D驱动代码sdrv_g2d.c /* * SEMIDRIVE Copyright Statement * Copyright (c) SEMIDRIVE. All rights reserved * This software and all rights therein are owned by SEMIDRIVE, * and are protected by copyright law and other relevant laws, regulations and protection. * Without SEMIDRIVE’s prior written consent and /or related rights, * please do not use this software or any potion thereof in any form or by any means. * You may not reproduce, modify or distribute this software except in compliance with the License. * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * You should have received a copy of the License along with this program. * If not, see <http://www.semidrive.com/licenses/>. */ #ifndef __SDRV_G2D_H__ #define __SDRV_G2D_H__ #include <linux/platform_device.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #include <linux/list.h> #include <asm/io.h> #include <linux/iommu.h> #include <linux/wait.h> #include <uapi/drm/drm_fourcc.h> #include <uapi/drm/sdrv_g2d_cfg.h> #include "g2d_common.h" #define PR_INFO pr_info #define ERROR pr_err typedef unsigned long int addr_t; #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif extern int debug_g2d; #define G2D_INFO(fmt, args...) do {\ PR_INFO("[g2d] [%20s] " fmt, __func__, ##args);\ }while(0) #define G2D_DBG(fmt, args...) do {\ if (debug_g2d >= 1) {\ PR_INFO("[g2d] <%d> [%20s] " fmt, __LINE__, __func__, ##args);}\ }while(0) #define G2D_ERROR(fmt, args...) ERROR("[g2d] <%d> [%20s] Error: " fmt, __LINE__, __func__, ##args) #define DDBG(x) G2D_DBG(#x " -> %d\n", x) #define XDBG(x) G2D_DBG(#x " -> 0x%x\n", x) #define PDBG(x) G2D_DBG(#x " -> %p\n", x) #define ENTRY() G2D_DBG("call <%d>\n", __LINE__) #define GP_ECHO_NAME "g2d_gpipe_echo" #define GP_MID_NAME "g2d_gpipe_mid" #define GP_HIGH_NAME "g2d_gpipe_high" #define SPIPE_NAME "g2d_spipe" #define G2D_NR_DEVS 4 /*Kunlun DP layer format TILE vsize*/ enum { TILE_VSIZE_1 = 0b000, TILE_VSIZE_2 = 0b001, TILE_VSIZE_4 = 0b010, TILE_VSIZE_8 = 0b011, TILE_VSIZE_16 = 0b100, }; /*Kunlun DP layer format TILE hsize*/ enum { TILE_HSIZE_1 = 0b000, TILE_HSIZE_8 = 0b001, TILE_HSIZE_16 = 0b010, TILE_HSIZE_32 = 0b011, TILE_HSIZE_64 = 0b100, TILE_HSIZE_128 = 0b101, }; /**/ enum { FBDC_U8U8U8U8 = 0xc, FBDC_U16 = 0x9, FBDC_R5G6B5 = 0x5, FBDC_U8 = 0x0, FBDC_NV21 = 0x37, FBDC_YUV420_16PACK = 0x65 }; enum kunlun_plane_property { PLANE_PROP_ALPHA, PLANE_PROP_BLEND_MODE, PLANE_PROP_FBDC_HSIZE_Y, PLANE_PROP_FBDC_HSIZE_UV, PLANE_PROP_CAP_MASK, PLANE_PROP_MAX_NUM }; enum { DRM_MODE_BLEND_PIXEL_NONE = 0, DRM_MODE_BLEND_PREMULTI, DRM_MODE_BLEND_COVERAGE }; enum { PLANE_DISABLE, PLANE_ENABLE }; enum { PROP_PLANE_CAP_RGB = 0, PROP_PLANE_CAP_YUV, PROP_PLANE_CAP_XFBC, PROP_PLANE_CAP_YUV_FBC, PROP_PLANE_CAP_ROTATION, PROP_PLANE_CAP_SCALING, }; enum { TYPE_GP_ECHO = 0, TYPE_GP_MID, TYPE_GP_HIGH, TYPE_SPIPE }; struct g2d_pipe; struct pipe_operation { int (*init)(struct g2d_pipe *); int (*set)(struct g2d_pipe *, int , struct g2d_layer *); void (*csc_coef_set)(struct g2d_pipe *, struct g2d_coeff_table *); }; struct g2d_pipe { void __iomem *iomem_regs; void __iomem *regs; unsigned long reg_offset; int id; // the ordered id from 0 struct sdrv_g2d *gd; const char *name; int type; struct pipe_operation *ops; struct g2d_pipe_capability *cap; struct g2d_pipe *next; }; struct g2d_monitor { int is_monitor; int is_init; ktime_t timeout; struct hrtimer timer; bool g2d_on_task; int occupancy_rate; int timer_count; int valid_times; int sampling_time; }; struct sdrv_g2d { struct platform_device *pdev;/*关联的platform设备*/ struct cdev cdev; struct miscdevice mdev;/*misc字符设备(/dev/g2dx)*/ void __iomem *iomem_regs;/*G2D寄存器映射的虚拟地址*/ void __iomem *regs;/*G2D寄存器物理地址*/ bool iommu_enable;/*IOMMU使能状态*/ struct iommu_domain *domain;/*IOMMU域*/ struct mutex m_lock;/*操作互斥锁*/ struct wait_queue_head wq;/*等待队列(用于帧完成同步)*/ bool frame_done;/*帧处理完成标志*/ int id;/*设备ID*/ const char *name;/*设备名称*/ int irq;/*G2D中断号*/ int write_mode; cmdfile_info cmd_info[G2D_CMDFILE_MAX_NUM];/*命令缓冲区信息*/ unsigned long dma_buf;/*DMA缓冲区物理地址*/ const struct g2d_ops *ops;/*G2D硬件操作函数集*/ struct g2d_capability cap;/*G2D硬件能力描述*/ struct g2d_pipe *pipes[PIPE_MAX];/*图形处理管道数组*/ int num_pipe;/*启用的管道数量*/ int du_inited;/*设备初始化状态*/ struct g2d_monitor monitor;/*性能监控结构*/ }; struct g2d_ops { int (*init)(struct sdrv_g2d *); int (*enable)(struct sdrv_g2d*, int);/*使能/禁用硬件*/ int (*reset)(struct sdrv_g2d *);/*硬件复位*/ int (*mlc_set)(struct sdrv_g2d *, int , struct g2d_input *);/*多层合成配置*/ int (*fill_rect)(struct sdrv_g2d *, struct g2d_bg_cfg *, struct g2d_output_cfg *);/*矩形填充*/ int (*fastcopy)(struct sdrv_g2d *, addr_t , u32 , u32 , u32 , addr_t , u32);/*高速内存拷贝*/ int (*config)(struct sdrv_g2d *);/*硬件全局配置*/ int (*irq_handler)(struct sdrv_g2d *);/*中断处理*/ int (*rwdma)(struct sdrv_g2d *, struct g2d_input *);/*DMA读写控制*/ void (*close_fastcopy)(struct sdrv_g2d *);/*关闭快速拷贝*/ int (*wpipe_set)(struct sdrv_g2d *, int, struct g2d_output_cfg *);/*写管道配置*/ int (*check_stroke)(struct g2d_input *);/*描边参数校验*/ int (*scaler_coef_set)(struct sdrv_g2d *, struct g2d_coeff_table *);/*缩放系数设置*/ }; struct sdrv_g2d_data { const char *version; const struct g2d_ops* ops; }; struct ops_entry { const char *ver; void *ops; }; int g2d_get_capability(struct g2d_capability *cap); unsigned int get_compval_from_comp(struct pix_g2dcomp *comp); unsigned int get_frm_ctrl_from_comp(struct pix_g2dcomp *comp); int sdrv_wpipe_pix_comp(uint32_t format, struct pix_g2dcomp *comp); int sdrv_pix_comp(uint32_t format, struct pix_g2dcomp *comp); bool g2d_format_is_yuv(uint32_t format); int g2d_format_wpipe_bypass(uint32_t format); struct ops_list { struct list_head head; struct ops_entry *entry; }; extern struct list_head g2d_pipe_list_head; int g2d_ops_register(struct ops_entry *entry, struct list_head *head); void *g2d_ops_attach(const char *str, struct list_head *head); #define g2d_pipe_ops_register(entry) g2d_ops_register(entry, &g2d_pipe_list_head) #define g2d_pipe_ops_attach(str) g2d_ops_attach(str, &g2d_pipe_list_head) int g2d_choose_pipe(struct sdrv_g2d *gd, int hwid, int type, uint32_t offset); struct sdrv_g2d *get_g2d_by_id(int id); extern struct ops_entry gpipe_mid_g2d_entry; extern struct ops_entry gpipe_high_g2d_entry; extern struct ops_entry spipe_g2d_entry; #endif //__SDRV_G2D_H__ 以上是芯驰提供Linux内核G2D驱动源码对应的头文件sdrv_g2d.h #ifndef __SDRV_G2D_CFG_H #define __SDRV_G2D_CFG_H #include "sdrv_drm.h" #ifdef __YOCTO_G2D_TEST__ typedef __u8 uint8_t; typedef __u16 uint16_t; typedef __u32 uint32_t; typedef unsigned long uint64_t; #endif #define G2D_LAYER_MAX_NUM 6 #ifndef G2DLITE_API_USE typedef enum { SWAP_A_RGB = 0b0000, SWAP_A_RBG = 0b0001, SWAP_A_GBR = 0b0010, SWAP_A_GRB = 0b0011, SWAP_A_BGR = 0b0100, SWAP_A_BRG = 0b0101, SWAP_B_ARG = 0b1000, SWAP_B_AGR = 0b1001, SWAP_B_RGA = 0b1010, SWAP_B_RAG = 0b1011, SWAP_B_GRA = 0b1100, SWAP_B_GAR = 0b1101 } COMP_SWAP_MODE; typedef enum { UV_YUV444_RGB = 0b00, UV_YUV422 = 0b01, UV_YUV440 = 0b10, UV_YUV420 = 0b11 } DATA_UV_MODE; typedef enum { LINEAR_MODE = 0b000, RLE_COMPR_MODE = 0b001, GPU_RAW_TILE_MODE = 0b010, GPU_CPS_TILE_MODE = 0b011, VPU_RAW_TILE_MODE = 0b100, VPU_CPS_TILE_MODE = 0b101, VPU_RAW_TILE_988_MODE = 0b110, } DATA_MODE; typedef enum { FMT_INTERLEAVED = 0b00, FMT_MONOTONIC = 0b01, FMT_SEMI_PLANAR = 0b10, FMT_PLANAR = 0b11 } FRM_BUF_STR_FMT; typedef enum { ROT_DEFAULT = 0b000, ROT_ROT = 0b001, ROT_VFLIP = 0b010, ROT_HFLIP = 0b100 } ROT_TYPE; #endif #ifndef G2DLITE_API_USE enum { BLEND_PIXEL_NONE = 0, BLEND_PIXEL_PREMULTI, BLEND_PIXEL_COVERAGE }; typedef enum { ROTATION_TYPE_NONE = 0b000, ROTATION_TYPE_ROT_90 = 0b001, ROTATION_TYPE_HFLIP = 0b010, ROTATION_TYPE_VFLIP = 0b100, ROTATION_TYPE_ROT_180 = ROTATION_TYPE_VFLIP | ROTATION_TYPE_HFLIP, ROTATION_TYPE_ROT_270 = ROTATION_TYPE_ROT_90 | ROTATION_TYPE_VFLIP | ROTATION_TYPE_HFLIP, ROTATION_TYPE_VF_90 = ROTATION_TYPE_VFLIP | ROTATION_TYPE_ROT_90, ROTATION_TYPE_HF_90 = ROTATION_TYPE_HFLIP | ROTATION_TYPE_ROT_90, } rotation_type; #endif typedef enum { PD_NONE = 0, PD_SRC = 0x1, PD_DST = 0x2 } PD_LAYER_TYPE; struct g2d_output_cfg{ uint32_t width; uint32_t height; uint32_t fmt; uint64_t addr[4]; uint32_t stride[4]; uint32_t rotation; uint32_t nplanes; uint32_t offsets[4]; struct tile_ctx out_ctx; struct g2d_buf_info out_buf[4]; struct g2d_buf bufs[4]; }; struct g2d_bg_cfg { uint32_t en; uint32_t color; uint8_t g_alpha; uint8_t zorder; uint64_t aaddr; uint8_t bpa; uint32_t astride; uint32_t x; uint32_t y; uint32_t width; uint32_t height; PD_LAYER_TYPE pd_type; struct g2d_buf_info cfg_buf; struct g2d_buf abufs; }; struct g2d_coeff_table { int set_tables; int hcoef_set; int hcoef[33][5]; int vcoef_set; int vcoef[33][4]; int csc_coef_set; int csc_coef[15]; }; struct g2d_input{ unsigned char layer_num; struct g2d_bg_cfg bg_layer; struct g2d_layer layer[G2D_LAYER_MAX_NUM]; struct g2d_output_cfg output; struct g2d_coeff_table tables; }; struct g2d_pipe_capability { uint32_t formats[100]; int nformats; int layer_type; int rotation; int scaling; int yuv; int yuv_fbc; int xfbc; }; struct g2d_capability { int num_pipe; struct g2d_pipe_capability pipe_caps[G2D_LAYER_MAX_NUM]; }; struct g2d_layer_x { __u8 index; //plane index __u8 enable; __u8 nplanes; __u32 addr_l[4]; __u32 addr_h[4]; __u32 pitch[4]; __u32 offsets[4]; __s16 src_x; __s16 src_y; __s16 src_w; __s16 src_h; __s16 dst_x; __s16 dst_y; __u16 dst_w; __u16 dst_h; __u32 format; struct pix_g2dcomp comp; struct tile_ctx ctx; __u32 alpha; __u32 blend_mode; __u32 rotation; __u32 zpos; __u32 xfbc; __u64 modifier; __u32 width; __u32 height; struct g2d_buf_info in_buf[4]; }; struct g2d_output_cfg_x{ uint32_t width; uint32_t height; uint32_t fmt; uint64_t addr[4]; uint32_t stride[4]; uint32_t rotation; uint32_t nplanes; uint32_t offsets[4]; struct tile_ctx out_ctx; struct g2d_buf_info out_buf[4]; }; struct g2d_bg_cfg_x { uint32_t en; uint32_t color; uint8_t g_alpha; uint8_t zorder; uint64_t aaddr; uint8_t bpa; uint32_t astride; uint32_t x; uint32_t y; uint32_t width; uint32_t height; PD_LAYER_TYPE pd_type; struct g2d_buf_info cfg_buf; }; struct g2d_inputx{ unsigned char layer_num; struct g2d_bg_cfg_x bg_layer; struct g2d_layer_x layer[G2D_LAYER_MAX_NUM]; struct g2d_output_cfg_x output; struct g2d_coeff_table tables; }; #define G2D_COMMAND_BASE 0x00 #define G2D_IOCTL_BASE 'g' #define G2D_IO(nr) _IO(G2D_IOCTL_BASE,nr) #define G2D_IOR(nr,type) _IOR(G2D_IOCTL_BASE,nr,type) #define G2D_IOW(nr,type) _IOW(G2D_IOCTL_BASE,nr,type) #define G2D_IOWR(nr,type) _IOWR(G2D_IOCTL_BASE,nr,type) #define G2D_IOCTL_GET_CAPABILITIES G2D_IOWR(G2D_COMMAND_BASE + 1, struct g2d_capability) #define G2D_IOCTL_POST_CONFIG G2D_IOWR(G2D_COMMAND_BASE + 2, struct g2d_inputx) #define G2D_IOCTL_FAST_COPY G2D_IOWR(G2D_COMMAND_BASE + 3, struct g2d_inputx) #define G2D_IOCTL_FILL_RECT G2D_IOWR(G2D_COMMAND_BASE + 4, struct g2d_inputx) #endif //__SDRV_G2D_CFG_H 以上是芯驰提供的Linux应用层调用G2D的资源的头文件 请结合以上代码提供详细专业的代码注释。再结合LVGL 9.2.2源码实现Linux应用层调用/dev/g2d0设备并结合DRM接口实现图形化加速的绘制、填充、拷贝的项目可用源代码。
07-26
// 函数声明 void create_photo_album(const char*image_dir); void load_images_from_dir(const char *dir_path); void show_current_image(void); static void photo_album_event_cb(lv_event_t *e); static void handle_swipe(lv_coord_t end_x, lv_coord_t end_y); //static void event_handler(lv_obj_t *obj, lv_event_t event); //void create_photo_album(lv_obj_t *parent); int main(void) { lv_init(); /*Linux frame buffer device init*/ lv_display_t * disp = lv_linux_fbdev_create(); lv_linux_fbdev_set_file(disp, "/dev/fb0"); //添加触摸屏操作 lv_indev_t * indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event6"); //添加自己的代码 lv_obj_t *scr = lv_scr_act(); create_photo_album(scr); /*Handle LVGL tasks*/ while(1) { lv_timer_handler(); usleep(5000); } return 0; } // typedef struct ImageNode { char* path; // 图片路径 struct ImageNode* prev; // 前一张图片 struct ImageNode* next; // 下一张图片 } image_node_t; static image_node_t *image_list = NULL; // 图片链表 static image_node_t *current_image = NULL; // 当前显示的图片 static lv_obj_t *img_obj = NULL; // LVGL图片对象 //static lv_point_t start_x = 0; // 触摸开始X坐标 //static lv_point_t start_y = 0; // 触摸开始Y坐标 static lv_point_t start_point = {0, 0}; static lv_point_t end_point = {0, 0}; void create_photo_album(const char*image_dir) { load_images_from_dir(image_dir); if (image_list == NULL) { printf("No images found!\n"); return; } // 创建图片显示对象 img_obj = lv_img_create(lv_screen_active()); lv_obj_set_size(img_obj, 1024, 600); lv_obj_align(img_obj, LV_ALIGN_CENTER, 0, 0); // 设置当前图片为链表第一个 current_image = image_list; show_current_image(); // 添加触摸事件监听 lv_obj_add_event_cb(img_obj, photo_album_event_cb, LV_EVENT_ALL, NULL); } // 从目录加载BMP图片并创建链表 void load_images_from_dir(const char *dir_path) { DIR *dir; struct dirent *ent; if ((dir = opendir(dir_path)) != NULL) { while ((ent = readdir(dir)) != NULL) { // 检查文件扩展名是否为.bmp char *ext = strrchr(ent->d_name, '.'); if (ext && strcasecmp(ext, ".bmp") == 0) { // 创建新节点 image_node_t *new_node = malloc(sizeof(image_node_t)); new_node->path = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); sprintf(new_node->path, "%s/%s", dir_path, ent->d_name); // 添加到链表 if (image_list == NULL) { // 第一个节点 new_node->prev = new_node; new_node->next = new_node; image_list = new_node; } else { // 添加到链表末尾 new_node->prev = image_list->prev; new_node->next = image_list; image_list->prev->next = new_node; image_list->prev = new_node; } } } closedir(dir); } } // 显示当前图片 void show_current_image(void) { if (current_image && img_obj) { lv_img_set_src(img_obj, current_image->path); } } // 处理滑动事件 static void handle_swipe(lv_coord_t end_x, lv_coord_t end_y) { const lv_coord_t min_swipe_distance = 50; // 最小滑动距离 lv_coord_t delta_x = end_x - start_point.x; lv_coord_t delta_y = end_y - start_point.y; // 只处理水平滑动 if (abs(delta_x) > abs(delta_y) && abs(delta_x) > min_swipe_distance) { if (delta_x > 0) { // 向右滑动 - 上一张图片 if (current_image) { current_image = current_image->prev; show_current_image(); } } else { // 向左滑动 - 下一张图片 if (current_image) { current_image = current_image->next; show_current_image(); } } } } // 事件回调函数 static void photo_album_event_cb(lv_event_t *e) { lv_event_code_t code = lv_event_get_code(e); lv_indev_t *indev = lv_indev_get_act(); if (code == LV_EVENT_PRESSED) { // 记录触摸开始位置 lv_indev_get_point(indev, &start_point); } else if (code == LV_EVENT_RELEASED) { // 获取触摸结束位置 //lv_point_t end_x, end_y; lv_indev_get_point(indev, &end_point); // 处理滑动 handle_swipe(end_point.x, end_point.y); } }怎么修改才能在gec6818开发板上显示图片
08-06
wjs@wjs-desktop:~/Drone_Slam$ ros2 launch fishbot_grapher test_grapher_3.launch.py [INFO] [launch]: All log files can be found below /home/wjs/.ros/log/2025-07-27-21-35-15-661200-wjs-desktop-3163 [INFO] [launch]: Default logging verbosity is set to INFO pkg_share =/home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher<== model_path =/home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher/urdf/fishbot_base.urdf<== [INFO] [sllidar_node-1]: process started with pid [3164] [INFO] [wit_ros2_imu-2]: process started with pid [3166] [INFO] [test01-3]: process started with pid [3168] [INFO] [robot_state_publisher-4]: process started with pid [3170] [INFO] [cartographer_node-5]: process started with pid [3172] [INFO] [cartographer_occupancy_grid_node-6]: process started with pid [3175] [robot_state_publisher-4] [WARN] [1753623316.127651744] [robot_state_publisher]: No robot_description parameter, but command-line argument available. Assuming argument is name of URDF file. This backwards compatibility fallback will be removed in the future. [sllidar_node-1] [INFO] [1753623316.183488839] [sllidar_node]: SLLidar running on ROS2 package SLLidar.ROS2 SDK Version:1.0.1, SLLIDAR SDK Version:2.0.0 [robot_state_publisher-4] [INFO] [1753623316.214213434] [robot_state_publisher]: got segment base_link [robot_state_publisher-4] [INFO] [1753623316.214390052] [robot_state_publisher]: got segment imu_link [robot_state_publisher-4] [INFO] [1753623316.214425176] [robot_state_publisher]: got segment laser_link [sllidar_node-1] [ERROR] [1753623316.229875375] [sllidar_node]: Error, operation time out. SL_RESULT_OPERATION_TIMEOUT! [cartographer_node-5] [INFO] [1753623316.305550876] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher/config/test02.lua' for 'test02.lua'. [cartographer_node-5] [INFO] [1753623316.309873261] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/map_builder.lua' for 'map_builder.lua'. [cartographer_node-5] [INFO] [1753623316.311397967] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/map_builder.lua' for 'map_builder.lua'. [cartographer_node-5] [INFO] [1753623316.311938913] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/pose_graph.lua' for 'pose_graph.lua'. [cartographer_node-5] [INFO] [1753623316.312307185] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/pose_graph.lua' for 'pose_graph.lua'. [cartographer_node-5] [INFO] [1753623316.315840313] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder.lua' for 'trajectory_builder.lua'. [cartographer_node-5] [INFO] [1753623316.317244318] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder.lua' for 'trajectory_builder.lua'. [cartographer_node-5] [INFO] [1753623316.317971325] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_2d.lua' for 'trajectory_builder_2d.lua'. [cartographer_node-5] [INFO] [1753623316.318359630] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_2d.lua' for 'trajectory_builder_2d.lua'. [cartographer_node-5] [INFO] [1753623316.319137685] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_3d.lua' for 'trajectory_builder_3d.lua'. [cartographer_node-5] [INFO] [1753623316.319567575] [cartographer logger]: I0727 21:35:16.000000 3172 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_3d.lua' for 'trajectory_builder_3d.lua'. [cartographer_node-5] F0727 21:35:16.322907 3172 lua_parameter_dictionary.cc:399] Check failed: HasKey(key) Key 'collate_landmarks' not in dictionary: [cartographer_node-5] { [cartographer_node-5] collate_fixed_frame = true, [cartographer_node-5] trajectory_builder_2d = { [cartographer_node-5] adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.500000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 20.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight = 1.000000, [cartographer_node-5] rotation_weight = 40.000000, [cartographer_node-5] translation_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] loop_closure_adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.900000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 100.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 8.000000, [cartographer_node-5] max_z = 2.000000, [cartographer_node-5] min_range = 0.300000, [cartographer_node-5] min_z = -0.800000, [cartographer_node-5] missing_data_ray_length = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.017453, [cartographer_node-5] max_distance_meters = 0.200000, [cartographer_node-5] max_time_seconds = 5.000000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.349066, [cartographer_node-5] linear_search_window = 0.100000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] submaps = { [cartographer_node-5] grid_options_2d = { [cartographer_node-5] grid_type = "PROBABILITY_GRID", [cartographer_node-5] resolution = 0.050000, [cartographer_node-5] }, [cartographer_node-5] num_range_data = 35.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] probability_grid_range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] insert_free_space = true, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] }, [cartographer_node-5] range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D", [cartographer_node-5] tsdf_range_data_inserter = { [cartographer_node-5] maximum_weight = 10.000000, [cartographer_node-5] normal_estimation_options = { [cartographer_node-5] num_normal_samples = 4.000000, [cartographer_node-5] sample_radius = 0.500000, [cartographer_node-5] }, [cartographer_node-5] project_sdf_distance_to_scan_normal = true, [cartographer_node-5] truncation_distance = 0.300000, [cartographer_node-5] update_free_space = false, [cartographer_node-5] update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_distance_cell_to_hit_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_range_exponent = 0.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_data = true, [cartographer_node-5] use_online_correlative_scan_matching = true, [cartographer_node-5] voxel_filter_size = 0.025000, [cartographer_node-5] }, [cartographer_node-5] trajectory_builder_3d = { [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 12.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] intensity_cost_function_options_0 = { [cartographer_node-5] huber_scale = 0.300000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] weight = 0.500000, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight_0 = 1.000000, [cartographer_node-5] occupied_space_weight_1 = 6.000000, [cartographer_node-5] only_optimize_yaw = false, [cartographer_node-5] rotation_weight = 400.000000, [cartographer_node-5] translation_weight = 5.000000, [cartographer_node-5] }, [cartographer_node-5] high_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 2.000000, [cartographer_node-5] max_range = 15.000000, [cartographer_node-5] min_num_points = 150.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] low_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 4.000000, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_range = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.004000, [cartographer_node-5] max_distance_meters = 0.100000, [cartographer_node-5] max_time_seconds = 0.500000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.017453, [cartographer_node-5] linear_search_window = 0.150000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 0.100000, [cartographer_node-5] }, [cartographer_node-5] rotational_histogram_size = 120.000000, [cartographer_node-5] submaps = { [cartographer_node-5] high_resolution = 0.100000, [cartographer_node-5] high_resolution_max_range = 20.000000, [cartographer_node-5] low_resolution = 0.450000, [cartographer_node-5] num_range_data = 160.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] num_free_space_voxels = 2.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_intensities = false, [cartographer_node-5] use_online_correlative_scan_matching = false, [cartographer_node-5] voxel_filter_size = 0.150000, [cartographer_node-5] }, [cartographer_node-5] } [cartographer_node-5] [FATAL] [1753623316.327824354] [cartographer logger]: F0727 21:35:16.000000 3172 lua_parameter_dictionary.cc:399] Check failed: HasKey(key) Key 'collate_landmarks' not in dictionary: [cartographer_node-5] { [cartographer_node-5] collate_fixed_frame = true, [cartographer_node-5] trajectory_builder_2d = { [cartographer_node-5] adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.500000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 20.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight = 1.000000, [cartographer_node-5] rotation_weight = 40.000000, [cartographer_node-5] translation_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] loop_closure_adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.900000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 100.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 8.000000, [cartographer_node-5] max_z = 2.000000, [cartographer_node-5] min_range = 0.300000, [cartographer_node-5] min_z = -0.800000, [cartographer_node-5] missing_data_ray_length = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.017453, [cartographer_node-5] max_distance_meters = 0.200000, [cartographer_node-5] max_time_seconds = 5.000000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.349066, [cartographer_node-5] linear_search_window = 0.100000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] submaps = { [cartographer_node-5] grid_options_2d = { [cartographer_node-5] grid_type = "PROBABILITY_GRID", [cartographer_node-5] resolution = 0.050000, [cartographer_node-5] }, [cartographer_node-5] num_range_data = 35.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] probability_grid_range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] insert_free_space = true, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] }, [cartographer_node-5] range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D", [cartographer_node-5] tsdf_range_data_inserter = { [cartographer_node-5] maximum_weight = 10.000000, [cartographer_node-5] normal_estimation_options = { [cartographer_node-5] num_normal_samples = 4.000000, [cartographer_node-5] sample_radius = 0.500000, [cartographer_node-5] }, [cartographer_node-5] project_sdf_distance_to_scan_normal = true, [cartographer_node-5] truncation_distance = 0.300000, [cartographer_node-5] update_free_space = false, [cartographer_node-5] update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_distance_cell_to_hit_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_range_exponent = 0.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_data = true, [cartographer_node-5] use_online_correlative_scan_matching = true, [cartographer_node-5] voxel_filter_size = 0.025000, [cartographer_node-5] }, [cartographer_node-5] trajectory_builder_3d = { [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 12.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] intensity_cost_function_options_0 = { [cartographer_node-5] huber_scale = 0.300000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] weight = 0.500000, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight_0 = 1.000000, [cartographer_node-5] occupied_space_weight_1 = 6.000000, [cartographer_node-5] only_optimize_yaw = false, [cartographer_node-5] rotation_weight = 400.000000, [cartographer_node-5] translation_weight = 5.000000, [cartographer_node-5] }, [cartographer_node-5] high_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 2.000000, [cartographer_node-5] max_range = 15.000000, [cartographer_node-5] min_num_points = 150.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] low_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 4.000000, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_range = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.004000, [cartographer_node-5] max_distance_meters = 0.100000, [cartographer_node-5] max_time_seconds = 0.500000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.017453, [cartographer_node-5] linear_search_window = 0.150000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 0.100000, [cartographer_node-5] }, [cartographer_node-5] rotational_histogram_size = 120.000000, [cartographer_node-5] submaps = { [cartographer_node-5] high_resolution = 0.100000, [cartographer_node-5] high_resolution_max_range = 20.000000, [cartographer_node-5] low_resolution = 0.450000, [cartographer_node-5] num_range_data = 160.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] num_free_space_voxels = 2.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_intensities = false, [cartographer_node-5] use_online_correlative_scan_matching = false, [cartographer_node-5] voxel_filter_size = 0.150000, [cartographer_node-5] }, [cartographer_node-5] } [ERROR] [sllidar_node-1]: process has died [pid 3164, exit code 255, cmd '/home/wjs/Drone_Slam/install/sllidar_ros2/lib/sllidar_ros2/sllidar_node --ros-args -r __node:=sllidar_node --params-file /tmp/launch_params_zfxrdf7h']. [cartographer_node-5] *** Check failure stack trace: *** [cartographer_node-5] @ 0xffffa6fad41c google::LogMessage::Fail() [cartographer_node-5] @ 0xffffa6fb46d0 google::LogMessage::SendToLog() [cartographer_node-5] @ 0xffffa6fad0f4 google::LogMessage::Flush() [cartographer_node-5] @ 0xffffa6faeebc google::LogMessageFatal::~LogMessageFatal() [cartographer_node-5] @ 0xaaaabf79392c (unknown) [cartographer_node-5] @ 0xaaaabf79398c (unknown) [cartographer_node-5] @ 0xaaaabf793dc8 (unknown) [cartographer_node-5] @ 0xaaaabf7b10a8 (unknown) [cartographer_node-5] @ 0xaaaabf77aeec (unknown) [cartographer_node-5] @ 0xaaaabf6d743c (unknown) [cartographer_node-5] @ 0xffffa65973fc (unknown) [cartographer_node-5] @ 0xffffa65974cc __libc_start_main [cartographer_node-5] @ 0xaaaabf6dabf0 (unknown) [test01-3] Traceback (most recent call last): [test01-3] File "/home/wjs/.local/lib/python3.10/site-packages/serial/serialposix.py", line 322, in open [test01-3] self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) [test01-3] FileNotFoundError: [Errno 2] No such file or directory: '/dev/mcu_usb' [test01-3] [test01-3] During handling of the above exception, another exception occurred: [test01-3] [test01-3] Traceback (most recent call last): [test01-3] File "/home/wjs/Drone_Slam/install/fishbot_grapher/lib/fishbot_grapher/test01", line 33, in <module> [test01-3] sys.exit(load_entry_point('fishbot-grapher==0.0.0', 'console_scripts', 'test01')()) [test01-3] File "/home/wjs/Drone_Slam/build/fishbot_grapher/fishbot_grapher/test01.py", line 101, in main [test01-3] tf_subscriber = TFSubscriber() [test01-3] File "/home/wjs/Drone_Slam/build/fishbot_grapher/fishbot_grapher/test01.py", line 20, in __init__ [test01-3] self.ser = serial.Serial("/dev/mcu_usb", 115200) [test01-3] File "/home/wjs/.local/lib/python3.10/site-packages/serial/serialutil.py", line 244, in __init__ [test01-3] self.open() [test01-3] File "/home/wjs/.local/lib/python3.10/site-packages/serial/serialposix.py", line 325, in open [test01-3] raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg)) [test01-3] serial.serialutil.SerialException: [Errno 2] could not open port /dev/mcu_usb: [Errno 2] No such file or directory: '/dev/mcu_usb' [wit_ros2_imu-2] [INFO] [1753623318.137865708] [imu]: Serial port opening failure [ERROR] [test01-3]: process has died [pid 3168, exit code 1, cmd '/home/wjs/Drone_Slam/install/fishbot_grapher/lib/fishbot_grapher/test01 --ros-args']. [ERROR] [cartographer_node-5]: process has died [pid 3172, exit code -6, cmd '/opt/ros/humble/lib/cartographer_ros/cartographer_node -configuration_directory /home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher/config -configuration_basename test02.lua --ros-args -r __node:=cartographer_node --params-file /tmp/launch_params_tgg9k32e'].
07-28
wjs@wjs-desktop:~/Drone_Slam$ ros2 launch fishbot_grapher test_grapher_3.launch.py [INFO] [launch]: All log files can be found below /home/wjs/.ros/log/2025-07-27-21-44-14-611581-wjs-desktop-3511 [INFO] [launch]: Default logging verbosity is set to INFO pkg_share =/home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher<== model_path =/home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher/urdf/fishbot_base.urdf<== [INFO] [sllidar_node-1]: process started with pid [3512] [INFO] [wit_ros2_imu-2]: process started with pid [3514] [INFO] [test01-3]: process started with pid [3516] [INFO] [robot_state_publisher-4]: process started with pid [3518] [INFO] [cartographer_node-5]: process started with pid [3520] [INFO] [cartographer_occupancy_grid_node-6]: process started with pid [3528] [sllidar_node-1] [INFO] [1753623855.053473670] [sllidar_node]: SLLidar running on ROS2 package SLLidar.ROS2 SDK Version:1.0.1, SLLIDAR SDK Version:2.0.0 [robot_state_publisher-4] [WARN] [1753623855.060580496] [robot_state_publisher]: No robot_description parameter, but command-line argument available. Assuming argument is name of URDF file. This backwards compatibility fallback will be removed in the future. [robot_state_publisher-4] [INFO] [1753623855.094832372] [robot_state_publisher]: got segment base_link [robot_state_publisher-4] [INFO] [1753623855.095034876] [robot_state_publisher]: got segment imu_link [robot_state_publisher-4] [INFO] [1753623855.095085164] [robot_state_publisher]: got segment laser_link [sllidar_node-1] [INFO] [1753623855.109755054] [sllidar_node]: SLLidar S/N: 7885EC95C1EA9ED1B2E49CF4FB594571 [sllidar_node-1] [INFO] [1753623855.109953948] [sllidar_node]: Firmware Ver: 1.01 [sllidar_node-1] [INFO] [1753623855.110013734] [sllidar_node]: Hardware Rev: 18 [sllidar_node-1] [INFO] [1753623855.161457399] [sllidar_node]: SLLidar health status : 0 [sllidar_node-1] [INFO] [1753623855.161700711] [sllidar_node]: SLLidar health status : OK. [cartographer_node-5] [INFO] [1753623855.329700319] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher/config/test02.lua' for 'test02.lua'. [cartographer_node-5] [INFO] [1753623855.331169076] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/map_builder.lua' for 'map_builder.lua'. [cartographer_node-5] [INFO] [1753623855.331564029] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/map_builder.lua' for 'map_builder.lua'. [cartographer_node-5] [INFO] [1753623855.334823472] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/pose_graph.lua' for 'pose_graph.lua'. [cartographer_node-5] [INFO] [1753623855.335258474] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/pose_graph.lua' for 'pose_graph.lua'. [cartographer_node-5] [INFO] [1753623855.336206744] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder.lua' for 'trajectory_builder.lua'. [cartographer_node-5] [INFO] [1753623855.336478199] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder.lua' for 'trajectory_builder.lua'. [cartographer_node-5] [INFO] [1753623855.336887520] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_2d.lua' for 'trajectory_builder_2d.lua'. [cartographer_node-5] [INFO] [1753623855.337144200] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_2d.lua' for 'trajectory_builder_2d.lua'. [cartographer_node-5] [INFO] [1753623855.338000725] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_3d.lua' for 'trajectory_builder_3d.lua'. [cartographer_node-5] [INFO] [1753623855.338301971] [cartographer logger]: I0727 21:44:15.000000 3520 configuration_file_resolver.cc:41] Found '/opt/ros/humble/share/cartographer/configuration_files/trajectory_builder_3d.lua' for 'trajectory_builder_3d.lua'. [cartographer_node-5] F0727 21:44:15.343778 3520 lua_parameter_dictionary.cc:399] Check failed: HasKey(key) Key 'collate_landmarks' not in dictionary: [cartographer_node-5] { [cartographer_node-5] collate_fixed_frame = true, [cartographer_node-5] trajectory_builder_2d = { [cartographer_node-5] adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.500000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 20.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight = 1.000000, [cartographer_node-5] rotation_weight = 40.000000, [cartographer_node-5] translation_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] loop_closure_adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.900000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 100.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 8.000000, [cartographer_node-5] max_z = 2.000000, [cartographer_node-5] min_range = 0.300000, [cartographer_node-5] min_z = -0.800000, [cartographer_node-5] missing_data_ray_length = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.017453, [cartographer_node-5] max_distance_meters = 0.200000, [cartographer_node-5] max_time_seconds = 5.000000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.349066, [cartographer_node-5] linear_search_window = 0.100000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] submaps = { [cartographer_node-5] grid_options_2d = { [cartographer_node-5] grid_type = "PROBABILITY_GRID", [cartographer_node-5] resolution = 0.050000, [cartographer_node-5] }, [cartographer_node-5] num_range_data = 35.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] probability_grid_range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] insert_free_space = true, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] }, [cartographer_node-5] range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D", [cartographer_node-5] tsdf_range_data_inserter = { [cartographer_node-5] maximum_weight = 10.000000, [cartographer_node-5] normal_estimation_options = { [cartographer_node-5] num_normal_samples = 4.000000, [cartographer_node-5] sample_radius = 0.500000, [cartographer_node-5] }, [cartographer_node-5] project_sdf_distance_to_scan_normal = true, [cartographer_node-5] truncation_distance = 0.300000, [cartographer_node-5] update_free_space = false, [cartographer_node-5] update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_distance_cell_to_hit_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_range_exponent = 0.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_data = true, [cartographer_node-5] use_online_correlative_scan_matching = true, [cartographer_node-5] voxel_filter_size = 0.025000, [cartographer_node-5] }, [cartographer_node-5] trajectory_builder_3d = { [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 12.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] intensity_cost_function_options_0 = { [cartographer_node-5] huber_scale = 0.300000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] weight = 0.500000, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight_0 = 1.000000, [cartographer_node-5] occupied_space_weight_1 = 6.000000, [cartographer_node-5] only_optimize_yaw = false, [cartographer_node-5] rotation_weight = 400.000000, [cartographer_node-5] translation_weight = 5.000000, [cartographer_node-5] }, [cartographer_node-5] high_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 2.000000, [cartographer_node-5] max_range = 15.000000, [cartographer_node-5] min_num_points = 150.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] low_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 4.000000, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_range = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.004000, [cartographer_node-5] max_distance_meters = 0.100000, [cartographer_node-5] max_time_seconds = 0.500000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.017453, [cartographer_node-5] linear_search_window = 0.150000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 0.100000, [cartographer_node-5] }, [cartographer_node-5] rotational_histogram_size = 120.000000, [cartographer_node-5] submaps = { [cartographer_node-5] high_resolution = 0.100000, [cartographer_node-5] high_resolution_max_range = 20.000000, [cartographer_node-5] low_resolution = 0.450000, [cartographer_node-5] num_range_data = 160.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] num_free_space_voxels = 2.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_intensities = false, [cartographer_node-5] use_online_correlative_scan_matching = false, [cartographer_node-5] voxel_filter_size = 0.150000, [cartographer_node-5] }, [cartographer_node-5] } [cartographer_node-5] [FATAL] [1753623855.349454665] [cartographer logger]: F0727 21:44:15.000000 3520 lua_parameter_dictionary.cc:399] Check failed: HasKey(key) Key 'collate_landmarks' not in dictionary: [cartographer_node-5] { [cartographer_node-5] collate_fixed_frame = true, [cartographer_node-5] trajectory_builder_2d = { [cartographer_node-5] adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.500000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 20.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight = 1.000000, [cartographer_node-5] rotation_weight = 40.000000, [cartographer_node-5] translation_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] loop_closure_adaptive_voxel_filter = { [cartographer_node-5] max_length = 0.900000, [cartographer_node-5] max_range = 50.000000, [cartographer_node-5] min_num_points = 100.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 8.000000, [cartographer_node-5] max_z = 2.000000, [cartographer_node-5] min_range = 0.300000, [cartographer_node-5] min_z = -0.800000, [cartographer_node-5] missing_data_ray_length = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.017453, [cartographer_node-5] max_distance_meters = 0.200000, [cartographer_node-5] max_time_seconds = 5.000000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.349066, [cartographer_node-5] linear_search_window = 0.100000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 10.000000, [cartographer_node-5] }, [cartographer_node-5] submaps = { [cartographer_node-5] grid_options_2d = { [cartographer_node-5] grid_type = "PROBABILITY_GRID", [cartographer_node-5] resolution = 0.050000, [cartographer_node-5] }, [cartographer_node-5] num_range_data = 35.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] probability_grid_range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] insert_free_space = true, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] }, [cartographer_node-5] range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D", [cartographer_node-5] tsdf_range_data_inserter = { [cartographer_node-5] maximum_weight = 10.000000, [cartographer_node-5] normal_estimation_options = { [cartographer_node-5] num_normal_samples = 4.000000, [cartographer_node-5] sample_radius = 0.500000, [cartographer_node-5] }, [cartographer_node-5] project_sdf_distance_to_scan_normal = true, [cartographer_node-5] truncation_distance = 0.300000, [cartographer_node-5] update_free_space = false, [cartographer_node-5] update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_distance_cell_to_hit_kernel_bandwidth = 0.500000, [cartographer_node-5] update_weight_range_exponent = 0.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_data = true, [cartographer_node-5] use_online_correlative_scan_matching = true, [cartographer_node-5] voxel_filter_size = 0.025000, [cartographer_node-5] }, [cartographer_node-5] trajectory_builder_3d = { [cartographer_node-5] ceres_scan_matcher = { [cartographer_node-5] ceres_solver_options = { [cartographer_node-5] max_num_iterations = 12.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] intensity_cost_function_options_0 = { [cartographer_node-5] huber_scale = 0.300000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] weight = 0.500000, [cartographer_node-5] }, [cartographer_node-5] occupied_space_weight_0 = 1.000000, [cartographer_node-5] occupied_space_weight_1 = 6.000000, [cartographer_node-5] only_optimize_yaw = false, [cartographer_node-5] rotation_weight = 400.000000, [cartographer_node-5] translation_weight = 5.000000, [cartographer_node-5] }, [cartographer_node-5] high_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 2.000000, [cartographer_node-5] max_range = 15.000000, [cartographer_node-5] min_num_points = 150.000000, [cartographer_node-5] }, [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] low_resolution_adaptive_voxel_filter = { [cartographer_node-5] max_length = 4.000000, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_num_points = 200.000000, [cartographer_node-5] }, [cartographer_node-5] max_range = 60.000000, [cartographer_node-5] min_range = 1.000000, [cartographer_node-5] motion_filter = { [cartographer_node-5] max_angle_radians = 0.004000, [cartographer_node-5] max_distance_meters = 0.100000, [cartographer_node-5] max_time_seconds = 0.500000, [cartographer_node-5] }, [cartographer_node-5] num_accumulated_range_data = 1.000000, [cartographer_node-5] pose_extrapolator = { [cartographer_node-5] constant_velocity = { [cartographer_node-5] imu_gravity_time_constant = 10.000000, [cartographer_node-5] pose_queue_duration = 0.001000, [cartographer_node-5] }, [cartographer_node-5] imu_based = { [cartographer_node-5] gravity_constant = 9.806000, [cartographer_node-5] imu_acceleration_weight = 1.000000, [cartographer_node-5] imu_rotation_weight = 1.000000, [cartographer_node-5] odometry_rotation_weight = 1.000000, [cartographer_node-5] odometry_translation_weight = 1.000000, [cartographer_node-5] pose_queue_duration = 5.000000, [cartographer_node-5] pose_rotation_weight = 1.000000, [cartographer_node-5] pose_translation_weight = 1.000000, [cartographer_node-5] solver_options = { [cartographer_node-5] max_num_iterations = 10.000000, [cartographer_node-5] num_threads = 1.000000, [cartographer_node-5] use_nonmonotonic_steps = false, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_imu_based = false, [cartographer_node-5] }, [cartographer_node-5] real_time_correlative_scan_matcher = { [cartographer_node-5] angular_search_window = 0.017453, [cartographer_node-5] linear_search_window = 0.150000, [cartographer_node-5] rotation_delta_cost_weight = 0.100000, [cartographer_node-5] translation_delta_cost_weight = 0.100000, [cartographer_node-5] }, [cartographer_node-5] rotational_histogram_size = 120.000000, [cartographer_node-5] submaps = { [cartographer_node-5] high_resolution = 0.100000, [cartographer_node-5] high_resolution_max_range = 20.000000, [cartographer_node-5] low_resolution = 0.450000, [cartographer_node-5] num_range_data = 160.000000, [cartographer_node-5] range_data_inserter = { [cartographer_node-5] hit_probability = 0.550000, [cartographer_node-5] intensity_threshold = 40.000000, [cartographer_node-5] miss_probability = 0.490000, [cartographer_node-5] num_free_space_voxels = 2.000000, [cartographer_node-5] }, [cartographer_node-5] }, [cartographer_node-5] use_intensities = false, [cartographer_node-5] use_online_correlative_scan_matching = false, [cartographer_node-5] voxel_filter_size = 0.150000, [cartographer_node-5] }, [cartographer_node-5] } [sllidar_node-1] [INFO] [1753623855.378131908] [sllidar_node]: current scan mode: DenseBoost, sample rate: 32 Khz, max_distance: 18.0 m, scan frequency:10.0 Hz, [cartographer_node-5] *** Check failure stack trace: *** [cartographer_node-5] @ 0xffff8223d41c google::LogMessage::Fail() [cartographer_node-5] @ 0xffff822446d0 google::LogMessage::SendToLog() [cartographer_node-5] @ 0xffff8223d0f4 google::LogMessage::Flush() [cartographer_node-5] @ 0xffff8223eebc google::LogMessageFatal::~LogMessageFatal() [cartographer_node-5] @ 0xaaaad44c392c (unknown) [cartographer_node-5] @ 0xaaaad44c398c (unknown) [cartographer_node-5] @ 0xaaaad44c3dc8 (unknown) [cartographer_node-5] @ 0xaaaad44e10a8 (unknown) [cartographer_node-5] @ 0xaaaad44aaeec (unknown) [cartographer_node-5] @ 0xaaaad440743c (unknown) [cartographer_node-5] @ 0xffff818273fc (unknown) [cartographer_node-5] @ 0xffff818274cc __libc_start_main [cartographer_node-5] @ 0xaaaad440abf0 (unknown) [test01-3] Traceback (most recent call last): [test01-3] File "/home/wjs/.local/lib/python3.10/site-packages/serial/serialposix.py", line 322, in open [test01-3] self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) [test01-3] FileNotFoundError: [Errno 2] No such file or directory: '/dev/mcu_usb' [test01-3] [test01-3] During handling of the above exception, another exception occurred: [test01-3] [test01-3] Traceback (most recent call last): [test01-3] File "/home/wjs/Drone_Slam/install/fishbot_grapher/lib/fishbot_grapher/test01", line 33, in <module> [test01-3] sys.exit(load_entry_point('fishbot-grapher==0.0.0', 'console_scripts', 'test01')()) [test01-3] File "/home/wjs/Drone_Slam/build/fishbot_grapher/fishbot_grapher/test01.py", line 101, in main [test01-3] tf_subscriber = TFSubscriber() [test01-3] File "/home/wjs/Drone_Slam/build/fishbot_grapher/fishbot_grapher/test01.py", line 20, in __init__ [test01-3] self.ser = serial.Serial("/dev/mcu_usb", 115200) [test01-3] File "/home/wjs/.local/lib/python3.10/site-packages/serial/serialutil.py", line 244, in __init__ [test01-3] self.open() [test01-3] File "/home/wjs/.local/lib/python3.10/site-packages/serial/serialposix.py", line 325, in open [test01-3] raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg)) [test01-3] serial.serialutil.SerialException: [Errno 2] could not open port /dev/mcu_usb: [Errno 2] No such file or directory: '/dev/mcu_usb' [wit_ros2_imu-2] [INFO] [1753623857.378557163] [imu]: Serial port opening failure [ERROR] [test01-3]: process has died [pid 3516, exit code 1, cmd '/home/wjs/Drone_Slam/install/fishbot_grapher/lib/fishbot_grapher/test01 --ros-args']. [ERROR] [cartographer_node-5]: process has died [pid 3520, exit code -6, cmd '/opt/ros/humble/lib/cartographer_ros/cartographer_node -configuration_directory /home/wjs/Drone_Slam/install/fishbot_grapher/share/fishbot_grapher/config -configuration_basename test02.lua --ros-args -r __node:=cartographer_node --params-file /tmp/launch_params_i_dk6w5r'].
07-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值