FPGA SATA IP控制器的SATA接口调试记录

news2025/7/19 16:53:30

本文档是基于FPGA K7 SATA IP控制器的SATA接口调试记录,接口遵循标准的ACHI协议。

操作系统内核版本:5.4.18

由于K7PCIE只有3个bar,AHCI协议规定SATA控制器是在第四个BAR上,另外由于PCIE配置空间设备类寄存器和能力寄存器未配置成sata设备,导致系统自带的驱动不能没生效。因此需要修改系统sata驱动并重新编译安装。

Sata驱动在内核目录/drivers/ata/下,对于ahci sata对于的驱动文件是ahci.c,单独编译ahci文件需要对该目录下的Makefile文件进行如下修改:

SPDX-License-Identifier: GPL-2.0

#将ahci.c文件编译成模块

CONFIG_SATA_AHCI := m

#CONFIG_PATA_PLATFORM := m

#CONFIG_PATA_OF_PLATFORM := m

#CONFIG_SATA_SIL24 := m

KERNEL_VERSION := $(shell uname -r)

KERNELDIR = /lib/modules/$(KERNEL_VERSION)/build

#INSTDIR = /lib/modules/$(KERNEL_VERSION)/kernel/drivers/ata

KERNEL := kernel-$(KERNEL_VERSION)

PWD := $(shell pwd)

EXTRA_CFLAGS += -DATA_DEBUG

#obj-$(CONFIG_ATA)                 += libata.o

# non-SFF interface

#obj-$(CONFIG_SATA_AHCI)             += ahci.o libahci.o

#编译生成的模块名称为ahci_test.ko

obj-$(CONFIG_SATA_AHCI)               := ahci_test.o

#模块有ahci.c文件编译生成

ahci_test-objs := ahci.o

#obj-$(CONFIG_SATA_ACARD_AHCI)      += acard-ahci.o libahci.o

#obj-$(CONFIG_SATA_AHCI_SEATTLE)    += ahci_seattle.o libahci.o libahci_platform.o

#obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o

#obj-$(CONFIG_SATA_FSL)                += sata_fsl.o

#obj-$(CONFIG_SATA_GEMINI)       += sata_gemini.o

#obj-$(CONFIG_SATA_INIC162X)     += sata_inic162x.o

#obj-$(CONFIG_SATA_SIL24)   += sata_sil24.o

#obj-$(CONFIG_SATA_SIL24)   += sata_sil24_test.o

#sata_sil24_test-objs := sata_sil24.o

#obj-$(CONFIG_SATA_DWC)             += sata_dwc_460ex.o

#obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o

#obj-$(CONFIG_AHCI_BRCM)                   += ahci_brcm.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_CEVA)            += ahci_ceva.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_DA850)         += ahci_da850.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_DM816)        += ahci_dm816.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_IMX)              += ahci_imx.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_MTK)             += ahci_mtk.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_MVEBU)       += ahci_mvebu.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_OCTEON)     += ahci_octeon.o

#obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_ST)                 += ahci_st.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_TEGRA)         += ahci_tegra.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_XGENE)         += ahci_xgene.o libahci.o libahci_platform.o

#obj-$(CONFIG_AHCI_QORIQ)         += ahci_qoriq.o libahci.o libahci_platform.o

# SFF w/ custom DMA

#obj-$(CONFIG_PDC_ADMA)           += pdc_adma.o

#obj-$(CONFIG_PATA_ARASAN_CF)         += pata_arasan_cf.o

#obj-$(CONFIG_PATA_OCTEON_CF)        += pata_octeon_cf.o

#obj-$(CONFIG_SATA_QSTOR)         += sata_qstor.o

#obj-$(CONFIG_SATA_SX4)                += sata_sx4.o

# SFF SATA w/ BMDMA

#obj-$(CONFIG_ATA_PIIX)                 += ata_piix.o

#obj-$(CONFIG_SATA_MV)                += sata_mv.o

#obj-$(CONFIG_SATA_NV)                 += sata_nv.o

