介绍
这是一个外设寄存器读写通用设计,通过SVD文件转换的代码可以直接用来生成HAL操作的class.具体代码应用往下看~.
实现代码
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);
}
}