Since ARM opcodes are 4-bytes each, you will not be able to find 0x4000????
using a simple binary search. So we have to use a more complex approach.
Operand Search
Using Sark you can get the operand values from all the opcodes in the program and check them:
import sark
for line in sark.lines():
if not line.is_code:
continue
for operand in line.insn.operands:
if operand.type.is_imm:
if 0x40000000 <= operand.value < 0x40008000:
print 'Reference Found at x{:08X}'.format(operand.value)
But this is a lot of code, and running over the entire IDB might take a while in large firmware.
Reference Search
Since the memory-mapped peripherals are not in the firmware file itself, we need to create a new segment for it.
idaapi.add_segm(0, 0x40000000, 0x40008000, 'peripherals', 'PERIPHERALS')
# You can use more advanced APIs to make the storate sparse, and properly set all the
# properties of the segment, but this is irrelevant now.
Once the segment is created, IDA will automatically create the references to it from all relevant operands (if not, you can always force autoanalysis). After the analysis is finished, all we need to do is go over the new segment and list all references to it.
for line in sark.Segment(name='peripherals').lines:
for xref in line.xrefs_to:
print 'Found a reference at 0x{:08X}'.format(xref.frm)