- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在为 UART(Xilinx 的 AXI UART Lite)编写我的第一个串行驱动程序。我知道内核中有一个,但我不是在嵌入式 Linux 环境中工作。
使用 the documentation和现有的引用代码,我已经实现了我的驱动程序。但是,我无法验证正在调用我的 startup
或 request_port
函数。启动函数基本上做what this does .但是,不使用我正在轮询的 IRQ。同样,我拥有的 request_port 功能非常相似 to this function .
文档指出 the startup function当端口打开时被调用一次。因为我在/dev 中确实有我期望的设备节点,所以我想我需要打开端口。在 minicom 的步骤中,我打开文件(使用 lsof 验证)。然而,我在 dmesg 中找不到任何我放在 startup
或 request_port
函数中的消息。
很抱歉延迟回复,但在发布代码之前我不得不跳过一些障碍。这是我的:
#define MAX_SUPPORTED_UARTS 1
#define DRIVER_MAJOR_NUM 243 /* local/experimental */
#define DRIVER_MINOR_NUM 0
static int request_port(struct uart_port *);
static void release_port(struct uart_port *);
static int startup(struct uart_port *);
static void shutdown(struct uart_port *);
static struct uart_ops axilite_ops = {
.release_port = release_port,
.request_port = request_port,
.startup = startup,
.shutdown = shutdown,
};
static struct uart_port axilite_ports[MAX_SUPPORTED_UARTS] = {
{
.mapbase = 0, /* determined during discovery */
.membase = 0, /* calcuated after learning mapbase */
.iotype = UPIO_MEM, /* from serial_core.c */
.irq = 0, /* currently, device doesn't use an IRQ, just polling */
.fifosize = 16, /* directly Xilinx documentation */
.ops = &axilite_ops,
.flags = UPF_FIXED_TYPE | UPF_FIXED_PORT | UPF_SPD_VHI,
.mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR, /* from uartlite.c in kernel tree */
},
};
static struct uart_driver axilite_driver = {
.owner = THIS_MODULE,
.driver_name = "axilite",
.dev_name = "ttyAUL",
.major = DRIVER_MAJOR_NUM,
.minor = DRIVER_MINOR_NUM,
.nr = MAX_SUPPORTED_UARTS,
};
static int startup(struct uart_port *pup)
{
void __iomem* pmem = pup->membase;
uint32_t ctlreg = 0;
pr_info("%s:%d entry point\n", __func__, __LINE__);
ctlreg = ioread32(CTL_REG_ADDR(pmem));
pr_info("DEBUG: %s:%d CTL Reg is 0x%08x\n",
__func__, __LINE__, ctlreg);
/* clear the FIFO's */
ctlreg |= CTL_REG_RST_TX | CTL_REG_RST_RX;
iowrite32(ctlreg, CTL_REG_ADDR(pmem));
return 0;
}
static void shutdown(struct uart_port *pup)
{
void __iomem* pmem = pup->membase;
pr_info("%s:%d entry point\n", __func__, __LINE__);
/* Using a queue from the axilite driver in the kernel */
iowrite32(0, CTL_REG_ADDR(pmem));
}
static void release_port(struct uart_port *pup)
{
pr_info("%s:%d entry point\n", __func__, __LINE__);
if (pup->membase)
iounmap(pup->membase);
pup->membase = NULL;
}
static int request_port(struct uart_port *pup)
{
int result = 0;
uint32_t bus_addr = pup->mapbase;
void __iomem* pmem = NULL;
pr_info("%s:%d mapping bus addr to virtual space\n",
__func__, __LINE__);
pmem = ioremap_nocache(bus_addr, UART_REGISTER_REGION);
if (IS_ERR_OR_NULL(pmem)) {
pr_err("%s:%d ioremap_nocache failed\n",
__func__, __LINE__);
result = PTR_ERR(pmem);
goto startup_exit;
}
pup->membase = pmem;
pr_info("%s:%d busaddr 0x%08x mapped to %p\n",
__func__, __LINE__, bus_addr, pmem);
startup_exit:
return result;
}
static int add_uart_ports(void)
{
int result = 0;
uint32_t i = 0, baseaddr = 0;
pr_info("%s:%d adding %d port(s) to the system\n",
__func__, __LINE__, uart_count);
/* calls into code which learns the base address,
* verified that it works
*/
baseaddr = get_uart_base(i);
if ((int)baseaddr == -EINVAL) {
pr_err("%s:%d Invalid index used\n", __func__, __LINE__);
result = (int)baseaddr;
goto add_ports_exit;
}
else if (0 == baseaddr) {
pr_err("%s:%d Invalid bus address encountered, port add stopped\n",
__func__, __LINE__);
result = -ENODEV;
goto add_ports_exit;
}
else
axilite_port[i].mapbase = baseaddr;
result = uart_add_one_port(&axilite_driver, &axilite_port[i]);
if (result) {
pr_err("%s:%d uart_add_one_port failed for port %d\n",
__func__, __LINE__, i);
goto add_ports_exit;
}
/* TODO think of a better way to track whether the port
* is registered. this will work for now.
*/
axilite_port[i].private_data = &uart_count;
init_stage |= UART_PORT_REGISTERED;
add_ports_exit:
return result;
}
static int add_uart_driver(void)
{
int result = 0;
pr_info("%s:%d adding the driver\n", __func__, __LINE__);
uart_count = get_uart_count();
axilite_driver.nr = (int)uart_count;
result = uart_register_driver(&axilite_driver);
if (result) {
pr_err("%s:%d uart_register_driver failed\n",
__func__, __LINE__);
goto add_driver_exit;
}
init_stage |= DRIVER_REGISTERED;
add_driver_exit:
return result;
}
编辑
我没有添加平台驱动程序。虽然这是 Xilinx 系统,但我的驱动程序不会在嵌入式 Linux 中运行。鉴于此,我认为驱动程序启动类似于 the driver for 21285 .这是错误的吗?
结束编辑
这可能是什么原因造成的?我应该做什么或检查什么?
安迪
最佳答案
在serial_core.c uart_port_startup
方法中,开头有代码:
if (uport->type == PORT_UNKNOWN)
return 1;
这就是没有调用启动方法的原因。您需要将 struct uart_port.type
设置为一个非未知值。至少它对我有用。您可能需要添加新的 PORT_ 类型或使用现有类型 - 不确定冲突。对于我的虚拟设备,这是可行的:
static struct uart_port tiny_port = {
.ops = &tiny_ops,
.type = PORT_8250,
};
关于linux - 未执行串行驱动程序启动/请求函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37058142/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!