#obj-$(CONFIG_SATA_PROMISE)     += sata_promise.o

#obj-$(CONFIG_SATA_RCAR)            += sata_rcar.o

#obj-$(CONFIG_SATA_SIL)                 += sata_sil.o

#obj-$(CONFIG_SATA_SIS)                 += sata_sis.o

#obj-$(CONFIG_SATA_SVW)              += sata_svw.o

#obj-$(CONFIG_SATA_ULI)                += sata_uli.o

#obj-$(CONFIG_SATA_VIA)                += sata_via.o

#obj-$(CONFIG_SATA_VITESSE)       += sata_vsc.o

# SFF PATA w/ BMDMA

#obj-$(CONFIG_PATA_ALI)                += pata_ali.o

#obj-$(CONFIG_PATA_AMD)             += pata_amd.o

#obj-$(CONFIG_PATA_ARTOP)         += pata_artop.o

#obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o

#obj-$(CONFIG_PATA_ATP867X)      += pata_atp867x.o

#obj-$(CONFIG_PATA_BK3710)        += pata_bk3710.o

#obj-$(CONFIG_PATA_CMD64X)      += pata_cmd64x.o

#obj-$(CONFIG_PATA_CS5520)        += pata_cs5520.o

#obj-$(CONFIG_PATA_CS5530)        += pata_cs5530.o

#obj-$(CONFIG_PATA_CS5535)        += pata_cs5535.o

#obj-$(CONFIG_PATA_CS5536)        += pata_cs5536.o

#obj-$(CONFIG_PATA_CYPRESS)      += pata_cypress.o

#obj-$(CONFIG_PATA_EFAR)             += pata_efar.o

#obj-$(CONFIG_PATA_EP93XX)        += pata_ep93xx.o

#obj-$(CONFIG_PATA_FTIDE010)    += pata_ftide010.o

#obj-$(CONFIG_PATA_HPT366)        += pata_hpt366.o

#obj-$(CONFIG_PATA_HPT37X)        += pata_hpt37x.o

#obj-$(CONFIG_PATA_HPT3X2N)     += pata_hpt3x2n.o

#obj-$(CONFIG_PATA_HPT3X3)        += pata_hpt3x3.o

#obj-$(CONFIG_PATA_ICSIDE)          += pata_icside.o

#obj-$(CONFIG_PATA_IMX)               += pata_imx.o

#obj-$(CONFIG_PATA_IT8213)         += pata_it8213.o

#obj-$(CONFIG_PATA_IT821X)         += pata_it821x.o

#obj-$(CONFIG_PATA_JMICRON)    += pata_jmicron.o

#obj-$(CONFIG_PATA_MACIO)         += pata_macio.o

#obj-$(CONFIG_PATA_MARVELL)    += pata_marvell.o

#obj-$(CONFIG_PATA_MPC52xx)     += pata_mpc52xx.o

#obj-$(CONFIG_PATA_NETCELL)      += pata_netcell.o

#obj-$(CONFIG_PATA_NINJA32)      += pata_ninja32.o

#obj-$(CONFIG_PATA_NS87415)      += pata_ns87415.o

#obj-$(CONFIG_PATA_OLDPIIX)       += pata_oldpiix.o

#obj-$(CONFIG_PATA_OPTIDMA)    += pata_optidma.o

#obj-$(CONFIG_PATA_PDC2027X)   += pata_pdc2027x.o

#obj-$(CONFIG_PATA_PDC_OLD)    += pata_pdc202xx_old.o

#obj-$(CONFIG_PATA_RADISYS)      += pata_radisys.o

#obj-$(CONFIG_PATA_RDC)              += pata_rdc.o

#obj-$(CONFIG_PATA_SC1200)        += pata_sc1200.o

#obj-$(CONFIG_PATA_SCH)               += pata_sch.o

#obj-$(CONFIG_PATA_SERVERWORKS)   += pata_serverworks.o

#obj-$(CONFIG_PATA_SIL680) += pata_sil680.o

