搜索
bottom↓
回复: 0

《STM32MP1 M4裸机CubeIDE开发指南 V1.5.2》第二十八章A7和M4联合调试

[复制链接]

出0入234汤圆

发表于 2022-8-10 11:55:43 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2022-8-10 12:17 编辑

1)实验平台:正点原子STM32MP157开发板
2) 章节摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南 V1.5.2
3)购买链接:https://detail.tmall.com/item.htm?id=631745687288
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/arm-linux/zdyzmp157.html1.0.0 文档
5)正点原子官方B站:https://space.bilibili.com/394620890
6)STM32MP157技术交流QQ群:703341432 lQLPJxaFi2zaB4UWWrDAMgIsFEW2pwLb3abnwDMA_90_22.png
lQDPJxaFi2nfFizMjM0CbLCPlxn_FVheIQLb3aGrwFQA_620_140.jpg

lQLPJxaFi2nfFhLMkM0BXrDNvOUyeU_FPgLb3aGvQNIA_350_144.png
第二十八章  A7和M4联合调试
        我们在前面的第六章节分析STM32CubeMP1固件包的时候,固件包下有一个OpenAMP文件夹,AMP是指非对称多处理(Asymmetric Multiprocessing),非对称多处理是指各核的结构并非对称,例如STM32MP1是两个Cortex-A7内核加一个Cortex-M4内核的组合,各个核结构并非对称。OpenAMP常用于处理器间通信,OpenAMP软件框架为开发AMP系统提供了必要的API函数,可以基于这些API实现核间通信。
OpenAMP下的Remoteproc允许本地处理器与系统上可用的远程处理器进行通信,对于STM32MP157,本地处理器就是指Cortex-A7,远程处理器指Cortex-M4,本节我们就利用Remoteproc来让Cortex-A7远程控制Cortex-M4的生命周期,即加载、启动和停止Cortex-M4上的固件(.elf或者.axf文件)。
        前面的Cortex-M4开发实验部分我们是在线仿真的,即通过ST-Link将程序下载到SRAM中运行,开发板掉电后程序就会丢失,这种方式适合在Cortex-M4开发调试阶段,也叫工程模式(Engineering Mode)。如果在核间通信的时候,我们就需要使用量产模式(Production Mode)来进行联合调试,下面我们讲解如何实现Cortex-A7和Cortex-M4联合调试。
        关于Cortex-A7和Cortex-M4双核通信的相关实验,正点原子会有独立的文档章节进行讲解。本节我们只是讲解如何在Linux操作系统中使用Cortex-A7去加载、启动和停止运行Cortex-M4的固件。
        本章将分为如下几个小节:
        28.1、Remoteproc框架简介;
        28.2、使用STM32CubeIDE进行调试;
        28.3、拷贝文件后手动调试;
28.1 Remoteproc框架简介
28.1.1 Remoteproc框架

对于具有非对称多处理的SOC,不同的核心可能跑不同的操作系统,例如STM32MP157的Cortex-A7运行Linux操作系统,Cortex-M4可以运行RTOS操作系统。为了使运行Linux的主处理器与协处理器之间能够轻松通信,Linux引入了Remoteproc框架,该框架允许不同的平台/体系结构在抽象硬件差异的同时控制那些远程协处理器,如主处理器加载协处理器固件,打开、关闭或配置协处理器等。此外,Remoteproc框架还添加了RPMsg和Virtio,所以Remoteproc驱动只需要提供一些低级处理程序,其它RPMsg驱动程序就可以正常工作。
Remoteproc驱动提供可直接调用的API,方便用户层去调用,在Linux操作系统下已经有remoteproc 的相关驱动和API,这里我们就不需要过多地去关注remoteproc 了,我们直接使用它来控制M4内核即可(Remoteproc、RPMsg和Virtio是OpenAMP下重要的框架,在后面的章节我们会对它们进行讲解)。STM32MP157的Linux下Remoteproc框架如下:
image002.jpg
图28.1.1. 1 Remoteproc框架

        在Remoteproc框架框图中,我们查看两个重要的组成部分:
        remoteproc是通用远程处理框架部分,其作用是:
        1)将.elf文件加载到Cortex-M4内核中(在MDK下是.axf文件);
        2)解释.elf文件资源表以设置关联的资源(例如IPC和内存分割等);
        3)控制Cortex-M4内核启动、关闭;
        4)提供监视和调试远程服务;
        stm32_rproc是远程处理器平台(即M4)驱动程序,其作用是:
        1)向Remoteproc框架注册供应商特定的功能(如回调部分);
        2)处理Cortex-A7和Cortex-M4关联的平台资源(例如寄存器,看门狗,复位,时钟和存储器);
        3)通过邮箱框架将通知转发到M4;
        以上Cortex-A7称为主处理器,Cortex-M4称为协处理器,主处理器先启动,然后引导协处理器启动,主处理器再加载协处理器固件。总之,Remoteproc框架实现了对远程协处理器生命周期的控制,它允许Cortex-A7主处理器将.elf固件加载到Cortex-M4内核中,然后解析固件资源列表后再启动/关闭/配置Cortex-M4内核。而RPMsg(远程处理器消息传递,英文:Remote Processor Messaging)通过共享内存向远程CPU发送消息或从远程CPU接收消息。
        下面,我们利用Remoteproc来实现Cortex-A7加载并运行Cortex-M4固件(.elf文件)。
