STM32MP157A的IRQ流程
时间: 2024-04-02 19:34:07 浏览: 55
STM32MP157A是一款基于Cortex-A7和Cortex-M4内核的双核处理器,因此其IRQ流程也分为两种:Cortex-A7核的IRQ流程和Cortex-M4核的IRQ流程。
对于Cortex-A7核,其IRQ流程如下:
1. 当外部中断信号到来时,中断控制器(GIC)会将中断信号转发给Cortex-A7核。
2. Cortex-A7核会根据中断类型和优先级确定要执行的中断处理程序。
3. Cortex-A7核会将处理器状态保存到堆栈中,并跳转到中断处理程序的入口地址开始执行中断处理程序。
4. 中断处理程序会根据需要进行中断处理,处理完成后,将处理器状态恢复并返回到中断发生前的状态。
对于Cortex-M4核,其IRQ流程如下:
1. 当外部中断信号到来时,中断控制器(NVIC)会将中断信号转发给Cortex-M4核。
2. Cortex-M4核会根据中断类型和优先级确定要执行的中断处理程序。
3. Cortex-M4核会将处理器状态保存到堆栈中,并跳转到中断处理程序的入口地址开始执行中断处理程序。
4. 中断处理程序会根据需要进行中断处理,处理完成后,将处理器状态恢复并返回到中断发生前的状态。
需要注意的是,Cortex-A7核和Cortex-M4核之间可以通过共享内存进行数据交换和通信,因此中断处理程序可以在两个核之间进行协同处理。
相关问题
STM32MP157A上MFRC522驱动代码
以下是在STM32MP157A上MFRC522的驱动代码。需要注意的是,该代码是在Linux环境下运行的,因此需要使用Linux的GPIO库进行GPIO操作。
```c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
// GPIO pins used for the MFRC522
#define MFRC522_RST_PIN 114
#define MFRC522_IRQ_PIN 115
// MFRC522 commands
#define MFRC522_CMD_IDLE 0x00
#define MFRC522_CMD_CALCCRC 0x03
#define MFRC522_CMD_TRANSMIT 0x04
#define MFRC522_CMD_RECEIVE 0x08
#define MFRC522_CMD_TRANSCEIVE 0x0C
#define MFRC522_CMD_AUTHENT 0x0E
#define MFRC522_CMD_SOFTRESET 0x0F
// MFRC522 registers
#define MFRC522_REG_COMMAND 0x01
#define MFRC522_REG_COMMIEN 0x02
#define MFRC522_REG_DIVIEN 0x03
#define MFRC522_REG_COMMIRQ 0x04
#define MFRC522_REG_DIVIRQ 0x05
#define MFRC522_REG_ERROR 0x06
#define MFRC522_REG_STATUS1 0x07
#define MFRC522_REG_STATUS2 0x08
#define MFRC522_REG_FIFO_DATA 0x09
#define MFRC522_REG_FIFO_LEVEL 0x0A
#define MFRC522_REG_WATERLEVEL 0x0B
#define MFRC522_REG_CONTROL 0x0C
#define MFRC522_REG_BITFRAMING 0x0D
#define MFRC522_REG_COLL 0x0E
#define MFRC522_REG_MODE 0x11
#define MFRC522_REG_TX_MODE 0x12
#define MFRC522_REG_RX_MODE 0x13
#define MFRC522_REG_TX_CONTROL 0x14
#define MFRC522_REG_TX_AUTO 0x15
#define MFRC522_REG_TX_SELL 0x16
#define MFRC522_REG_RX_SELL 0x17
#define MFRC522_REG_RX_THRESHOLD 0x18
#define MFRC522_REG_DEMOD 0x19
#define MFRC522_REG_MF_TX 0x1C
#define MFRC522_REG_MF_RX 0x1D
#define MFRC522_REG_SERIALSPEED 0x1F
#define MFRC522_REG_CRC_RESULT_MSB 0x21
#define MFRC522_REG_CRC_RESULT_LSB 0x22
#define MFRC522_REG_MOD_WIDTH 0x24
#define MFRC522_REG_RF_CFG 0x26
#define MFRC522_REG_GS_N 0x27
#define MFRC522_REG_CWGS_PREG 0x28
#define MFRC522_REG_MODGS_PREG 0x29
#define MFRC522_REG_T_MODE 0x2A
#define MFRC522_REG_T_PRESCALER 0x2B
#define MFRC522_REG_T_RELOAD_MSB 0x2C
#define MFRC522_REG_T_RELOAD_LSB 0x2D
#define MFRC522_REG_T_COUNTER_VALUE_MSB 0x2E
#define MFRC522_REG_T_COUNTER_VALUE_LSB 0x2F
struct mfrc522 {
struct spi_device *spi;
unsigned int irq_gpio;
unsigned int rst_gpio;
};
static inline int mfrc522_send_command(struct mfrc522 *mfrc, u8 cmd, u8 *data, size_t len)
{
int ret;
u8 buffer[64];
buffer[0] = cmd;
if (len > 0) {
memcpy(buffer + 1, data, len);
}
ret = spi_write(mfrc->spi, buffer, len + 1);
if (ret < 0) {
dev_err(&mfrc->spi->dev, "Error sending command %02x: %d\n", cmd, ret);
return ret;
}
return 0;
}
static inline int mfrc522_receive_data(struct mfrc522 *mfrc, u8 *data, size_t len)
{
int ret;
u8 buffer[64];
ret = spi_read(mfrc->spi, buffer, len);
if (ret < 0) {
dev_err(&mfrc->spi->dev, "Error receiving data: %d\n", ret);
return ret;
}
memcpy(data, buffer, len);
return 0;
}
static inline int mfrc522_reset(struct mfrc522 *mfrc)
{
gpio_set_value(mfrc->rst_gpio, 0);
udelay(100);
gpio_set_value(mfrc->rst_gpio, 1);
udelay(100);
return 0;
}
static inline int mfrc522_init(struct mfrc522 *mfrc)
{
int ret;
u8 version;
u8 buffer[25];
// Reset the MFRC522
mfrc522_reset(mfrc);
// Read the MFRC522 version
ret = mfrc522_send_command(mfrc, 0x00, NULL, 0);
if (ret < 0) {
return ret;
}
ret = mfrc522_receive_data(mfrc, &version, 1);
if (ret < 0) {
return ret;
}
dev_info(&mfrc->spi->dev, "MFRC522 version: %d\n", version);
// Configure the MFRC522
ret = mfrc522_send_command(mfrc, MFRC522_CMD_SOFTRESET, NULL, 0);
if (ret < 0) {
return ret;
}
mdelay(100);
// Configure the timer
buffer[0] = 0xA0; // TPrescaler = 0xA0
buffer[1] = 0x03; // TReloadVal = 0x3E8
ret = mfrc522_send_command(mfrc, MFRC522_REG_T_MODE, buffer, 2);
if (ret < 0) {
return ret;
}
// Configure the TX/RX registers
buffer[0] = 0x40; // 100% ASK modulation
buffer[1] = 0x3F; // Maximum RX waiting time
buffer[2] = 0x03; // Enable MIFARE Crypto1
ret = mfrc522_send_command(mfrc, MFRC522_REG_TX_MODE, buffer, 3);
if (ret < 0) {
return ret;
}
buffer[0] = 0x08; // Transceive FIFO level is 8
ret = mfrc522_send_command(mfrc, MFRC522_REG_RX_MODE, buffer, 1);
if (ret < 0) {
return ret;
}
// Configure the ModWidthReg
buffer[0] = 0x26; // ModWidthReg = 0x26
ret = mfrc522_send_command(mfrc, MFRC522_REG_MOD_WIDTH, buffer, 1);
if (ret < 0) {
return ret;
}
dev_info(&mfrc->spi->dev, "MFRC522 initialized\n");
return 0;
}
static irqreturn_t mfrc522_irq_handler(int irq, void *dev_id)
{
struct mfrc522 *mfrc = (struct mfrc522 *) dev_id;
// TODO: handle the IRQ
return IRQ_HANDLED;
}
static int mfrc522_probe(struct spi_device *spi)
{
int ret;
struct mfrc522 *mfrc;
// Allocate memory for the MFRC522 device
mfrc = devm_kzalloc(&spi->dev, sizeof(*mfrc), GFP_KERNEL);
if (mfrc == NULL) {
dev_err(&spi->dev, "Error allocating memory\n");
return -ENOMEM;
}
// Save a reference to the SPI device
mfrc->spi = spi;
// Set up the GPIO pins
mfrc->irq_gpio = MFRC522_IRQ_PIN;
ret = devm_gpio_request(&spi->dev, mfrc->irq_gpio, "MFRC522 IRQ");
if (ret < 0) {
dev_err(&spi->dev, "Error requesting IRQ GPIO pin: %d\n", ret);
return ret;
}
gpio_direction_input(mfrc->irq_gpio);
mfrc->rst_gpio = MFRC522_RST_PIN;
ret = devm_gpio_request(&spi->dev, mfrc->rst_gpio, "MFRC522 RST");
if (ret < 0) {
dev_err(&spi->dev, "Error requesting RST GPIO pin: %d\n", ret);
return ret;
}
gpio_direction_output(mfrc->rst_gpio, 1);
// Initialize the MFRC522
ret = mfrc522_init(mfrc);
if (ret < 0) {
dev_err(&spi->dev, "Error initializing MFRC522: %d\n", ret);
return ret;
}
// Register the IRQ handler
ret = devm_request_irq(&spi->dev, gpio_to_irq(mfrc->irq_gpio), mfrc522_irq_handler,
IRQF_TRIGGER_FALLING, "MFRC522", mfrc);
if (ret < 0) {
dev_err(&spi->dev, "Error registering IRQ: %d\n", ret);
return ret;
}
return 0;
}
static int mfrc522_remove(struct spi_device *spi)
{
// TODO: cleanup
return 0;
}
static const struct of_device_id mfrc522_of_match[] = {
{ .compatible = "mfrc522", },
{},
};
MODULE_DEVICE_TABLE(of, mfrc522_of_match);
static struct spi_driver mfrc522_driver = {
.driver = {
.name = "mfrc522",
.of_match_table = mfrc522_of_match,
},
.probe = mfrc522_probe,
.remove = mfrc522_remove,
};
module_spi_driver(mfrc522_driver);
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("MFRC522 driver for STM32MP157A");
MODULE_LICENSE("GPL");
```
需要注意的是,以上代码仅供参考,实际应用中可能需要进行更多的修改和优化。
STM32MP157A上MFRC522外设设备树如何写
MFRC522是一种RFID读卡器,可以通过SPI接口与STM32MP157A进行通信。在设备树中,需要添加以下节点:
```
&spi3 {
status = "okay";
pinctrl-0 = <&spi3_pins_a>;
cs-gpios = <&gpioz 11 GPIO_ACTIVE_LOW>;
num-chip-selects = <1>;
mfrc522@0 {
compatible = "nxp,mfrc522";
reg = <0>;
spi-max-frequency = <1000000>;
interrupt-parent = <&gpioz>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpioz 10 GPIO_ACTIVE_HIGH>;
};
};
```
解释一下这个节点的内容:
- `&spi3`:SPI3控制器节点
- `status`:设备状态,设置为“okay”表示启用该设备
- `pinctrl-0`:SPI3的引脚配置,这里使用了一个名为“spi3_pins_a”的引脚配置
- `cs-gpios`:片选引脚所使用的GPIO引脚,这里使用了GPIOZ11
- `num-chip-selects`:片选数量,这里只有一个
- `mfrc522@0`:MFRC522读卡器节点,通过SPI与STM32MP157A通信
- `compatible`:设备的兼容性,这里使用了NXP公司的mfrc522驱动程序
- `reg`:设备地址,这里设置为0
- `spi-max-frequency`:SPI总线的最大时钟频率,这里设置为1MHz
- `interrupt-parent`:中断引脚所使用的GPIO控制器,这里使用了GPIOZ
- `interrupts`:中断引脚号,这里使用了GPIOZ9
- `reset-gpios`:MFRC522的复位引脚,这里使用了GPIOZ10
需要注意的是,以上节点中的GPIO引脚的编号和方向需要根据实际硬件电路进行配置。
阅读全文