乐趣区

关于c++:C-Style-IO-Access-For-STM32

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.

退出移动版