#obj-$(CONFIG_PATA_SIS)                 += pata_sis.o

#obj-$(CONFIG_PATA_TOSHIBA)     += pata_piccolo.o

#obj-$(CONFIG_PATA_TRIFLEX)       += pata_triflex.o

#obj-$(CONFIG_PATA_VIA)                += pata_via.o

#obj-$(CONFIG_PATA_WINBOND)  += pata_sl82c105.o

# SFF PIO only

#obj-$(CONFIG_PATA_CMD640_PCI)      += pata_cmd640.o

#obj-$(CONFIG_PATA_FALCON)       += pata_falcon.o

#obj-$(CONFIG_PATA_GAYLE) += pata_gayle.o

#obj-$(CONFIG_PATA_BUDDHA)     += pata_buddha.o

#obj-$(CONFIG_PATA_ISAPNP)         += pata_isapnp.o

#obj-$(CONFIG_PATA_IXP4XX_CF)  += pata_ixp4xx_cf.o

#obj-$(CONFIG_PATA_MPIIX)  += pata_mpiix.o

#obj-$(CONFIG_PATA_NS87410)      += pata_ns87410.o

#obj-$(CONFIG_PATA_OPTI)             += pata_opti.o

#obj-$(CONFIG_PATA_PCMCIA)       += pata_pcmcia.o

#obj-$(CONFIG_PATA_PALMLD)       += pata_palmld.o

#obj-$(CONFIG_PATA_PLATFORM)  += pata_platform.o

#obj-$(CONFIG_PATA_PLATFORM)  += pata_platform_test.o

#pata_platform_test-objs := pata_platform.o

#obj-$(CONFIG_PATA_OF_PLATFORM)    += pata_of_platform.o

#obj-$(CONFIG_PATA_OF_PLATFORM)    += pata_of_platform_test.o

#pata_of_platform_test-objs := pata_of_platform.o

#obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o

#obj-$(CONFIG_PATA_RZ1000)        += pata_rz1000.o

#obj-$(CONFIG_PATA_SAMSUNG_CF)     += pata_samsung_cf.o

#obj-$(CONFIG_PATA_PXA)               += pata_pxa.o

# Should be last but two libata driver

#obj-$(CONFIG_PATA_ACPI)             += pata_acpi.o

# Should be last but one libata driver

#obj-$(CONFIG_ATA_GENERIC)       += ata_generic.o

# Should be last libata driver

#obj-$(CONFIG_PATA_LEGACY)       += pata_legacy.o

#libata-y  := libata-core.o libata-scsi.o libata-eh.o \

#       libata-transport.o libata-trace.o

#libata-$(CONFIG_ATA_SFF)    += libata-sff.o

#libata-$(CONFIG_SATA_PMP)         += libata-pmp.o

#libata-$(CONFIG_ATA_ACPI) += libata-acpi.o

#libata-$(CONFIG_SATA_ZPODD)    += libata-zpodd.o

all: prepare

         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

         cp *.ko $(KERNEL)/

prepare:

         rm -rf $(KERNEL)

         mkdir $(KERNEL)

        

clean:

         rm -f *.o *.ko .*.cmd *.mod.*  *.unsigned *.order *.symvers .*.cmd.* .*.ko.* .*.mod.o.* .*.o.* *.mod

         rm -f -r .tmp_versions

         rm -rf $(KERNEL)

ahci驱动是一个pcie驱动,要使该驱动和我们的pcie设备匹配,需要在设备信息表ahci_pci_tbl[]中增加对应的FPGA pcie设备信息,我这里PCIE厂家id是0x7018,设备id是0x8080,修改如下所示:

{ PCI_DEVICE(0x7018, 0x8080), board_ahci},

由于系统本身已经安装了ahci.ko驱动因此还需要修改驱动名称,否则安装相同的驱动会报驱动已安装错误。如驱动名称为“ahci_test”修改ahci.c文件中宏定义如下:

#define DRV_NAME         "ahci_test"

