创建硬编码定义的变体

时间:2019-05-05 13:56:30

标签: c buffer microcontroller avr-gcc

我有一个用于微控制器的C源代码,我将向您展示标题的第一部分:

#define USART_RX_BUFFER_SIZE 256
#define USART_TX_BUFFER_SIZE 256
#define USART_RX_BUFFER_MASK (USART_RX_BUFFER_SIZE - 1)
#define USART_TX_BUFFER_MASK (USART_TX_BUFFER_SIZE - 1)

#if (USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK)
#error RX buffer size is not a power of 2
#endif
#if (USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK)
#error TX buffer size is not a power of 2
#endif

typedef struct USART_Buffer {
    volatile uint8_t RX[USART_RX_BUFFER_SIZE];
    volatile uint8_t TX[USART_TX_BUFFER_SIZE];
    volatile uint16_t RX_Head;
    volatile uint16_t RX_Tail;
    volatile uint16_t TX_Head;
    volatile uint16_t TX_Tail;
} USART_Buffer_t;

typedef struct Usart_and_buffer {
    USART_t *usart;
    USART_DREINTLVL_t dreIntLevel;
    USART_TXCINTLVL_t txcIntLevel;
    USART_Buffer_t buffer;
    PORT_t *rs485_Port;
    uint8_t  rs485_Pin;
    bool rs485;
} USART_data_t;

uint8_t USART_RXBuffer_GetByte(USART_data_t *usart_data);
bool USART_RXComplete(USART_data_t *usart_data);
void USART_TransmitComplete(USART_data_t *usart_data);
...

还有其他一些类似的功能。 它们的实现通常同时使用USART_data_tUSART_Buffer_t,例如:

bool USART_TXBuffer_PutByte(USART_data_t *usart_data, uint8_t data) {
    uint8_t tempCTRLA;
    uint16_t tempTX_Head;
    bool TXBuffer_FreeSpace;
    USART_Buffer_t * TXbufPtr;

    if (usart_data->rs485) usart_data->rs485_Port->OUTSET = usart_data->rs485_Pin;
    TXbufPtr = &usart_data->buffer;
...

在我的实际应用程序中,我需要声明许多USART_data_t结构,但只有其中几个需要如此大的缓冲区(256字节)。大多数将使用很小的字节,例如64甚至32字节。

我很容易用完内存,实际上所有空间都未使用。

我的目标是找到一种节省空间的方法。

肮脏的方法是克隆整个文件,将 all 重命名为变量/函数,以具有两个不同的版本,例如一个带有256字节的缓冲区,另一个带有64字节的缓冲区。 。 但是然后我还必须更改代码中的每个调用,否则我将避免这种情况。

此库非常快,因为它可在2的幂的循环缓冲区上工作,并且使用上面的定义,只需几个时钟周期即可完成所需的数学运算。因此,我真的不想重写整个库以使用内存的动态分配。

还有其他想法吗?

使用示例:

USART_data_t RS232B_USART_data;
USART_data_t RS232A_USART_data;

#define RS232B_BUFFER_SIZE                  4
char RS232B_RxBuffer[RS232B_BUFFER_SIZE];
char RS232B_TxBuffer[RS232B_BUFFER_SIZE];

#define RS232A_BUFFER_SIZE                  64
char RS232A_RxBuffer[RS232A_BUFFER_SIZE];
char RS232A_TxBuffer[RS232A_BUFFER_SIZE];

ISR(USARTC1_RXC_vect) { USART_RXComplete(&RS232B_USART_data); }
ISR(USARTC1_DRE_vect) { USART_DataRegEmpty(&RS232B_USART_data); }
ISR(USARTC1_TXC_vect) { USART_TransmitComplete(&RS232B_USART_data); }

ISR(USARTD0_RXC_vect) { USART_RXComplete(&RS232A_USART_data); }
ISR(USARTD0_DRE_vect) { USART_DataRegEmpty(&RS232A_USART_data); }
ISR(USARTD0_TXC_vect) { USART_TransmitComplete(&RS232A_USART_data); }

// ...

USART_InterruptDriver_Initialize(&RS232B_USART_data, &RS232B_USART, USART_DREINTLVL_LO_gc, USART_TXCINTLVL_LO_gc, false);
USART_Format_Set(RS232B_USART_data.usart, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
USART_RxdInterruptLevel_Set(RS232B_USART_data.usart, USART_RXCINTLVL_HI_gc);
USART_Baudrate_Set(&RS232B_USART, 2094, -7);
USART_Rx_Enable(RS232B_USART_data.usart);
USART_Tx_Enable(RS232B_USART_data.usart);

USART_InterruptDriver_Initialize(&RS232A_USART_data, &RS232A_USART, USART_DREINTLVL_LO_gc, USART_TXCINTLVL_LO_gc, false);
USART_Format_Set(RS232A_USART_data.usart, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
USART_RxdInterruptLevel_Set(RS232A_USART_data.usart, USART_RXCINTLVL_HI_gc);
USART_Baudrate_Set(&RS232A_USART, 2094, -7);
USART_Rx_Enable(RS232A_USART_data.usart);
USART_Tx_Enable(RS232A_USART_data.usart);

1 个答案:

答案 0 :(得分:0)

您可能会重写USART_Buffer_t,使其仅包含指向rx / tx缓冲区的指针,并添加两个附加变量,这些变量设置为“附加”缓冲区的大小。

这都是写下来的,所以请期待错别字等,但希望您能理解。

typedef struct USART_Buffer {
    volatile uint8_t* pRX;
    volatile uint8_t* pTX;
    volatile uint16_t RX_Size;
    volatile uint16_t TX_Size;
    volatile uint16_t RX_Head;
    volatile uint16_t RX_Tail;
    volatile uint16_t TX_Head;
    volatile uint16_t TX_Tail;
} USART_Buffer_t;

然后您编写一个辅助函数,如

USART_InitBuffers(USART_data_t data, uint8_t* pTxBuffer, uint16_t sizeTxBuffer, uint8_t* pRxBuffer, uint16_t sizeRxBuffer) {
     data.pRX = pTxBuffer;
     // ... other assignments
}

这样,您可以为每个USART指定不同大小的数组:

uint8_t TxData1[100]
uint8_t RxData1[10]
uint8_t TxData2[255]
uint8_t RxData2[50]

USART_Buffer_t data1;
USART_Buffer_t data2;

main() {
    USART_InitBuffers(&data1, TxData1, sizeof(TxData1), RxData1, sizeof(RxData1));
    USART_InitBuffers(&data2, TxData2, sizeof(TxData2), RxData2, sizeof(RxData2));
}

最后,您必须调整库函数,以使用RX_Size和TX_Size而不是使用USART_RX_BUFFER_SIZE和USART_TX_BUFFER_SIZE。