克里斯,
我不是 Cortex-M 专家,所以你的 MMV。但是根据您上面的描述,您正在尝试使用一种非常复杂的方式来修改外围寄存器中的单个位。通常有两种处理方式:
使用一组宏(我最熟悉的)。这将减少您在每次读/写引脚时调用函数的空间和 CPU 时间开销,因为宏在编译期间直接转换为所需的确切值/操作。
改用 PF4 寄存器的位带地址(从未使用过 Cortex-M)。这似乎是您的架构的首选方式。
根据 ARM Cortex-M4 技术参考手册第 3.4 节,您可以使用位带别名地址来修改 PF4 位。有关其工作原理的详细信息,请参阅 TRM 的第 3.7 节。
根据您上面的代码,PF4 是地址 0x40025040 中的第 4 位,位带公式给出(取自合理使用下的 TRM):
• bit_band_base 是别名区域的起始地址。 (0x42000000)
• byte_offset 是位带区域中包含目标位的字节数。 (0x00025040)
• bit_number 是目标位的位位置,0 到 7。 (0x4)
bit_word_offset = (byte_offset x 32) + (bit_number × 4)
bwo = 0x25040* 0x20 + 0x4 * 0x4 = 0x004A0810
bit_word_addr = bit_band_base + bit_word_offset
bwa = 0x42000000 + 0x4A0810 = 0x424A0810
• bit_word_offset 是目标位在位带内存区域中的位置。
• bit_word_addr 是别名内存区域中的字的地址,它映射到
目标位。
所以
*(volatile unsigned long *)0x424A0810 = 0x1;
等同于写作
*MyOutput |= 0x10;
如果你真的想走使用函数直接写的路线,试试这个(仅限PF31,如果PF需要高于31,实现留给读者);此代码包含基于 PC 的测试 #define,因此您可以在命令行上使用 gcc 对其进行编译。
#include <inttypes.h>
#include <stdio.h>
#define PC_TESTING 1
#if PC_TESTING
unsigned long FAKE_PFBASE;
#define PFBASE &FAKE_PFBASE
#else
#define PFBASE (volatile unsigned long *) 0x40025040
#endif
#define SUCCESS 0
#define ERROR_INVALID_PIN -1
#define ERROR_INVALID_STATE -2
typedef enum {OFF = 0, ON} ONOFF_t;
typedef enum { PF0 = 0, PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12, PF13, PF14, PF15, PF16, PF17, PF18, PF19, PF20, PF21, PF22, PF23, PF24, PF25, PF26, PF27, PF28, PF29, PF30, PF31 } PIN_t;
int SetOutput( PIN_t PIN, ONOFF_t ONOFF)
{
uint32_t mask, value;
// Implementing more than 32 pins is exercise for the reader
if (PIN > 31)
return ERROR_INVALID_PIN;
// In case someone did something wrong
if (ONOFF != OFF && ONOFF != ON)
return ERROR_INVALID_STATE;
//Broken into separate steps for ease of reading
//Select the bit of interest
mask = 1 << PIN;
//Clear the bit of interest
value = *PFBASE & ~mask; //~ is a bit-wise invert. 0x0000 0010 becomes 0xFFFF FFEF
//Set the bit of interest if that is requested
if( ON == ONOFF)
value |= mask;
*PFBASE = value;
return SUCCESS;
}
int main()
{
int success = 0;
FAKE_PFBASE = 0l;
success = SetOutput( PF4, ON);
printf (" Success = %d, *PFBASE = 0x%08x\n", success, *PFBASE );
success = SetOutput(PF0, ON );
printf (" Success = %d, *PFBASE = 0x%08x\n", success, *PFBASE );
success = SetOutput(PF0, OFF );
printf (" Success = %d, *PFBASE = 0x%08x\n", success, *PFBASE );
//Error handling left to reader
success = SetOutput(33, OFF );
printf (" Success = %d, *PFBASE = 0x%08x\n", success, *PFBASE );
success = SetOutput(PF2, 2 );
printf (" Success = %d, *PFBASE = 0x%08x\n", success, *PFBASE );
return 0;
}
示例输出:
$ ./a.out
Success = 0, *PFBASE = 0x00000010
Success = 0, *PFBASE = 0x00000011
Success = 0, *PFBASE = 0x00000010
Success = -1, *PFBASE = 0x00000010
Success = -2, *PFBASE = 0x00000010