Skip to content

Commit 1741eb8

Browse files
committed
Merge branch 'dev' of github.com:xwings/qiling into dev
2 parents d775c3d + 38564fd commit 1741eb8

File tree

7 files changed

+190
-70
lines changed

7 files changed

+190
-70
lines changed

examples/mcu/stm32f411_i2c_lcd.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -80,31 +80,32 @@ def render(self):
8080
print('LCD quit')
8181
pygame.quit()
8282

83-
def send(self, data):
84-
self.buf.append(data)
85-
86-
if len(self.buf) == 4:
87-
up = self.buf[0] & 0xf0
88-
lo = self.buf[3] & 0xf0
89-
cmd = up | (lo >> 4)
90-
91-
if self.buf[0] & 0x1:
92-
if self.cur_col < 16 and self.cur_row < 2:
93-
self.data[self.cur_row][self.cur_col] = cmd
94-
self.cur_col += 1
95-
self.pixels = LCD.make_screen(self.data)
96-
97-
elif cmd == 0x1:
98-
self.data = [[ord(' ') for _ in range(self.cols)] for _ in range(self.rows)]
99-
self.pixels = LCD.make_screen(self.data)
100-
101-
elif up == 0x80:
102-
self.cur_row, self.cur_col = 0, lo >> 4
103-
104-
elif up == 0xc0:
105-
self.cur_row, self.cur_col = 1, lo >> 4
106-
107-
self.buf = []
83+
def send(self, buf):
84+
for data in buf:
85+
self.buf.append(data)
86+
87+
if len(self.buf) == 4:
88+
up = self.buf[0] & 0xf0
89+
lo = self.buf[3] & 0xf0
90+
cmd = up | (lo >> 4)
91+
92+
if self.buf[0] & 0x1:
93+
if self.cur_col < 16 and self.cur_row < 2:
94+
self.data[self.cur_row][self.cur_col] = cmd
95+
self.cur_col += 1
96+
self.pixels = LCD.make_screen(self.data)
97+
98+
elif cmd == 0x1:
99+
self.data = [[ord(' ') for _ in range(self.cols)] for _ in range(self.rows)]
100+
self.pixels = LCD.make_screen(self.data)
101+
102+
elif up == 0x80:
103+
self.cur_row, self.cur_col = 0, lo >> 4
104+
105+
elif up == 0xc0:
106+
self.cur_row, self.cur_col = 1, lo >> 4
107+
108+
self.buf = []
108109

109110
def run(self):
110111
threading.Thread(target=self.render).start()

qiling/hw/char/stm32f4xx_usart.py

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
import ctypes
77

88
from qiling.hw.peripheral import QlPeripheral
9+
from qiling.hw.connectivity import QlConnectivityPeripheral
910
from qiling.hw.const.stm32f4xx_usart import USART_SR, USART_CR1
1011

