首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >usart驱动包装

usart驱动包装
EN

Code Review用户
提问于 2019-12-28 10:51:49
回答 1查看 110关注 0票数 2

你能检查一下我的usart驱动程序包装吗?

它包含C语言Xilinx驱动程序,但我编写了C++程序,并需要C++ usart驱动程序。它是如何正确设计的,以及我需要在您的视图中添加哪些内容?

我会感谢你最严格的评价。

谢谢。

代码语言:javascript
复制
//**********************************************************************
// name:           usart.hpp
//
// test:           non.
//
// description:    a usart driver wrapper.
//
// author:         Artyom Shimko
//
// contact:        soikadigital@gmail.com
//
// created:        28.12.19
//
// release:        28.12.19
//
// changes:        non.
//
#ifndef USART_HPP
#define USART_HPP


#include "platform.h"                      // Platform depending settings.
#include "xuartps_hw.h"                    // The Xilinx header file for XUartPs device.

namespace UsartSapce {

    enum usartNumber { usart0 = XPAR_PS7_UART_0_BASEADDR,
                       usart1 = XPAR_PS7_UART_1_BASEADDR};
}


template <typename T>
class Usart : public Platform {

private:
   u32 usartNumber;

public:
   Usart(u32 usartNumber);                 // The set usart number method.

   status transmit(T *pData, u32 dataValue);
   status receive (T *pData, u32 dataValue);

   void reset(void);
};


//**********************************************************************
// The class constructor definition, it sets the usart number.
//**********************************************************************
// id:             A required usart number.
//
template <typename T>
Usart<T>::Usart (u32 usartNumber ) {

   this->usartNumber = usartNumber;
}


//**********************************************************************
// The usart reset method.
//**********************************************************************
// parameters:     non.
//
// return:         non.
//
template <typename T>
void Usart<T>::reset(void) {

   XUartPs_ResetHw(usartNumber);
 }


//**********************************************************************
// The data transmit usart method.
//**********************************************************************
// pData:          The pointer to transmited data.
//
// dataValue:      Value of transmited data.
//
// return:         ok aka 0 or error aka -1. The error occurs then pData
//                 is equal to nullptr or/and dataValue is equal to null.
//
template <typename T>
status Usart<T>::transmit(T *pData, u32 dataValue) {

   u8 *pByteData = nullptr;

   if(parameterCheck_(pData,dataValue) != StatusSpace::ok) {

       return StatusSpace::error;
   }

   pByteData = reinterpret_cast<u8*>(pData);

   for(u32 byteCounter = 0; byteCounter < dataValue; ++byteCounter) {

       XUartPs_SendByte(usartNumber, *(pByteData + byteCounter));
   }

    return StatusSpace::ok;
}

//**********************************************************************
// The data receive usart method.
//**********************************************************************
// pData:          The pointer to an array for received data.
//
// dataValue:      Value of received data.
//
// return:         ok aka 0 or error aka -1. The error occurs then pData
//                 is equal to nullptr or/and dataValue is equal to null.
//
template <typename T>
status Usart<T>::receive(T *pData, u32 dataValue) {

   u8 *pByteData = nullptr;

   if(parameterCheck_(pData,dataValue) != StatusSpace::ok) {

       return StatusSpace::error;
   }

   pByteData = reinterpret_cast<u8*>(pData);

   for(u32 byteCounter = 0; byteCounter < dataValue; ++byteCounter) {

       *(pByteData + byteCounter) = XUartPs_RecvByte(usartNumber);
   }

   return StatusSpace::ok;
}

#endif
EN

回答 1

Code Review用户

发布于 2020-01-04 16:33:46

考虑使用enum class

与其在自己的enum中使用常规的namespace,不如使用enum class

代码语言:javascript
复制
enum class UsartSpace: u32 {
    usart0 = XPAR_PS7_UART_0_BASEADDR,
    usart1 = XPAR_PS7_UART_1_BASEADDR,
};

然后,为了确保某人不能用错误的基址实例化Usart,使构造函数将此enum作为参数:

代码语言:javascript
复制
template <typename T>
Usart<T>::Usart(UsartSpace usartSpace): usartNumber(static_cast<u32>(usartSpace)) {
}

而且,"Space“是一个通用的词,不太能说明问题,但是您不能调用enum Usart,因为您已经拥有了class Usart。考虑将枚举移动到class Usart内部,因为它引用了一个端口,所以只需将其称为Port。或许还应明确港口号和地址之间的区别:

代码语言:javascript
复制
template <typename T>
class Usart: public Platform {
private:
    u32 baseAddress;
    static const u32 addresses[] = {
        XPAR_PS7_UART_0_BASEADDR,
        XPAR_PS7_UART_1_BASEADDR,
    };

public:
    enum class Port {
        usart0,
        usart1,
    };

    Usart(Port port);
    ...
};

...

template <typename T>
Usart<T>::Usart(Port port):
    baseAddress(addresses[static_cast<size_t>(port)])
{
}

然后,在使用该类的代码中,您将编写:

代码语言:javascript
复制
Usart<sometype> usart(Usart::Port::usart0);

使用更好的名称

在我看来,您所称的usartNumber就像一个基本地址,因此将其称为baseAddress。无论如何,不要在成员变量名中重复类的名称。

另外,dataValue不是某些数据的值,而是要读或写的数据的大小。所以叫它size,如果可能的话使用size_t作为它的类型:

代码语言:javascript
复制
status transmit(T *pData, size_t size);
status receive (T *pData, size_t size);

status还是StatusSpace?

我觉得这是另一种情况,即enum在它自己的namespace中被用作声明另一种类型的常量的方法。相反,我要界定:

代码语言:javascript
复制
enum class Status {
    ok,
    error,
    ...
};

在适当的

中使用数组表示法

与其编写*(pByteData + byteCounter),不如编写更加理想化的pByteData[byteCounter]

在适当的情况下使用const

您不会期望函数transmit()修改要发送的数据。因此,要明确这一点:

代码语言:javascript
复制
template <typename T>
class Usart: public Platform {
    ...
    status transmit(const T *pdata, size_t size);
    ...
}

考虑模板化transmit()receive(),而不是整个class

唯一依赖于模板参数T的是transmit()receive()函数。通过制作class模板,您基本上可以锁定在实例化类时可以发送和接收的数据类型。相反,只考虑这两个函数的模板,这样您就可以在同一个UART上发送和接收不同的数据类型,而不必恢复该类:

代码语言:javascript
复制
class Usart: public Platform {
    ...
    template <typename T>
    status transmit(const T *pData, size_t size);

    template <typename T>
    status receive(T *pData, size_t size);
    ...
};

使用DO2记录您的代码

您正在记录您的代码,这是一个很好的实践,但是请考虑使用含氧的S格式,这样您就可以用HTML和其他表单创建交叉引用的文档,还可以检查是否记录了所有函数和函数的所有参数。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/234728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档