完成以上修改后编译、安装驱动后/dev目录下依然未生成sata盘对应的设备节点文件。

dmesg命令查看内核打印信息发现未打印端口相关信息。通过查看驱动代码发现读取端口映射寄存器为0。读取端口映射寄存器代码如下:

手动将该寄存器0x7100000c(0x71000000为sata控制器bar基地址)置1后重新安装驱动,/dev/目录下依然未生成sata设备文件。dmesg查看内核驱动打印信息显示端口状态为link down。

查看端口状态寄存器0x71000128(0x71000100为端口0寄存器基地址)的值为0x30,说明端口sata设备确实没有link up。 将端口速率设置寄存器0x71080020设置成1,将sata3.0 改成sata2.0(该寄存器的值和端口速率对应关系为:0:sata1.0 ,1:sata2.0,2:sata3.0)。

重新安装驱动在/dev/目录下成功生成了sda设备文件。此时再次读取端口状态寄存器0x71000128值为0x123。

为了使驱动安装后自动配置以上两个寄存器,将以上两个寄存器配置在驱动中通过代码实现如下:

为了后续调试时能够隔离软件问题,梳理出以下初始化sata控制器步骤(memtool是内存读写工具):

1、进根权限

sudo su 输入密码

2、使能pcie设备

setpci -d 0731:8000 4.B=6

3、复位sata控制器HBA_HOST_GHC

memtool mw 0x71000004 0x01

4、设置HBA_HOST_CAP寄存器

memtool mw 0x71000000 0x6F36FF05

5、读取HBA_HOST_CAP寄存器

memtool md 0x71000000

6、设置端口映射寄存器HBA_HOST_PI

memtool mw 0x7100000c 0x1

7、HBA_PORT_CMD寄存器写0

memtool mw 0x71000118 0x0

8、HBA_HOST_BISTCR寄存器写0x5700

memtool mw 0x710000a4 0x5700

9、读取HBA_HOST_BISTCR寄存器写

memtool md 0x710000a4

10、读取HBA_PORT_CMD寄存器,读取的值为0x4

memtool md 0x71000118

11、HBA_PORT_CMD第4位置1

memtool mw 0x71000118 0x14

12、HBA_PORT_CMD第1位置1

memtool mw 0x71000118 0x16

13、读HBA_PORT_SSTS寄存器,寄存器第0位或者第1位需要置1才link up

memtool md 0x71000128

如果无法link up 需要执行完步骤1-6后设置0x71080020寄存器,将sata3.0 改成sata1.0

memtool mw 0x71080020 0x1

然后执行步骤7-13

参考手册《DWC_ahsata_databook.pdf》

简单梳理了几个关键的数据读写盘相关接口,后续有时间再深入研究。

        

struct ata_port_operations ahci_ops = {

         .inherits            = &sata_pmp_port_ops,

         .qc_defer          = ahci_pmp_qc_defer,

         .qc_prep           = ahci_qc_prep,

         .qc_issue          = ahci_qc_issue,

         .qc_fill_rtf                  = ahci_qc_fill_rtf,

         .freeze                        = ahci_freeze,

         .thaw                          = ahci_thaw,

         .softreset                   = ahci_softreset,

         .hardreset                 = ahci_hardreset,

         .postreset                  = ahci_postreset,

         .pmp_softreset                 = ahci_softreset,

         .error_handler                   = ahci_error_handler,

         .post_internal_cmd          = ahci_post_internal_cmd,

         .dev_config                = ahci_dev_config,

         .scr_read          = ahci_scr_read,

         .scr_write                  = ahci_scr_write,

         .pmp_attach             = ahci_pmp_attach,

         .pmp_detach            = ahci_pmp_detach,

         .set_lpm           = ahci_set_lpm,

         .em_show                  = ahci_led_show,

         .em_store                  = ahci_led_store,

         .sw_activity_show  = ahci_activity_show,

         .sw_activity_store  = ahci_activity_store,

