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

Good luck.