D语言下ARM外设通用模板设计

D语言下ARM外设通用模板设计

介绍

这是一个外设寄存器读写通用设计,通过SVD文件转换的代码可以直接用来生成HAL操作的class.具体代码应用往下看~.

mculib4d的项目网站
源代码在这里

实现代码

module mculib.arch.cortex_m.peripheral;

import std.traits : isNumeric;
import std.meta : allSatisfy;

//pragma(LDC_verbose);


/**
    转换到位带区

    函数并未检查
*/
template BitBand(size_t addr,size_t bitnum) if(bitnum < 32)
{
    enum BitBand = (addr & 0xF0000000) + 0x0200_0000 + ((addr & 0x000FFFFF) << 5) + (bitnum << 2);
}

pragma(inline,true) 
size_t BitBand(size_t addr,uint bitnum)
{
    return (addr & 0xF0000000) + 0x0200_0000 + ((addr & 0x000FFFFF) << 5) + (bitnum << 2);
}



enum Access
{
    none = 0,
    read    = 1u << 0,
    write   = 1u << 1,
    clear   = 1u << 2,
    set     = 1u << 3,
    ro      = read,
    wo      = write,
    rw      = (read|write),
    rwa     = -1,
}

package template CanRead(Access v)
{
    static if(Access.read & v){
        enum CanRead = true;
    }else{
        enum CanRead = false;
    }
}

package template CanWrite(Access v)
{
    static if(Access.write & v){
        enum CanWrite = true;
    }else{
        enum CanWrite = false;
    }
}

package template CanClear(Access v)
{
    static if(Access.clear & v){
        enum CanClear = true;
    }else{
        enum CanClear = false;
    }
}

