通过内存映射访问UART2时出现“总线错误”(mmap函数)

时间:2019-07-03 05:54:07

标签: memory-management linux-device-driver embedded-linux mmap uart

我正在嵌入式Linux板上工作。

根据我们的要求,需要通过内存映射而不是串行字符文件(/ dev / ttymxc1)访问UART2。当我通过mmap()函数访问UART1时,它工作正常。但是,当我尝试通过mmap()函数访问UART2时,出现“总线错误”。我无法理解发生了什么,因为UART1在工作,而UART2在工作。 请找到我的源代码,并在这里建议我任何错误。

#include <signal.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <time.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <string.h>

 typedef unsigned int            uint32_t;

 #define READ_REG32(reg)         ( *((volatile uint32_t *) (reg)) )
 #define WRITE_REG32(value,reg)  ( *((volatile uint32_t *) (reg)) = value )

 #define ALLOC_SIZE              (1024)  
 //#define UART1_BASE        0x02020000
 #define UART2_BASE        0x021E8000

 /* Register definitions */
 #define URXD  0x0  /* Receiver Register */
 #define UTXD  0x40 /* Transmitter Register */
 #define UCR1  0x80 /* Control Register 1 */
 #define UCR2  0x84 /* Control Register 2 */
 #define UCR3  0x88 /* Control Register 3 */
 #define UCR4  0x8c /* Control Register 4 */
 #define UFCR  0x90 /* FIFO Control Register */
 #define USR1  0x94 /* Status Register 1 */
 #define USR2  0x98 /* Status Register 2 */
 #define UESC  0x9c /* Escape Character Register */
 #define UTIM  0xa0 /* Escape Timer Register */
 #define UBIR  0xa4 /* BRM Incremental Register */
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
 #define UTS   0xb4 /* UART Test Register (mx31) */

 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
 #define  URXD_ERR        (1<<14)
 #define  URXD_OVRRUN     (1<<13)
 #define  URXD_FRMERR     (1<<12)
 #define  URXD_BRK        (1<<11)
 #define  URXD_PRERR      (1<<10)
 #define  URXD_RX_DATA    (0xFF)
 #define  UCR1_ADEN       (1<<15) /* Auto dectect interrupt */
 #define  UCR1_ADBR       (1<<14) /* Auto detect baud rate */
 #define  UCR1_TRDYEN     (1<<13) /* Transmitter ready interrupt enable */
 #define  UCR1_IDEN       (1<<12) /* Idle condition interrupt */
 #define  UCR1_RRDYEN     (1<<9)     /* Recv ready interrupt enable */
 #define  UCR1_RDMAEN     (1<<8)     /* Recv ready DMA enable */
 #define  UCR1_IREN       (1<<7)     /* Infrared interface enable */
 #define  UCR1_TXMPTYEN   (1<<6)     /* Transimitter empty interrupt enable */
 #define  UCR1_RTSDEN     (1<<5)     /* RTS delta interrupt enable */
 #define  UCR1_SNDBRK     (1<<4)     /* Send break */
 #define  UCR1_TDMAEN     (1<<3)     /* Transmitter ready DMA enable */
 #define  UCR1_UARTCLKEN  (1<<2)     /* UART clock enabled */
 #define  UCR1_DOZE       (1<<1)     /* Doze */
 #define  UCR1_UARTEN     (1<<0)     /* UART enabled */

 #define  UTS_FRCPERR     (1<<13) /* Force parity error */
 #define  UTS_LOOP        (1<<12) /* Loop tx and rx */
 #define  UTS_TXEMPTY     (1<<6)     /* TxFIFO empty */
 #define  UTS_RXEMPTY     (1<<5)     /* RxFIFO empty */
 #define  UTS_TXFULL     (1<<4)     /* TxFIFO full */
 #define  UTS_RXFULL     (1<<3)     /* RxFIFO full */
 #define  UTS_SOFTRST     (1<<0)     /* Software reset */

 void uart_putc(void *base, int ch)
 {
     WRITE_REG32(ch, base + UTXD);
     /* Wait until sent */
     while (!(READ_REG32(base + UTS) & UTS_TXEMPTY));
 }

 static void write_on_uart()  
 {  
         int fd=0;
         void *map_base;

         fd = open("/dev/mem", O_RDWR | O_SYNC);  

         if (fd) {  
             printf("Success to open /dev/mem fd=%08x\n", fd);  
         }  
         else {  
             printf("Fail to open /dev/mem fd=%08x\n", fd);    
         }  

         map_base = mmap(0, ALLOC_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, UART2_BASE);

         if ((int)map_base == -1)
         {
            printf("Fail to create a base address \n");
            return;
          }

          printf("map_base: %p\n", map_base);

         for (int i = 0 ; i < 10; i++)
         uart_putc(map_base,'S');

         close(fd);
         munmap(map_base, ALLOC_SIZE);

 }

 int main(int argc, char **argv)
 {
          write_on_uart();
          return 0;
 }

获取错误:

/ dev / mem已打开。[4243.747456]未处理的错误:在0x76fdd000处的非linefetch(0x1008)上发生外部异常终止 [4243.756248] pgd = 950c4000 [4243.759060] [76fdd000] * pgd = 94736835,* pte = 021e8703,* ppte = 021e8e33

映射到地址0x76fdd000的内存。 总线错误(核心已转储)

0 个答案:

没有答案