28.1.2 实验准备
        实验前,我们需要以下硬件资源:
        1)正点原子STM32MP157开发板(配套电源线);
        2)2根Type-C线;
        3)ST-Link下载器(加转接板和T口USB线);
        4)一张TF卡或U盘;
        5)一根网线;
        以上的第3和第4项根据选择的环境不同而需求不同,例如:如果使用STM32CubeIDE将固件通过Remoteproc下载到开发板的Linux操作系统中的话,那么ST-Link下载器就必须要用到;如果选择通过将TF卡或者U盘拷贝固件到开发板的话,则不需要ST-Link下载器;如果使用网络(如FTP或SSH)的方式传输固件的话,则第3和第4项都不需要,但是要一根网线。
        注意事项:
        一开始ST推出了STM32CubeIDE1.4.0版本,本教程一直使用的也是STM32CubeIDE1.4.0版本,使用正常,没发现什么问题。后来ST又推出了STM32CubeIDE1.5以及STM32CubeIDE1.6.1,测试发现STM32CubeIDE1.6.1无法识别MPU Serial(详情请见第28.2小节),可能是新版本软件的Bug或者其它原因,目前遇见这种情况的小伙伴,他们将STM32CubeIDE1.6.1卸载,再安装STM32CubeIDE1.4.0,然后再安装STM32CubeIDE1.6.1就可以了,这也是奇怪,笔者还未发现具体是什么原因,如果找到原因的朋友可以在正点原子论坛http://www.openedv.com/forum.php发表你的解决办法,大家一起学习,共同进步!
1.        硬件连接
1)使用STM32CubeIDE进行调试
        下面,我们采用STM32CubeIDE将固件通过Remoteproc下载到开发板的Linux操作系统中,我们先进行连线操作。首先,需要使用一根Type-C线将开发板的USB_OTG接口接到PC的USB接口,用于模拟出一个USB网卡,然后再用一根Type-C线将开发板的USB_TTL接口接到PC的USB接口,用于模拟通过串口获取USB网卡的IP,以实现开发板和电脑通信,如下图:
image004.jpg
图28.1.2.1.1硬件连接图1

2)网络传输文件
        如果不是使用STM32CubeIDE进行调试,而是使用网络的方式传输固件的话,硬件连接方式如下,只需要接电源线以及在USB_TTL口接Type-C线,外加网口接一根网线(网线另一端可以接路由器或者和电脑直连,根据个人情况来选择):
image006.jpg
图28.1.2.1.2硬件连接图1

1)        采用TF或者U盘卡拷贝固件
如果使用TF卡或者U盘等存储设备来拷贝的话,开发板只需要接电源线以及在USB_TTL接口接Type-C线即可。
2.        启动Linux操作系统
        先接好线,开发板拨码开关拨到010,即eMMC启动方式,因为开发板出厂Linux系统已经烧录在eMMC里了,接好电源线启动开发板,等待A7启动完成。判断A7是否启动完成,可以通过观察底板的LED0是否在闪烁(出厂的Linux系统在设备树里已经默认配置LED0为心跳灯,启动进入Linux系统后,LED0会闪烁),或者在串口终端查看串口的打印信息,如果开发板底板的LED0在闪烁或者串口终端已经打印“root@ATK-stm32mp1”,则说明Linux 系统已经完全启动。
