你能检查一下我的usart驱动程序包装吗?
它包含C语言Xilinx驱动程序,但我编写了C++程序,并需要C++ usart驱动程序。它是如何正确设计的,以及我需要在您的视图中添加哪些内容?
我会感谢你最严格的评价。
谢谢。
//**********************************************************************
// 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发布于 2020-01-04 16:33:46
enum class与其在自己的enum中使用常规的namespace,不如使用enum class:
enum class UsartSpace: u32 {
usart0 = XPAR_PS7_UART_0_BASEADDR,
usart1 = XPAR_PS7_UART_1_BASEADDR,
};然后,为了确保某人不能用错误的基址实例化Usart,使构造函数将此enum作为参数:
template <typename T>
Usart<T>::Usart(UsartSpace usartSpace): usartNumber(static_cast<u32>(usartSpace)) {
}而且,"Space“是一个通用的词,不太能说明问题,但是您不能调用enum Usart,因为您已经拥有了class Usart。考虑将枚举移动到class Usart内部,因为它引用了一个端口,所以只需将其称为Port。或许还应明确港口号和地址之间的区别:
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)])
{
}然后,在使用该类的代码中,您将编写:
Usart<sometype> usart(Usart::Port::usart0);在我看来,您所称的usartNumber就像一个基本地址,因此将其称为baseAddress。无论如何,不要在成员变量名中重复类的名称。
另外,dataValue不是某些数据的值,而是要读或写的数据的大小。所以叫它size,如果可能的话使用size_t作为它的类型:
status transmit(T *pData, size_t size);
status receive (T *pData, size_t size);status还是StatusSpace?我觉得这是另一种情况,即enum在它自己的namespace中被用作声明另一种类型的常量的方法。相反,我要界定:
enum class Status {
ok,
error,
...
};中使用数组表示法
与其编写*(pByteData + byteCounter),不如编写更加理想化的pByteData[byteCounter]。
const 您不会期望函数transmit()修改要发送的数据。因此,要明确这一点:
template <typename T>
class Usart: public Platform {
...
status transmit(const T *pdata, size_t size);
...
}transmit()和receive(),而不是整个class唯一依赖于模板参数T的是transmit()和receive()函数。通过制作class模板,您基本上可以锁定在实例化类时可以发送和接收的数据类型。相反,只考虑这两个函数的模板,这样您就可以在同一个UART上发送和接收不同的数据类型,而不必恢复该类:
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);
...
};您正在记录您的代码,这是一个很好的实践,但是请考虑使用含氧的S格式,这样您就可以用HTML和其他表单创建交叉引用的文档,还可以检查是否记录了所有函数和函数的所有参数。
https://codereview.stackexchange.com/questions/234728
复制相似问题