11-
class STM32F4xxUsart(QlPeripheral):
12+
class STM32F4xxUsart(QlConnectivityPeripheral):
1213
class Type(ctypes.Structure):
1314
""" the structure available in :
1415
stm32f413xx.h
@@ -56,9 +57,6 @@ def __init__(self, ql, label, intn=None):
5657

5758
self.intn = intn
5859

59-
self.recv_buf = bytearray()
60-
self.send_buf = bytearray()
61-
6260
@QlPeripheral.debug_info()
6361
def read(self, offset: int, size: int) -> int:
6462
buf = ctypes.create_string_buffer(size)
@@ -92,33 +90,15 @@ def transfer(self):
9290
data = self.usart.DR
9391

9492
self.usart.SR |= USART_SR.TXE
95-
self.send_buf.append(data)
93+
self.send_to_user(data)
9694

9795
if not (self.usart.SR & USART_SR.RXNE):
9896
# TXE bit must had been cleared
99-
if self.recv_buf:
97+
if self.has_input():
10098
self.usart.SR |= USART_SR.RXNE
101-
self.usart.DR = self.recv_buf.pop(0)
102-
103-
104-
def send(self, data: bytes):
105-
""" send user data into USART.
106-
107-
Args:
108-
data (bytes): Input Data
109-
"""
110-
self.recv_buf += data
111-
112-
def recv(self) -> bytes:
113-
""" receive data from USART.
114-
115-
Returns:
116-
bytes: USART send buffer data
117-
"""
118-
data = bytes(self.send_buf)
119-
self.send_buf.clear()
120-
return data
99+
self.usart.DR = self.recv_from_user()
121100

101+
@QlConnectivityPeripheral.device_handler
122102
def step(self):
123103
self.transfer()
124104

qiling/hw/connectivity.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
7+
import ctypes
8+
import queue
9+
10+
from qiling.core import Qiling
11+
from qiling.hw.peripheral import QlPeripheral
12+
13+
14+
class QlConnectivityPeripheral(QlPeripheral):
15+
class Type(ctypes.Structure):
16+
""" Define the reigister fields of peripheral.
17+
18+
Example:
19+
fields_ = [
20+
('SR' , ctypes.c_uint32),
21+
('DR' , ctypes.c_uint32),
22+
('BRR' , ctypes.c_uint32),
23+
('CR1' , ctypes.c_uint32),
24+
('CR2' , ctypes.c_uint32),
25+
('CR3' , ctypes.c_uint32),
26+
('GTPR', ctypes.c_uint32),
27+
]
28+
"""
29+
_fields_ = []
30+
31+
def __init__(self, ql: Qiling, label: str, limit:int = 1):
32+
super().__init__(ql, label)
33+
34+
self.rtube = queue.Queue()
35+
self.wtube = queue.Queue()
36+
37+
self.limit = limit
38+
self.device_list = []
39+
40+
def has_input(self):
41+
return not self.rtube.empty()
42+
43+
def send(self, data: bytes):
44+
""" Send data into the peripheral.
45+
46+
Example:
47+
ql.hw.usart1.send(b'hello')
48+
"""
49+
50+
for byte in bytearray(data):
51+
self.rtube.put(byte)
52+
53+
def recv(self, numb:int = 4096) -> bytes:
54+
""" Receive data from peripheral
55+
56+
Example:
57+
data = ql.hw.i2c1.send()
58+
"""
59+
data = bytearray()
60+
while self.can_recv() and numb != 0:
61+
data.append(self.wtube.get())
62+
numb -= 1
63+
64+
return bytes(data)
65+
66+
def can_recv(self):
67+
return not self.wtube.empty()
68+
69+
def send_to_user(self, data: int):
70+
""" send single byte to user
71+
"""
72+
73+
self.wtube.put(data)
74+
75+
def recv_from_user(self) -> bytes:
76+
""" Read single byte from user input
77+
"""
78+
79+
return self.rtube.get()
80+
81+
def connect(self, device):
82+
if len(self.device_list) < self.limit:
83+
self.device_list.append(device)
84+
85+
@staticmethod
86+
def device_handler(func):
87+
def wrapper(self):
88+
if self.device_list and self.can_recv():
89+
data = self.recv(numb=1)
90+
for device in self.device_list:
91+
device.send(data)
92+
93+
func(self)
94+
95+
return wrapper

qiling/hw/i2c/stm32f4xx_i2c.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
import ctypes
77

88
from qiling.hw.peripheral import QlPeripheral
9+
from qiling.hw.connectivity import QlConnectivityPeripheral
910
from qiling.hw.const.stm32f4xx_i2c import I2C_CR1, I2C_CR2, I2C_SR1, I2C_SR2, I2C_DR, I2C_OAR1, I2C_OAR2
1011

1112

12-
class STM32F4xxI2c(QlPeripheral):
13+
class STM32F4xxI2c(QlConnectivityPeripheral):
1314
class Type(ctypes.Structure):
1415
""" the structure is available in :
1516
stm32f423xx.h
@@ -52,9 +53,6 @@ def __init__(self, ql, label, ev_intn=None, er_intn=None):
5253
self.ev_intn = ev_intn # event interrupt
5354
self.er_intn = er_intn # error interrupt
5455

55-
self.devices = []
56-
self.current = None
57-
5856
self.reset()
5957

6058
def reset(self):
@@ -141,21 +139,21 @@ def generate_stop(self):
141139

142140
self.i2c.SR1 |= I2C_SR1.STOPF
143141
self.i2c.SR1 &= ~I2C_SR1.ADDR
142+
144143
self.set_slave_mode()
144+
self.send_event_interrupt()
145145

146146
def send_address(self):
147147
if self.i2c.DR == self.i2c.OAR1 >> 1:
148-
for dev in self.devices:
149-
if self.i2c.DR == dev.address:
150-
self.current = dev
151148

152149
# TODO: send ACK
153150
self.i2c.SR1 |= I2C_SR1.ADDR | I2C_SR1.TXE
154151
self.send_event_interrupt()
155152

156153
def send_data(self):
157154
self.i2c.SR1 |= I2C_SR1.BTF | I2C_SR1.TXE
158-
self.current.send(self.i2c.DR)
155+
156+
self.send_to_user(self.i2c.DR)
159157
self.send_event_interrupt()
160158