         .transmit_led_message  = ahci_transmit_led_message,

#ifdef CONFIG_PM

         .port_suspend          = ahci_port_suspend,

         .port_resume           = ahci_port_resume,

#endif

         .port_start                = ahci_port_start,

         .port_stop                 = ahci_port_stop,

};

EXPORT_SYMBOL_GPL(ahci_ops);

#命令填充

         .qc_prep           = ahci_qc_prep,

#命令提交

         .qc_issue          = ahci_qc_issue,

        

#初始化sata控制器

ahci_pci_init_controller

#注册相关设备文件,生成/dev/sda设备

int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/8039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数学之美系列 1.3w字精简版阅读笔记

目录 系列一:统计语言模型 (Statistical Language Models) 系列二:谈谈中文分词 系列三:隐含马尔可夫模型在语言处理中的应用 系列四:怎样度量信息 系列五:布尔代数与搜索引擎的索引 系列六:图论和网…

【深入理解Kotlin协程】协程中的Channel和Flow 协程中的线程安全问题

热数据通道 Channel Channel 实际上就是 个并发安全的队列&#xff0c;它可以用来连接协程&#xff0c;实现不同协程的通信&#xff0c;代码如代码清单所示 suspend fun testChannel() {val channel Channel<Int>() var i 0//生产者 发val producer GlobalScope.lau…

双立方插值原理分析

双立方插值原理分析双立方插值 : 其核心思想是利用三次多项式S(x)求逼近理论上最佳插值函数sin(x)/x&#xff0c;待求像素(x, y)的灰度值由其周围16个灰度值加权内插得到公式推导过程 上述图片中像素点的说明&#xff1a; 红色的点为16个真实存在的像素点 P 为双立方插值待插…

SCD1: 微服务概览

1.1简介 1.1.1 概念 集群&#xff1a; 它是一种物理形态&#xff0c;简单来讲就是把同一个业务部署到多个服务器上。而在接收到请求流量时&#xff0c;主要是通过负载均衡器&#xff0c;来进行流量分配。   分布式&#xff1a; 它是一种工作方式&#xff0c;将一个业务拆成多…

SpringMVC学习篇(三)

转发和重定向 1 保存数据四种方式 1.1 转发范围 1.1.1 Model a 设置值 a.1 语法 Model对象.addAttribute(key,value);a.2 示例 m.addAttribute("a","香蕉");b 有效范围 在转发的当前页面有效1.1.2 ModelMap a 设置值 a.1 语法 ModelMap对象.addAt…

API网关功能一览

API网关功能一览 无论是单体应用&#xff0c;SOA或者现在流行的微服务架构&#xff0c;都需要一个API网关。 API网关作为内网的入口&#xff1b;统一对外提供服务。 一些公共服务的建设&#xff0c;也可以在网关层统一处理。 网关应该是无状态&#xff0c;容易线性扩展的;运行时…

基于Swagger的接口自动化测试

本文是一篇讲述敦煌网云原生微服务与服务接口(API)自动化测试实现的文章。 云原生微服务框架项目升级在如火如荼的进行中&#xff0c;根据磐石框架延伸产生的测试技术&#xff0c;亦是本文主旨所在。 一、Swagger介绍 原始时代&#xff0c;可能在工程开发前夕&#xff0c;会…

XSS进阶一

目录实验目的预备知识实验环境实验步骤一实例一、热身运动&#xff0c;不设防实验步骤二实例二、小写不行&#xff0c;就大写吧实验步骤三实例三、大写小写都不行&#xff0c;看你怎么办&#xff1f;实验目的 1.深入理解xss工作原理。 2.怎么去绕过规则实现xss。 3.培养学生的…

卷积版动作仿真模拟网络

🍿*★,*:.☆欢迎您/$:*.★* 🍿 目录 背景 正文 总结 背景描述

【图像分割】基于差分进化算法优化模糊熵实现多级图像阈值分割附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

猿创征文|2022年前端之路——我的前端开发好帮手

