CAN RX&Amp;TX缓冲器/FIFO起始地址(F0SA/TBSA)的寄存器只考虑地址的低16位,但RAM地址可以从0x20000000到0x20040000(18位).

RX FIFO Start Address Register TX Buffer Start Address Register

链接到datasheet.

因此,如果我将一个数组初始化为RX FIFO,如下所示:

uint8_t can1_rx_fifo0[CAN1_RX_FIFO_ELEMENTS * 16] __attribute__((__aligned__(4)));

编译器将其放在内存地址0x20005A70,这是没有问题的,因为我可以将0x5A70写入F0SA/TBSA,并且CAN将看到正确的缓冲区/FIFO地址.但是,如果该数组位于地址0x20015A70,我仍然只能将0x5A70写入F0SA/TBSA,而这是错误的地址.

我try 这样做,FIFO被放在我指定的适当地址,但随后该地址被覆盖/用于RAM中的其他内容.

#define CAN1_RX_FIFO            (volatile struct can1_rx_fifo_struct*)(0x20000000)

static struct can1_rx_fifo_struct
{
    uint8_t can1_rx_fifo[CAN1_RX_FIFO_ELEMENTS * 16];
};

我是不是误解了这是怎么回事?如果不是,我如何才能以最佳且安全的方式初始化数组,以便将其存储在0x20000000-0x2000FFFF之间的内存地址?

推荐答案

当我为另一个Atsam部件编写CAN驱动程序时,我只是厚颜无耻地确保它被分配给.bss,将其设置为static,然后确保.bss在RAM的顶部.

从我的驱动程序代码中:

struct can_msg_t                   // opaque type used by the CAN driver API
{
  uint32_t reg0;
  uint32_t reg1;
  uint8_t  data [CAN_DATA_BYTES_N];
};
_Static_assert(sizeof(can_msg_t) == 8+CAN_DATA_BYTES_N,    // defensive programmming   
               "can_msg_t: incorrect padding detected");

...

typedef struct
{
  struct can_msg_t  rx_buffer     [CAN_RX_BUFFER_N];
  struct can_msg_t  rx_fifo_0     [CAN_RX_FIFO_N];
  struct can_msg_t  rx_fifo_1     [CAN_RX_FIFO_N];
  struct can_msg_t  tx_buffer     [CAN_TX_BUFFER_N + CAN_TX_FIFO_SIZE_N];
  can_msg_tx_event  tx_event_fifo [CAN_TX_EVENT_FIFO];
  uint32_t          rx_std_filter [CAN_RX_STD_FILTER_N];
  uint32_t          rx_ext_filter [CAN_RX_EXT_FILTER_N];
} can_port_t;

static volatile can_port_t can0;
static volatile can_port_t can1;

can0can1将被分配到.bss..bss还没有大到超出可寻址范围,它被分配在0x20000000,所以这将(厚脸皮)工作.

您还可以确保它们不会被静态断言分配到错误的节中:

#define TOP_ADDRESS 0x2000FFFFu

_Static_assert( (uintptr_t)&can0 <= (TOP_ADDRESS - sizeof(can_port_t)), 
                "can0 outside addressable range for the CAN registers." );
_Static_assert( (uintptr_t)&can1 <= (TOP_ADDRESS - sizeof(can_port_t)), 
                "can1 outside addressable range for the CAN registers." );

请注意,使用 struct 也会自动排序对齐.

C++相关问答推荐

是否可以在C中进行D3 D12申请?

为什么信号量为空= 0,而不是阻塞?

如何判断宏参数是否为C语言中的整型文字

C中是否有语法可以直接初始化一个常量文本常量数组的 struct 成员?

我可以在C中声明不同长度数组的数组而不带变量名吗?

文件权限为0666,但即使以超级用户身份也无法打开

如何确保在C程序中将包含uft8字符的字符串正确写入MySQL?

这个计算C中阶乘的函数正确吗?

tick.q中的Kdb+键控表语法

如何用C语言为CLI应用程序编写按键检测系统?

*S=0;正在优化中.可能是GCC 13号虫?或者是一些不明确的行为?

GETS()在C++中重复它前面的行

意外的C并集结果

分配给静态变量和动态变量的位置之间有区别吗?

如何不断地用C读取文件?

c如何传递对 struct 数组的引用,而不是设置 struct 的副本

C循环条件内的函数

无法将字符串文字分配给 C 中的字符数组

GDB 跳过动态加载器代码

可以从指针数组中的值初始化指针吗?