161159
## I2C Status register 2 (I2C_SR2)
@@ -189,16 +187,17 @@ def is_7bit_mode(self):
189187
def fetch_device_address(self):
190188
# dual addressing mode
191189
if self.i2c.OAR2 & I2C_OAR2.ENDUAL:
192-
self.i2c.OAR1 = self.devices[0].address << 1
193-
self.i2c.OAR2 = I2C_OAR2.ENDUAL | (self.devices[1].address << 1)
190+
self.i2c.OAR1 = self.device_list[0].address << 1
191+
self.i2c.OAR2 = I2C_OAR2.ENDUAL | (self.device_list[1].address << 1)
194192

195193
# single device, 10-bit slave address
196194
elif self.i2c.OAR1 & I2C_OAR1.ADDMODE:
197-
self.i2c.OAR1 = I2C_OAR1.ADDMODE | self.devices[0].address
195+
self.i2c.OAR1 = I2C_OAR1.ADDMODE | self.device_list[0].address
198196

199197
# single device, 7-bit slave address
200198
else:
201-
self.i2c.OAR1 = self.devices[0].address << 1
199+
self.i2c.OAR1 = self.device_list[0].address << 1
202200

203-
def connect(self, dev):
204-
self.devices.append(dev)
201+
@QlConnectivityPeripheral.device_handler
202+
def step(self):
203+
pass

qiling/hw/spi/stm32f4xx_spi.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#
55

66
import ctypes
7+
78
from qiling.hw.peripheral import QlPeripheral
9+
from qiling.hw.connectivity import QlConnectivityPeripheral
810
from qiling.hw.const.stm32f4xx_spi import SPI_CR1, SPI_CR2, SPI_SR, SPI_CRCPR, SPI_I2SCFGR, SPI_I2SPR
911

1012

11-
class STM32F4xxSpi(QlPeripheral):
13+
class STM32F4xxSpi(QlConnectivityPeripheral):
1214
class Type(ctypes.Structure):
1315
""" the structure available in :
1416
stm32f413xx.h
@@ -99,10 +101,12 @@ def write(self, offset: int, size: int, value: int):
99101
ctypes.memmove(ctypes.addressof(self.spi) + offset, data, size)
100102

101103
if self.in_field(self.struct.DR, offset, size):
102-
self.send_data()
104+
self.spi.SR |= SPI_SR.RXNE
105+
self.send_to_user(self.spi.DR)
103106

104107
def send_interrupt(self):
105108
self.ql.hw.nvic.set_pending(self.intn)
106109

107-
def send_data(self):
108-
self.spi.SR |= SPI_SR.RXNE
110+
@QlConnectivityPeripheral.device_handler
111+
def step(self):
112+
pass

qiling/hw/timer/stm32f4xx_rtc.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44
#
55

6+
import time
67
import ctypes
8+
79
from qiling.hw.peripheral import QlPeripheral
10+
from qiling.hw.const.stm32f4xx_rtc import RTC_TR, RTC_ISR
811

912

1013
class STM32F4xxRtc(QlPeripheral):
@@ -99,5 +102,27 @@ def read(self, offset: int, size: int) -> int:
99102

100103
@QlPeripheral.debug_info()
101104
def write(self, offset: int, size: int, value: int):
105+
if offset == self.struct.ISR.offset:
106+
for bitmask in [
107+
RTC_ISR.TAMP1F,
108+
RTC_ISR.TSOVF,
109+
RTC_ISR.TSF,
110+
RTC_ISR.WUTF,
111+
RTC_ISR.ALRBF,
112+
RTC_ISR.ALRAF,
113+
RTC_ISR.RSF
114+
]:
115+
if value & bitmask == 0:
116+
self.rtc.ISR &= ~bitmask
117+
118+
self.rtc.ISR = (self.rtc.ISR & ~RTC_ISR.INIT) | (value & RTC_ISR.INIT)
119+
return
120+
102121
data = (value).to_bytes(size, 'little')
103-
ctypes.memmove(ctypes.addressof(self.rtc) + offset, data, size)
122+
ctypes.memmove(ctypes.addressof(self.rtc) + offset, data, size)
123+
124+
def step(self):
125+
if self.rtc.ISR & RTC_ISR.INIT:
126+
self.rtc.ISR |= RTC_ISR.INITF
127+
128+
self.rtc.ISR |= RTC_ISR.RSF

qiling/hw/utils/bcd.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
7+
def byte2bcd(value):
8+
bcdhigh = 0
9+
while value >= 10:
10+
bcdhigh += 1
11+
value -= 10
12+
13+
return (bcdhigh << 4) | value
14+
15+
def bcd2byte(value):
16+
return ((value & 0xF0) >> 0x4) * 10 + (value & 0xf)

0 commit comments

Comments
 (0)