&#x1f4ac;关于「猿创征文 」第四季 | 2022 年我的开发者工具 活动主旨&#xff1a;开发者每天都在使用、寻找、贡献、创作各类开发者工具&#xff0c;包括开源服务、付费软件、API等。好的工具可以极大帮助我们提升效率&#xff0c;服务业务。本期邀请大家创作在2022年有效…

Linux 中 /etc/hosts 文件的用途是什么

前言 无论是Linux操作系统还是windows操作系统&#xff0c;都存在 /etc/hosts 文件&#xff0c;该文件主要用于映射 IP 地址和域名之间的连接。如果你对这句话还不是特别理解&#xff0c;那就跟着我继续往下一起来看一下这个文件到底是如何将IP地址和域名之间进行映射的。 /e…

云原生学习的最佳路径

前言 运维这个课程是一个入行门槛低&#xff0c;精通比较难的岗位。 之所以比较难精通&#xff0c;是因为学的比较杂。更重要的是很多种知识并没有一个很好的连贯性。 比如你学zabbix和学docker&#xff0c;就是在学两个东西。 在或者你学nginx和学mysql&#xff0c;这也是两…

SparkSQL-数据模型DataFrameDataSet

数据模型DataFrame 1. DataFrame是什么 在 Spark 中&#xff0c;DataFrame 是一种以 RDD 为基础的分布式数据集&#xff0c;类似于传统数据库中的二维表格。DataFrame 与 RDD 的主要区别在于&#xff0c;前者带有 schema 元信息&#xff0c;即 DataFrame 所表示的二维表数据集…

Postman的接口测试和持续集成——接口测试方法论

在使用Postman完成从单接口测试用例的设计到业务逻辑接口测试用例的设计之后&#xff0c;相信我们已经掌握了接口测试的思维以及具体的实现方法。到目前为止&#xff0c;我们还处在手动测试阶段&#xff0c;尽管和以前基于界面的业务测试相比已经有了很大区别&#xff0c;但距离…

shell脚本编程基础(上)

目录 (一&#xff09;shell介绍 1.什么是shell 扩展知识 2. shell功能 &#xff08;二&#xff09;shell语法 2.1 如何书写一个shell脚本 0x01 shell脚本的命名&#xff1a; 0x02 shell脚本格式&#xff1a; 0x03 shell中的注释使用#号 2.2 如何运行一个shell脚本 2.3 s…

Redis 实现限流策略

除了控制流量&#xff0c;限流还有一个应用目的是用于控制用户行为&#xff0c;避免垃圾请求。 比如在 UGC 社区&#xff0c;用户的发帖、回复、点赞等行为都要严格受控&#xff0c;一般要严格限定某行为在规定 时间内允许的次数&#xff0c;超过了次数那就是非法行为。对非法…

Word处理控件Aspose.Words功能演示:使用 Python 合并 Word 文档

当您必须将多个 Word 文档合并到一个文件中时&#xff0c;可能会有多种情况。例如&#xff0c;当多人编写文档的不同部分时&#xff0c;您需要在最后组合内容。另一方面&#xff0c;您可能需要将所有发票合并到一个 Word 文档中。为了以编程方式执行此合并&#xff0c;本文介绍…

码神之路项目总结(四)

一、图片上传 请求接口&#xff1a; 思路&#xff1a; 1、后端用MultipartFile接收前端传过来的文件信息 2、用uuid将文件重命名&#xff0c;然后将文件以新文件名通过七牛云上传到七牛云服务器 二、导航--文章分类 请求接口&#xff1a; 思路&#xff1a; 1、直接从文章…

全球绿色建筑的 10 个最酷的例子

全球变暖和气候变化&#xff0c;是我们日常生活中需要解决的社会问题。从减少塑料的使用到尽量减少汽车的使用&#xff0c;因为它会导致化石燃料的燃烧&#xff0c;每个人都必须具有社会意识&#xff0c;以减轻全球变暖的影响。 在这种情况下&#xff0c;我们为世界十大绿色建…