如何安全地传递最终传递给内联汇编的IO地址?

如何解决如何安全地传递最终传递给内联汇编的IO地址?

我有一个AVR项目的简短摘要:

DELETE FROM dist
  WHERE hexbin1,hexbin2,source NOT IN (
    SELECT hexbin1,source FROM dist INNER JOIN (
      SELECT hexbin1 as h1,hexbin2 as h2,min(distance) as m
      FROM dist GROUP BY hexbin1,hexbin2)
    ON hexbin1==h1 AND hexbin2==h2 AND distance==m);

此块后面的想法是在短时间内(T1H_NOOP)启用特定的引脚(实际的物理微处理器引脚),然后将其关闭。上面的代码实际上可以完美地工作。

但是,在上面的代码中,确切的引脚是硬编码的:PORTB,引脚0( uint8_t high = _BV(0); uint8_t low = ~high; uint8_t port_value = 0; asm volatile ( "in %0,%1 \n\t" "or %0,%3 \n\t" "out %1,%0 \n\t" T1H_NOOP "and %0,%2 \n\t" "out %1,%0 \n\t" T1L_NOOP : "=r" (port_value) : "I" (_SFR_IO_ADDR(PORTB)),"r" (low),"r" (high)); )。我想要的是传递这样的地址:

_BV(0)

只要我留在C代码中,那实际上是可行的。

struct IO_ADDR {
    volatile uint8_t *port;
    uint8_t pin
}

当我这么说的时候,我的意思是我已经通过模拟器运行了这个程序,并且看到销钉按预期方式工作了,再加上我将该代码段与上面的程序集配对并在硬件上运行它。因此,很明显, struct IO_ADDR addr = { .port = &PORTB,.bit = 0 }; latch(&addr); void latch(struct IO_ADDR *addr) { if (addr->bit >= 8) return; *(addr->port) &= ~(_BV(addr->bit)); _delay_us(50); } 在寻址引脚本身,而不是指针。很好。

但是,当我这样做时,出现组装错误:

*(addr->port) &= ...

此错误:

        asm volatile (
            "in %0,%1   \n\t"
            "or %0,%3   \n\t"
            "out %1,%0  \n\t"
            T1H_NOOP
            "and %0,%2   \n\t"
            "out %1,%0   \n\t"
            T1L_NOOP
        : "=r" (port_value)
        : "I" (_SFR_IO_ADDR(*(addr->port))),"r" (high));

如果我用/nix/store/j31yaksw2dh82by2lgz1ysgh494cz6j2-src/neopixels.c: In function 'write_value': /nix/store/j31yaksw2dh82by2lgz1ysgh494cz6j2-src/neopixels.c:29:9: warning: asm operand 1 probably doesn't match constraints 29 | asm volatile ( | ^~~ /nix/store/j31yaksw2dh82by2lgz1ysgh494cz6j2-src/neopixels.c:29:9: error: impossible constraint in 'asm' 替换addr-> port参数,也会发生这种情况。

_SFR_IO_ADDR(addr->port)对此进行了预处理:

SFR_IO_ADDR(*(addr->port))

: "I" ( # 38 "src/neopixels.c" 3 4 (((uint16_t) &( # 38 "src/neopixels.c" *(addr->port) # 38 "src/neopixels.c" 3 4 )) - 0x20) # 38 "src/neopixels.c" ) 的情况下,最终组装应该是这样的,地址在此特定硬件上为0x24(并且忽略编译器选择的确切寄存器):

PORTB

要将该特定IO地址传递给我的汇编代码,我需要做什么?

解决方法

"I"程序集约束requires it's operand to be a constant(或者,对于-O1 / -O2,是一个常量表达式),因此很遗憾,您将无法将其作为参数传递。

,

经过一天的研究,我找到了这个答案:

        asm volatile (
            "ld %0,%1  \n\t"
            "or %0,%3  \n\t"
            "st %1,%0 \n\t"
            T1H_NOOP
            "and %0,%2 \n\t"
            "st %1,%0 \n\t"
            T1L_NOOP
        : "=r" (port_value)
        : "X" (*(addr->port)),"r" (low),"r" (high));

涉及两个关键点。其中之一是提供X约束,而不是I约束,这实际上意味着“操作数可以是任何东西”。这不是次优的,但是汇编器不接受一些更明显的地址(“操作数是不可重定位的内存地址”。)

此外,我从inout汇编程序指令(如罗斯·里奇在上面的注释中指出的那样)切换到需要在编译时必须知道的立即地址,并转到了{{ 1}}和ld指令,它们接受内存地址。

最后一点,我必须更改某些T1H_NOOP,T1L_NOOP,T0H_NOOP和T0L_NOOP宏中NOP指令的数量,以维持LUKS (encryption)所需的时序约束。

所有这些都非常痛苦,以至于我读了一些有关脉冲宽度调制和带有中断的计时器/时钟电路的文章,因为这感觉会比我的活动繁忙循环产生更可靠的时序。但是,添加中断处理程序会以我现在不准备处理的方式增加代码的复杂性。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-