Introduction
For STM, the common ways to manipulate low hardware are HAL and memory/register access. For third-party hardwares, there are no HAL support and we have to do memory/register access. For example, for ili9341 TFT LCD, the driving code looks like the following:
// Define the memory model for IO/Register access.typedef struct { __IO uint16_t reg; __IO uint16_t mem;} LCD_TypeDef;#define LCD_BASE ((uint32_t)(0x6C000000 | 0x000007FE))#define LCD ((LCD_TypeDef *)LCD_BASE)// Write commands by assignment.// NOTE: If people know some about FPGA will// figure out that they are much similar.INLINE void lcd_cmd(uint16_t cmd) { LCD->reg = cmd;}// Write data by assignment.INLINE void lcd_data(uint16_t dat) { LCD->mem = dat;}INLINE void lcd_cmd_data(uint16_t cmd, uint16_t data) { LCD->reg = cmd; LCD->mem = data;}
Personally, I prefer to C++. So the C++ style code will be:
#include <stm32f1xx.h>namespace igame { template<typename T, const uint32_t ADDR> struct IOMemory { typedef IOMemory<T, ADDR> type; typedef T val_t; typedef const T const_val_t; __IO T* __mem = reinterpret_cast<val_t *>(ADDR); }; // Input template<typename T, const uint32_t ADDR> void operator << (IOMemory<T, ADDR>& left, const uint16_t& right) { *left.__mem = right; } // Output template<typename T, const uint32_t ADDR> void operator << (const IOMemory<T, ADDR>& left, const int& right) { left << (const uint16_t&)right; } template<typename T, const uint32_t ADDR> void operator >> (const IOMemory<T, ADDR>& left, T& right) { right = *left.__mem; }} // ns
The working code should be:
namespace igame { class TFT9341 { ... private: static const uint32_t LCD_BASE_ADDR = ((uint32_t) (0x6C000000 | 0x000007FE)); const IOMemory<uint16_t, LCD_BASE_ADDR> m_reg; const IOMemory<uint16_t, LCD_BASE_ADDR + sizeof(uint16_t)> m_mem; ... public: ... uint16_t getId() { uint16_t res = 0; m_reg >> res; if (res < 0xFF || res == 0xFFFF || res == 0x9300) { m_reg << 0xD3; // Write cmd. m_mem >> res; // Output: 0x00 m_mem >> res; // Output: 0x00 m_mem >> res; // Output: 0x93 uint16_t temp = res << 8; m_mem >> res; // Output: 0x41 res |= temp; } return res; } // fn getId() void setPos(uint16_t x, uint16_t y) { m_reg << 0x2A; m_mem << (x >> 8); m_mem << (x & 0xFF); m_reg << 0x2B; m_mem << (y >> 8); m_mem << (y & 0xFF); } // fn setPos ... }; // class} // ns