/**
    外设操作: 
*/
package(mculib) abstract class Peripheral(size_t addr,Conf)
{
    private import core.atomic;
    
    
    /// 外设起始地址
    public enum PeripheralAddress = addr;

    /// 判定位带区
    
    static if(Conf.SVDCpuName == "CM3"){
        enum IsBitBandable = true;
    }else static if(Conf.SVDCpuName == "CM4"){
        enum IsBitBandable = true;
    }else{
        enum IsBitBandable = false;
    }
    

    /// 寄存器操作
    protected abstract class Register(size_t offset,Access access)
    {
        /// 当前寄存器访问地址
        public enum size_t RegistersAddress = PeripheralAddress + offset;

        /// 寄存器访问权限
        private enum Access RegistersAccess = access;

        /// 寄存器读写类型
        private{
            static if((ubyte.sizeof*8) == Conf.SVDWidth){
                alias RegistersType = ubyte;
            }else static if((ushort.sizeof*8) == Conf.SVDWidth){
                alias RegistersType = ushort;
            }else static if((uint.sizeof*8) == Conf.SVDWidth){
                alias RegistersType = uint;
            }else{
                static assert(false, "Registers Type no sup");
            }
        }

        enum shared(RegistersType*) RegistersBase = cast(shared RegistersType*)RegistersAddress;

        static if(CanRead!RegistersAccess)
        {
            /// 寄存器读
            pragma(inline,true)
            @property static RegistersType value() 
            {
                return atomicLoad(*cast(RegistersType*)RegistersAddress);
            }
            /// 重载this
            //alias value this;

            /**
                重载数组方式查询
            */
            static RegistersType opIndex()
            {
                return value();
            }

            static RegistersType opIndex(uint v)
            {
                static if(IsBitBandable){
                    auto Bandaddr = BitBand(RegistersAddress,v);
                    return atomicLoad(*cast(RegistersType*)Bandaddr);
                }else{
                    return (value() & (1u << v));
                }
            } 
            /*
            static RegistersType opIndex(A...)(A indices) if (allSatisfy!(isNumeric, A))
            {
                auto fmask = 0;
                foreach(v;indices)
                {
                    fmask |= 1u << (v & fmax);
                }
                return (value() & fmask);
            }
            */
        }

        /// 寄存器写
        pragma(inline,true)
        @property static value(T)(T v) if((T.sizeof <= RegistersType.sizeof) && CanWrite!RegistersAccess)
        {
            atomicStore(*cast(T*)RegistersAddress,v);
        }



        /// 寄存器的位操作
        protected final abstract class Bits(size_t mOffset,size_t BitsSize,Access mAccess)
        {
            /// 位访问权限
            private {
                static if(mAccess & Access.rwa){
                    enum Access BitsAccess = RegistersAccess;
                }else{
                    enum Access BitsAccess = mAccess;
                }
            }
            /// 位偏移
            //enum size_t Bits_Offset = BitsOffset;
            /// 取位大小
            enum size_t Bits_Size = BitsSize;
            /// 位组返回类型
            private{
                static if(Bits_Size <= 1U){
                    alias Bits_Type = bool;
                }else static if(Bits_Size <= ubyte.sizeof * 8){
                    alias Bits_Type = ubyte;
                }else static if(Bits_Size <= ushort.sizeof * 8){
                    alias Bits_Type = ushort;
                }else static if(Bits_Size <= uint.sizeof * 8){
                    alias Bits_Type = uint;
                }else{
                    static assert(false,"T.sizeof > uint.sizeof");
                }
            }
            /// 位组最小值
            enum Value_Min = Bits_Type.min;
            /// 位组最大值
            static if(is(Bits_Type == bool)){
                enum Value_Max = bool.max;
            }else{
                enum Value_Max = Bits_Type.max >> ((Bits_Type.sizeof * 8) - Bits_Size);
            }

            static if(is(Bits_Type == bool) && IsBitBandable){
                enum BitsAddress = BitBand!(RegistersAddress,mOffset);
                enum BitsOffset = 0;
            }else{
                enum BitsAddress = RegistersAddress + (mOffset / 8);
                enum BitsOffset = mOffset % 8;
            }

            static if(CanRead!BitsAccess)
            {
                static @property Bits_Type value()
                {
                    static if(is(Bits_Type == bool)){
                        static if(IsBitBandable){
                            return cast(Bits_Type)atomicLoad(*cast(Bits_Type*)BitsAddress);
                        }else{
                            return cast(Bits_Type)(atomicLoad(*cast(Bits_Type*)BitsAddress) & (1u << BitsOffset));
                        }
                    }else{
                        return cast(Bits_Type)(atomicLoad(*cast(Bits_Type*)BitsAddress) >> BitsOffset) & Value_Max;
                    }
                }
            }

            static if(CanWrite!BitsAccess){
                static @property value(Bits_Type v)
                {
                    static if(is(Bits_Type==bool)){
                        static if(IsBitBandable){
                            atomicStore(*cast(Bits_Type*)BitsAddress,v);
                        }else{
                            auto tv = cast(Bits_Type)atomicLoad(*cast(Bits_Type*)BitsAddress);
                            // 清除原有位
                            tv &= ~(Value_Max << BitsOffset);
                            if(v){
                                tv |= (1u << BitsOffset) ;
                            }
                            atomicStore(*cast(Bits_Type*)BitsAddress,tv);
                        }                       
                    }else{
                        auto tv = cast(Bits_Type)atomicLoad(*cast(Bits_Type*)BitsAddress);
                        // 清除原有位
                        tv &= ~(Value_Max << BitsOffset);
                        // 赋值位
                        tv |= (v & Value_Max) << BitsOffset;

                        atomicStore(*cast(Bits_Type*)BitsAddress,tv);
                    }
                }
            }

            /*
            // todo : 未实现
            static if(CanClear!BitsAccess && is(Bits_Type == bool)){
                static void clear()
                {
                }
            }
            */
            
        }
    }
}

调用方式

/*****************************************************************************************
*	System control block ACTLR
*/
final abstract class SCB_ACTRL : Peripheral!(0xE000E008,Conf) {
    /// Auxiliary control register
    final abstract class ACTRL : Register!(0x0,Access.rw){
        /// DISMCYCINT
        alias DISMCYCINT=Bits!(0,1,Access.rwa);
        /// DISDEFWBUF
        alias DISDEFWBUF=Bits!(1,1,Access.rwa);
        /// DISFOLD
        alias DISFOLD=Bits!(2,1,Access.rwa);
        /// DISFPCA
        alias DISFPCA=Bits!(8,1,Access.rwa);
        /// DISOOFP
        alias DISOOFP=Bits!(9,1,Access.rwa);
    }
}

svd转声明工具

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值