Trying to access the sensor's registers using memory-mapped I/O in a flat memory model

Hi, I'm working on a small embedded system project using x86-64 assembly on an Intel Atom E3845 microprocessor. The program aims to read temperature data from an Adafruit BMP280 sensor connected with I2C
Solution:
No more error message, it worked:
```global _start section .text _start:...
Jump to solution
9 Replies
Marvee Amasi
Marvee Amasi10mo ago
I'm trying to access the sensor's registers using memory-mapped I/O in a flat memory model, and I'm encountering a segmentation fault when I run the program, saying:
Segmentation fault (core dumped)
Segmentation fault (core dumped)
My relevant code :
global _start

section .text
_start:
; I2C communication registers set up...

; base address for BMP280 registers setting
movw $0x10000, %ax ; base address setting

; reading temp data register
movb (%rax), %bl ; reading byte from temp register

; processing my temp data...

movb $1, %eax
int $0x80 ; exit system call

section .data
; data segment...
message db "Temp data read", 0x0
global _start

section .text
_start:
; I2C communication registers set up...

; base address for BMP280 registers setting
movw $0x10000, %ax ; base address setting

; reading temp data register
movb (%rax), %bl ; reading byte from temp register

; processing my temp data...

movb $1, %eax
int $0x80 ; exit system call

section .data
; data segment...
message db "Temp data read", 0x0
Marvee Amasi
Marvee Amasi10mo ago
Can you help me identify the cause of the segmentation fault and suggest appropriate methods to access the BMP280 sensor registers in x86-64 assembly, considering the limitations of a flat memory model? Additionally, are there recommended practices or libraries for I2C sensor interaction on Intel Atom processors in a Linux environment? @Helper
Enthernet Code
Enthernet Code10mo ago
Hi @Marvee Amasi , it looks like you’re encountering a segmentation fault due to trying to access memory that your program doesn’t have permission to access.
Marvee Amasi
Marvee Amasi10mo ago
What am I doing wrong?
Enthernet Code
Enthernet Code10mo ago
Incorrect Use of Memory-Mapped I/O in User Space and Incorrect Register Access
Marvee Amasi
Marvee Amasi10mo ago
Yup @Enthernet Code I had to implement memory-mapped I/O using the mmap system call
Enthernet Code
Enthernet Code10mo ago
@Marvee Amasi Accessing hardware registers directly through memory-mapped I/O in user-space is not allowed in modern operating systems like Linux. This is due to the protection mechanisms in place to prevent unauthorized access to hardware resources.The segmentation fault occurs because the memory address 0x10000 you are trying to access is not allocated to your program, and hence, the operating system prevents access.
Solution
Marvee Amasi
Marvee Amasi10mo ago
No more error message, it worked:
global _start

section .text
_start:
; I2C communication registers set up...

;
mov $0, %eax ; opening system call
mov $0xFD, %ebx ; open file descriptor for /dev/mem
mov $0, %ecx ;
mov $_dev_mem, %edx ;
int $0x80 ; system call

; checking for successful open
cmp $0, %eax
jl .open_failed ; if fails

; Mapping my memory region
mov $9, %eax ; mmap system call
mov %eax, %ebx ; file descriptor from open
mov $0x1000, %ecx ;
mov $0x1000, %edx ;
mov $0x1, %esi ; prot - PROT_READ
mov $0x0, %edi ; flags
mov $0, %ebp ; offset
int $0x80 ; system call

; if mapping is successful
cmp $0, %eax
jl .mmap_failed ; if mapping fails

; accessing registers using the mapped address
movb (%rax), %bl ; reading byte from temp register

; processing my temp data...

; Unmapping memory region before exiting
mov $17, %eax ; munmap system call
mov %eax, %ebx ; mapped address
mov $0x1000, %ecx ;
int $0x80 ; system call

mov $1, %eax
int $0x80 ; exit system call

.open_failed:
; Handle error message
...

.mmap_failed:
; Handle mapping error
...

section .data
_dev_mem: db "/dev/mem", 0x0 ;
message db "Temp data read", 0x0
global _start

section .text
_start:
; I2C communication registers set up...

;
mov $0, %eax ; opening system call
mov $0xFD, %ebx ; open file descriptor for /dev/mem
mov $0, %ecx ;
mov $_dev_mem, %edx ;
int $0x80 ; system call

; checking for successful open
cmp $0, %eax
jl .open_failed ; if fails

; Mapping my memory region
mov $9, %eax ; mmap system call
mov %eax, %ebx ; file descriptor from open
mov $0x1000, %ecx ;
mov $0x1000, %edx ;
mov $0x1, %esi ; prot - PROT_READ
mov $0x0, %edi ; flags
mov $0, %ebp ; offset
int $0x80 ; system call

; if mapping is successful
cmp $0, %eax
jl .mmap_failed ; if mapping fails

; accessing registers using the mapped address
movb (%rax), %bl ; reading byte from temp register

; processing my temp data...

; Unmapping memory region before exiting
mov $17, %eax ; munmap system call
mov %eax, %ebx ; mapped address
mov $0x1000, %ecx ;
int $0x80 ; system call

mov $1, %eax
int $0x80 ; exit system call

.open_failed:
; Handle error message
...

.mmap_failed:
; Handle mapping error
...

section .data
_dev_mem: db "/dev/mem", 0x0 ;
message db "Temp data read", 0x0
Had to dig deep with some resources using mmap
Marvee Amasi
Marvee Amasi10mo ago
Thanks man @Enthernet Code

Did you find this page helpful?