I bought a camera board with 2.8 inch TFT LCD and STM32 on eBay for 50 bucks some time ago. The primary project was put aside after I lost my initial excitement and motivation. After almost a year I was organizing libraries from ST for STM32 for some other purposes. I came across GUI library and remembered that I have the board laying around and decided to test the GUI library.
STM32 camera board (SWD debugging; I rewired the uSD soon after I bought it) |
Circle on functional LCD at the end (original FW displayed the picture from camera) |
LCD connection - it is a 37pin connector |
Soon I discovered that there are no usable markings for the LCD. I got the schematic from the seller and the demo project sources which were zipped in password protected archive. Nothing found with Google had any LCD type information. I had no way to determine how to set up the communication with the LCD. I didn't decide to query the seller for the password due to his lag in replying - I waited a week to get the mentioned files when I bought the board.
I assumed that the design is based on a evaluation board from ST. There are drives in ST libraries for the LCDs that ST uses on their boards.
Luckily I still have the original firmware (binary file only) to see how the LCD is used. I have programmed it and set up my debugger (winIDEA - I use iSystem emulator) to break on access to registers for the port to which LCD was connected. Fortunately only one port is used for LCD (PORTB). After each RUN the application stopped on each IO port signal change and I could read the signals values.
Watchpoint breakpoints setup in winIDEA |
Port registers display in winIDEA |
Obtained values exposed the LCD initialization sequence from the ST library for SPFD5408.
Ptyhon script:
import isystem.connect as ic from isystem.connect import IConnectDebug as ICDebug def toHEX8(val): return '0x{0:02X}'.format(val) def toDEC(val): return '{0: 3d}'.format(val) class LCDInterafceValues: def __init__(self): self.data = 0 def setNewValues(self, pinsValues): self.data = pinsValues def isnCS(self): return (self.data & (1<<12)) != 0 def isRS(self): return (self.data & (1<<13)) != 0 def isnWR(self): return (self.data & (1<<14)) != 0 def isnRD(self): return (self.data & (1<<15)) != 0 def getnCS(self): if (self.data & (1<<12)) != 0: return 1 else: return 0 def getRS(self): if (self.data & (1<<13)) != 0: return 1 else: return 0 def getnWR(self): if (self.data & (1<<14)) != 0: return 1 else: return 0 def getnRD(self): if (self.data & (1<<15)) != 0: return 1 else: return 0 def getData(self): return self.data & 0xFF def printHeader(self): print "CS RS RD WR data" def printLevels(self): if self.isnCS(): print "# ", else: print "| ", if self.isRS(): print "# ", else: print "| ", if self.isnRD(): print "# ", else: print "| ", if self.isnWR(): print "# ", else: print "| ", print toHEX8(self.getData()), print toDEC(self.getData()) cmgr = ic.ConnectionMgr() # Create a connection manager cmgr.connectMRU() # Connect to the last used instance of winIDEA debug = ic.CDebugFacade(cmgr) # Create a debug object for the connected winIDEA debug.reset() # Reset CPU pv = LCDInterafceValues() # Create a value parser helper pv.printHeader() # Watchpoints have already been set in dialogs in winIDEA # Just run until a watchpoint is hit, then read the IO levels while True: debug.run() # Run the CPU debug.waitUntilStopped() # Do nothing while the CPU is running # Evaluate expression. Any C expression with firmware variables would be valid here. # '@' prefix tells winIDEA to evaluate (read from memory) a peripheral register. PortBPins = debug.evaluate(ICDebug.fMonitor , "@GPIOB_IDR").getInt() pv.setNewValues(PortBPins); # Give the IO port value to helper pv.printLevels() # Display values |
CS RS RD WR data
# # # # 0x12 18
# # # # 0x12 18
# # # # 0x12 18
# # # # 0x12 18
# # # # 0x12 18
# | # # 0x12 18
| | # # 0x12 18
| | # | 0x12 18
| | # # 0x00 0
| | # | 0x00 0
| | # # 0xE3 227
# | # # 0xE3 227
# | # # 0xE3 227
# # # # 0xE3 227
| # # # 0xE3 227
| # # | 0xE3 227
| # # # 0x30 48
| # # | 0x30 48
| # # # 0x08 8
# # # # 0x08 8
# # # # 0x08 8
# | # # 0x08 8
| | # # 0x08 8
| | # | 0x08 8
| | # # 0x00 0
| | # | 0x00 0
| | # # 0xE7 231
# | # # 0xE7 231
# | # # 0xE7 231
# # # # 0xE7 231
| # # # 0xE7 231
| # # | 0xE7 231
| # # # 0x00 0
| # # | 0x00 0
| # # # 0x12 18
# # # # 0x12 18
# # # # 0x12 18
# | # # 0x12 18
| | # # 0x12 18
| | # | 0x12 18
| | # # 0x00 0
| | # | 0x00 0
| | # # 0xEF 239
# | # # 0xEF 239
# | # # 0xEF 239
# # # # 0xEF 239
| # # # 0xEF 239
| # # | 0xEF 239
| # # # 0x12 18
| # # | 0x12 18
| # # # 0x31 49
# # # # 0x31 49
# # # # 0x31 49
No comments:
Post a Comment