image008.jpg
图28.1.2.2.1串口打印信息

        此时,查看设备管理器,网络适配器下多出了“Remote NDIS Compatible Device #2”,该设备是USB_OTG模拟的USB网卡;端口下多出了一个CH340设备口,是USB_TTL的COM口(这里显示COM65),如下图所示:
image010.jpg
图28.1.2.2.2设备管理器情况

        如下,在网络连接处也可以看到模拟的USB网卡“Remote NDIS Compatible Device #2”:
image012.jpg
图28.1.2.2.3网络连接情况

        如果没有看到模拟的USB网卡,可以检查开发板Linux系统是否正常运行、连接在USB_OTG口的Type-C线是否接好以及线是否有问题等,可以尝试重启开发板或者重新接好Type-C线。下面,我们利用此USB网卡并借助Remoteproc将固件(.elf文件)传输到Linux操作系统中。
28.2 使用STM32CubeIDE进行调试
28.2.1 操作步骤

        如果使用STM32CubeIDE来开发M4,最终生成.elf文件,可通过STM32CubeIDE将.elf文件上传到开发板的“/lib/firmware”目录下并自动运行。
        我们本小节实验以第十一章的实验来进行测试,首先,按照28.1.2小节讲解的步骤接好线,再将ST-Link接在开发板JTAG口,然后开发板从eMMC启动,等待进入Linux操作系统,注意观察是否有USB网卡:
image014.jpg
28.2. 1 硬件连接图

        然后打开STM32CubeIDE,我们需要设置串行过滤器,因为默认情况下,STM32CubelDE是只将STMicroelectronics和FTDI设备作为首选的串行设备,其它设备无法识别,所以我们要关闭默认选项而选择我们需要的设备,点击“Windows PreferencesSTM32CubeMPU Serial”,设置如下:
image016.jpg
28.2. 2 设置属性

        可能会出现多个COM口,根据设备管理器显示的设备来选中对应的COM口:
image018.jpg
28.2. 3 勾选COM口

        点击Debug配置选项,进入Debug Configurations配置界面:
image020.jpg
28.2. 4 Debug配置

        如下,选中默认已有的BEEP_CM4 Debug配置项,如果没有此配置项,可以双击“STM32 Cortex-M C/C++ Applications”来新建一个配置项,关于这些操作,相信大家都已经很熟悉了,如果不清除的,可以看前面第四章的实验部分。
image022.jpg
28.2. 5 Debug工程配置

进入调试器配置部分,按照如下来配置,在Load Mode配置项选中“thru JTAG/SWD link(Production mode),Serial Port”处根据设备管理器显示部分选择COM口,这里选择“MPU Serial (COM65)”,“Inet Address”处会自动显示192.168.7.1,此IP地址就是USB网卡的IP地址:
image024.jpg
28.2. 6 调试器配置

        如果此时在Linux操作系统下输入ifconfig,可以看到USB网卡的IP为192.168.7.1,STM32CubeIDE就是通过此IP地址将.elf文件传输到Linux操作系统的。
image026.jpg
28.2. 7 查看USB网卡

        点击Debug后,STM32CubeIDE开始将BEEP_CM4.elf文件下载到Linux文件系统的“/lib/firmware”下,下载好后,系统会自动解析BEEP_CM4.elf文件资源,然后设置相关的资源,并运行程序:
image028.jpg
28.2. 8 使用STM32CubeIDE进行调试

        此时,开发板的蜂鸣器开始嘀嗒嘀嗒发出声响,在串口终端的“/lib/firmware”下也可以找到BEEP_CM4.elf文件,同时串口终端打印一些调试信息:
1   remoteproc remoteproc0: powering up m4
2   remoteproc remoteproc0: Booting fw image BEEP_CM4.elf, size 1920276
3   remoteproc remoteproc0: header-less resource table
4   remoteproc remoteproc0: no resource table found for this firmware
5   remoteproc remoteproc0: header-less resource table
6   remoteproc remoteproc0: remote processor m4 is now up
image030.jpg
28.2. 9 串口打印信息

        以上的打印信息中:
        第1行:启动M4;
        第2行,启动固件BEEP_CM4.elf,并提示该固件文件大小为1920276(指文件大小,不是程序大小);
        第3和第5行,A7打印“header-less resource table”表示资源表大小为0,资源表是描述固件资源的一个条目(或者说数据结构),在加载M4固件的时候,A7会去解析固件,并检查资源表的信息,如果资源表大小为0,就会打印“header-less resource table”;
        第4行,打印提示没有这个固件的资源表;
        第6行,远程处理器M4已经启动,这里主处理器是A7。
        可以点击STM32CubeIDE的暂停键暂停调试,蜂鸣器就停止发声,或者点击停止键退出调试:
image032.jpg
28.2. 10 使用STM32CubeIDE调试功能

28.2.2 fw_cortex_m4.sh脚本分析
        本小节可以作为对前面STM32CubeIDE操作过程的理解,可以不必深究。
1、fw_cortex_m4.sh脚本分析
        前面操作完成后,跑Linux操作系统的A7成功运行了跑裸机的M4的固件,这个过程其实是由一个fw_cortex_m4.sh脚本参与完成的,该脚本我们在前面的8.3小节里有简单提到过,因为还没有实验用到该脚本,所以我们前面未对该脚本进行解释。下面我们来看看这个脚本。
        在STM32CubeIDE的RemoteProc目录下可以看到该脚本:
image034.jpg
图28.2.2.1 IDE中的fw_cortex_m4.sh脚本

        不能直接在STM32CubeIDE上双击查看此脚本,可以使用代码查看软件来查看此脚本的内容,内容如下:
1   #!/bin/sh
2
3   rproc_class_dir="/sys/class/remoteproc/remoteproc0"
4   fmw_dir="/lib/firmware"
5   fmw_name= "BEEP_CM4.elf"
6
7   cd $(/usr/bin/dirname $(/usr/bin/readlink -f $0))
8
9   if [ $1 == "start" ]
10  then
11          # Start the firmware
12          /bin/rm -f /lib/firmware/$fmw_name
13          /bin/ln -s $PWD/lib/firmware/$fmw_name $fmw_dir
14          /bin/echo -n "$fmw_name" > $rproc_class_dir/firmware
15          /bin/echo -n start > $rproc_class_dir/state
16  fi
17
18  if [ $1 == "stop" ]
19  then
20          # Stop the firmware
21          /bin/echo -n stop > $rproc_class_dir/state
22  fi
        如果学过shell的基本语法,这段脚本很容易可以看懂,我们简单了解一下该脚本做了什么:
        第3行,/sys/class/remoteproc/remoteproc0是加载、启动和停止固件的文件操作路径,Linux下一切皆文件,我们实际上是通过操作文件来实现对应的功能。我们查看此路径下有什么:
image036.jpg
图28.2.2.2加载、启动、停止固件相关文件

        可以看到/sys/class/remoteproc/remoteproc0/firmware文件的内容是BEEP_CM4.elf,这个就是本实验M4固件的名字,默认情况下该文件的内容是rproc-m4-fw,在A7加载M4固件后,此文件内容就会被修改。
        第4行,/lib/firmware是固件(或者固件的软链接文件)所在的路径,我们看看该路径下有什么:
image038.jpg
图28.2.2.3链接文件

        可以看到,/lib/firmware下的BEEP_CM4.elf文件指向了/usr/local/projects/BEEP_CM4/lib/firmware/BEEP_CM4.elf,也就是/lib/firmware/BEEP_CM4.elf文件是软链接文件,实际的文件是/usr/local/projects/BEEP_CM4/lib/firmware/BEEP_CM4.elf,也就是运行固件时,实际上是运行/usr/local/projects/BEEP_CM4/lib/firmware/下的固件,如下图,可以看到BEEP_CM4.elf文件大小是1.9MB,同时我们注意到,在/usr/local/projects/BEEP_CM4下有一个fw_cortex_m4.sh文件,此文件的内容和STM32CubeIDE上的fw_cortex_m4.sh文件内容一样:
lQLPJxaTrEd_MdTMns0B_rDp0ZdlG4MTcgLzA4DnQIkA_510_158.png
图28.2.2.4 文件系统中的fw_cortex_m4.sh文件

        第5行,固件的名字是BEEP_CM4.elf;
        第7行,熟悉shell基本指令的话,就知道/usr/bin/dirname表示获取当前脚本的路径,$(/usr/bin/readlink -f $0)表示找出软链接所指向的位置,也就是fw_cortex_m4.sh文件的位置,整个语句$(/usr/bin/dirname $(/usr/bin/readlink -f $0))就是指获取当前脚本文件fw_cortex_m4.sh所在的目录。上图中我们已经知道脚本位于/usr/local/projects/BEEP_CM4下了,cd $(/usr/bin/dirname $(/usr/bin/readlink -f $0))就表示进入了/usr/local/projects/BEEP_CM4目录,该目录就是当前脚本所在的位置,如果执行pwd指令的话,就显示当前目录为:
/usr/local/projects/BEEP_CM4
image040.png
图28.2.2.5 fw_cortex_m4.sh文件所在路径

        第9行,如果指令的第二个字符是"start",则执行第10~16行的shell语句。在shell的基本语法中,如果执行如下指令:
./test.sh start BEEP_CM4.elf
        $0就是./test.sh,$1就是start,$2就是BEEP_CM4.elf,大家理解其操作含义即可。我们看看10~16行做了什么:
        第12行,先删除/lib/firmware/ BEEP_CM4.elf 文件;
        第13行,执行/bin/ln下的ln指令进行软链接到$PWD/lib/firmware/$fmw_name,这里$PWD=/usr/local/projects/BEEP_CM4,$fmw_name=BEEP_CM4.elf,所以/lib/firmware/下的BEEP_CM4.elf文件实际上是链接到了/usr/local/projects/BEEP_CM4//lib/firmware/$fmw_name/ BEEP_CM4.elf:
图28.2.2.6固件链接的位置

        第14行,"$fmw_name"= BEEP_CM4.elf,$rproc_class_dir/firmware= /sys/class/remoteproc/remoteproc0 /firmware,表示将字符串BEEP_CM4.elf写入到文件/sys/class/remoteproc/remoteproc0 /firmware中;
        第15行,表示运行固件,当固件运行后,/sys/class/remoteproc/remoteproc0/state文件的内容是running,表示固件正在运行,如果显示的是offline,则表示固件处于停止状态:
image042.jpg
图28.2.2.7固件在运行

        第18行,如果指令的第二个字符是"start",则执行第19~22行的shell语句,第21行就是停止固件的作用。
2、fw_cortex_m4.sh的使用
        经过前面分析,我们大体知道STM32CubeIDE做了如下工作:
1)STM32CubeIDE将fw_cortex_m4.sh文件传输到Linux文件系统的/usr/local/projects/BEEP_CM4目录下,将BEEP_CM4.elf文件传输到/usr/local/projects/BEEP_CM4/lib/firmware目录下;
2)执行fw_cortex_m4.sh脚本文件,将/lib/firmware/BEEP_CM4.elf链接到/usr/local/projects/BEEP_CM4/lib/firmware/BEEP_CM4.elf,然后再将字符串BEEP_CM4.elf写入到文件/sys/class/remoteproc/remoteproc0 /firmware中,再去运行或者停止BEEP_CM4.elf固件。
我们可以模仿fw_cortex_m4.sh脚本,自己去编写一个类似的脚本来实现加载、启动、停止固件。如下,我们在/lib/firmware目录下新建一个test.sh脚本,脚本内容如下:
#!/bin/sh

rproc_class_dir="/sys/class/remoteproc/remoteproc0"
fmw_dir="/lib/firmware"

cd /sys/class/remoteproc/remoteproc0

if [ $1 == "start" ]
then
    /bin/echo -n $2 > $rproc_class_dir/firmware
    /bin/echo -n start > $rproc_class_dir/state
fi

if [ $1 == "stop" ]
then
    /bin/echo -n stop > $rproc_class_dir/state
fi
        编写好脚本文件后,执行如下指令给脚本文件可读可写可执行权限:
chmod 777 test.sh
lQLPJxaTtCwYJJ45zQGbsH-H0g5kk7joAvMQb42AdQA_411_57.png
图28.2.2. 8 给脚本文件可读可写可执行权限

因为/lib/firmware目录下已经有了BEEP_CM4.elf,我们可以执行如下指令来加载、运行以及停止BEEP_CM4.elf固件:
/* 加载、运行固件 */
./test.sh start BEEP_CM4.elf
/* 停止运行固件 */
./test.sh stop BEEP_CM4.elf
image044.png
图28.2.2.9编写脚本实现加载、运行、停止固件

         所以,我们可以不使用STM32CubeIDE来运行M4固件,使用该脚本就可以了。
28.3 传输文件后手动运行调试
        如果不使用STM32CubeIDE来进行调试,可以使用TF卡或者U盘拷贝文件的方式将BEEP_CM4.elf文件拷贝到开发板Linux文件系统的/lib/firmware目录下,然后执行相关指令对固件BEEP_CM4.elf进行加载、运行和关闭操作(如果操作了前面28.2小节实验,实际上/lib/firmware目录下已经有该文件了)。如果使用的是网络的方式将固件BEEP_CM4.elf传输到Linux文件系统的/lib/firmware目录下,硬件接线方式请参考第28.1.2小节,按照如下操作进行传输文件。
28.3.1 通过网络传输文件
        成功编译工程后,进入工程CM4\Debug下可以看到BEEP_CM4.elf文件,同时按下Shift键并按下鼠标右键,可以打开选项界面,如下,可以看到Powershell选项或者如果电脑安装了Git的话,可以看到Git Bash Here,这两个也就是shell终端,可以打开shell后操作Linux指令,两者选其中一个就可以,下面我们就选择使用Powershell吧。
image046.png
图28.3.1. 1 打开Powershell

        打开Powershell后,输入ls后按下回车,可以看见当前目录下有什么文件:
image048.png
图28.3.1. 2 查看文件

        开发板启动进入Linux操作系统,输入ifconfig可以查看开发板的IP地址,如下IP地址是192.168.1.26:
image050.png
图28.3.1. 3 查看开发板的IP地址

        我们就是通过此IP将文件传输到开发板的,先检查开发板和Windows是否能正常通信,在Powershell中ping开发板IP地址可以ping通,说明两者通信正常,可以互传文件:
image052.png
图28.3.1. 4 测试Windows和Linux通信

        执行如下指令将BEEP_CM4.elf文件传输到开发板的/lib/firmware目录下:
scp BEEP_CM4.elf root@192.168.1.26:/lib/firmware
image054.png
图28.3.1. 5 将文件传输到Linux

        在开发板的/lib/firmware目录下可以看到已经有该文件了:
image056.png
图28.3.1. 6 文件传输成功

28.3.2 加载固件和测试
传输BEEP_CM4.elf文件成功后,通过执行以下指令来手动加载、运行或者关闭固件:
/* 加载固件 */
echo BEEP_CM4.elf > /sys/class/remoteproc/remoteproc0/firmware
/* 开启,此时程序就会运行,蜂鸣器就嘀嗒嘀嗒发出响声 */
echo start > /sys/class/remoteproc/remoteproc0/state
/* 关闭,停止固件运行 */
echo stop > /sys/class/remoteproc/remoteproc0/state
        不过要注意的是,执行最后一条stop指令的时候,如果此时蜂鸣器刚好由不响到响,执行此条指令以后蜂鸣器会一直响,如果此时蜂鸣器刚好由响到不响,执行此指令以后蜂鸣器就不响了,也就是停止在执行指令的那个状态。
image058.png
图28.3.2.1串口打印信息

如果在执行启动固件的指令,蜂鸣器优惠继续响:
scp BEEP_CM4.elf root@192.168.1.26:/lib/firmware
        当然,也可以参考前面28.2.2小节讲解的,执行如下指令即可:
/* 加载、运行固件 */
./test.sh start BEEP_CM4.elf
/* 停止运行固件 */
./test.sh stop BEEP_CM4.elf
        至此,我们已经掌握了如何在Linux下去运行M4固件,在双核通信实验部分,我们也是基于此方式来实现。关于双核通信的实验,大家可以看《【正点原子】STM32MP1异核通讯》文档教程。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 05:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表