1
0
forked from me/IronOS

Format Pine code

This commit is contained in:
Ben V. Brown
2021-01-17 10:55:15 +11:00
parent bf5055edaa
commit 7ecc7e4d12
60 changed files with 9387 additions and 10756 deletions

View File

@@ -105,7 +105,8 @@ typedef struct {
* ADC can be either disabled or enabled without conversion on going on regular group.
*/
typedef struct {
uint32_t Channel; /*!< Specifies the channel to configure into ADC regular group.
uint32_t
Channel; /*!< Specifies the channel to configure into ADC regular group.
This parameter can be a value of @ref ADC_channels
Note: Depending on devices, some channels may not be available on package pins. Refer to device datasheet for channels availability.
Note: On STM32F1 devices with several ADC: Only ADC1 can access internal measurement channels (VrefInt/TempSensor)

View File

@@ -69,13 +69,13 @@ extern "C" {
* - For all except parameters 'ExternalTrigInjecConv': ADC enabled without conversion on going on injected group.
*/
typedef struct {
uint32_t
InjectedChannel; /*!< Selection of ADC channel to configure
uint32_t InjectedChannel; /*!< Selection of ADC channel to configure
This parameter can be a value of @ref ADC_channels
Note: Depending on devices, some channels may not be available on package pins. Refer to device datasheet for channels availability.
Note: On STM32F1 devices with several ADC: Only ADC1 can access internal measurement channels (VrefInt/TempSensor)
Note: On STM32F10xx8 and STM32F10xxB devices: A low-amplitude voltage glitch may be generated (on ADC input 0) on the PA0 pin, when the ADC is converting with injection
trigger. It is advised to distribute the analog channels so that Channel 0 is configured as an injected channel. Refer to errata sheet of these devices for more details. */
Note: On STM32F10xx8 and STM32F10xxB devices: A low-amplitude voltage glitch may be generated (on ADC input 0) on the PA0 pin, when the ADC is converting with
injection trigger. It is advised to distribute the analog channels so that Channel 0 is configured as an injected channel. Refer to errata
sheet of these devices for more details. */
uint32_t InjectedRank; /*!< Rank in the injected group sequencer
This parameter must be a value of @ref ADCEx_injected_rank
Note: In case of need to disable a channel or change order of conversion sequencer, rank containing a previous channel setting can be overwritten by the new channel

View File

@@ -9,123 +9,112 @@
#include "main.hpp"
#include <IRQ.h>
const uint16_t powerPWM = 255;
const uint8_t holdoffTicks = 25; // delay of 7 ms
const uint8_t tempMeasureTicks = 25;
const uint16_t powerPWM = 255;
const uint8_t holdoffTicks = 25; // delay of 7 ms
const uint8_t tempMeasureTicks = 25;
uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle
// 2 second filter (ADC is PID_TIM_HZ Hz)
history<uint16_t, PID_TIM_HZ> rawTempFilter = { { 0 }, 0, 0 };
void resetWatchdog() {
fwdgt_counter_reload();
}
history<uint16_t, PID_TIM_HZ> rawTempFilter = {{0}, 0, 0};
void resetWatchdog() { fwdgt_counter_reload(); }
uint16_t getTipInstantTemperature() {
volatile uint16_t sum = 0; // 12 bit readings * 8*2 -> 16 bits
volatile uint16_t sum = 0; // 12 bit readings * 8*2 -> 16 bits
for (int i = 0; i < 4; i++) {
sum += adc_inserted_data_read(ADC0, i);
sum += adc_inserted_data_read(ADC1, i);
}
return sum; // 8x over sample
for (int i = 0; i < 4; i++) {
sum += adc_inserted_data_read(ADC0, i);
sum += adc_inserted_data_read(ADC1, i);
}
return sum; // 8x over sample
}
uint16_t getTipRawTemp(uint8_t refresh) {
if (refresh) {
uint16_t lastSample = getTipInstantTemperature();
rawTempFilter.update(lastSample);
return lastSample;
} else {
return rawTempFilter.average();
}
if (refresh) {
uint16_t lastSample = getTipInstantTemperature();
rawTempFilter.update(lastSample);
return lastSample;
} else {
return rawTempFilter.average();
}
}
uint16_t getHandleTemperature() {
#ifdef TEMP_TMP36
// We return the current handle temperature in X10 C
// TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for
// example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) =
// 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125
// mV per count So we need to subtract an offset of 0.5V to center on 0C
// (4964.8 counts)
//
int32_t result = getADC(0);
result -= 4965; // remove 0.5V offset
// 10mV per C
// 99.29 counts per Deg C above 0C
result *= 100;
result /= 993;
return result;
// We return the current handle temperature in X10 C
// TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for
// example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) =
// 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125
// mV per count So we need to subtract an offset of 0.5V to center on 0C
// (4964.8 counts)
//
int32_t result = getADC(0);
result -= 4965; // remove 0.5V offset
// 10mV per C
// 99.29 counts per Deg C above 0C
result *= 100;
result /= 993;
return result;
#else
#error
#endif
}
uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) {
static uint8_t preFillneeded = 10;
static uint32_t samples[BATTFILTERDEPTH];
static uint8_t index = 0;
if (preFillneeded) {
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
samples[i] = getADC(1);
preFillneeded--;
}
if (sample) {
samples[index] = getADC(1);
index = (index + 1) % BATTFILTERDEPTH;
}
uint32_t sum = 0;
static uint8_t preFillneeded = 10;
static uint32_t samples[BATTFILTERDEPTH];
static uint8_t index = 0;
if (preFillneeded) {
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
samples[i] = getADC(1);
preFillneeded--;
}
if (sample) {
samples[index] = getADC(1);
index = (index + 1) % BATTFILTERDEPTH;
}
uint32_t sum = 0;
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
sum += samples[i];
for (uint8_t i = 0; i < BATTFILTERDEPTH; i++)
sum += samples[i];
sum /= BATTFILTERDEPTH;
if (divisor == 0) {
divisor = 1;
}
return sum * 4 / divisor;
sum /= BATTFILTERDEPTH;
if (divisor == 0) {
divisor = 1;
}
return sum * 4 / divisor;
}
void unstick_I2C() {
/* configure SDA/SCL for GPIO */
GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin;
gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
SDA_Pin | SCL_Pin);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
GPIO_BOP(GPIOB) |= SCL_Pin;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
GPIO_BOP(GPIOB) |= SDA_Pin;
/* connect PB6 to I2C0_SCL */
/* connect PB7 to I2C0_SDA */
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ,
SDA_Pin | SCL_Pin);
/* configure SDA/SCL for GPIO */
GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin;
gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
GPIO_BOP(GPIOB) |= SCL_Pin;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
GPIO_BOP(GPIOB) |= SDA_Pin;
/* connect PB6 to I2C0_SCL */
/* connect PB7 to I2C0_SDA */
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin);
}
uint8_t getButtonA() {
return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0;
}
uint8_t getButtonB() {
return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0;
}
uint8_t getButtonA() { return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; }
uint8_t getButtonB() { return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; }
void reboot() {
//Spin for watchdog
for (;;) {
}
// Spin for watchdog
for (;;) {}
}
void delay_ms(uint16_t count) {
delay_1ms(count);
}
void delay_ms(uint16_t count) { delay_1ms(count); }
uint32_t __get_IPSR(void) {
return 0; // To shut-up CMSIS
return 0; // To shut-up CMSIS
}

View File

@@ -12,14 +12,14 @@
* An array of all of the desired voltages & minimum currents in preferred order
*/
const uint16_t USB_PD_Desired_Levels[] = {
//mV desired input, mA minimum required current
//Tip is ~ 7.5 ohms
20000, 2666, // 20V, 2.6A
15000, 2000, // 15V 2A
12000, 1600, //12V @ 1.6A
9000, 1200, //9V @ 1.2A
5000, 100, //5V @ whatever
// mV desired input, mA minimum required current
// Tip is ~ 7.5 ohms
20000, 2666, // 20V, 2.6A
15000, 2000, // 15V 2A
12000, 1600, // 12V @ 1.6A
9000, 1200, // 9V @ 1.2A
5000, 100, // 5V @ whatever
};
};
const uint8_t USB_PD_Desired_Levels_Len = 5;
#endif

View File

@@ -12,517 +12,506 @@ SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
#define I2C_TIME_OUT (uint16_t)(12000)
void FRToSI2C::CpltCallback() {
// TODO
// TODO
}
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) {
return Mem_Write(address, reg, &data, 1);
}
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); }
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
uint8_t temp = 0;
Mem_Read(add, reg, &temp, 1);
return temp;
uint8_t temp = 0;
Mem_Read(add, reg, &temp, 1);
return temp;
}
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) {
if (!lock())
return false;
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
i2c_interrupt_disable(I2C0, I2C_INT_EV);
dma_parameter_struct dma_init_struct;
if (!lock())
return false;
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
i2c_interrupt_disable(I2C0, I2C_INT_EV);
dma_parameter_struct dma_init_struct;
uint8_t state = I2C_START;
uint8_t in_rx_cycle = 0;
uint16_t timeout = 0;
uint8_t tries = 0;
uint8_t i2c_timeout_flag = 0;
while (!(i2c_timeout_flag)) {
switch (state) {
case I2C_START:
tries++;
if (tries > 64) {
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
unlock();
return false;
}
if (0 == in_rx_cycle) {
/* disable I2C0 */
i2c_disable(I2C0);
/* enable I2C0 */
i2c_enable(I2C0);
uint8_t state = I2C_START;
uint8_t in_rx_cycle = 0;
uint16_t timeout = 0;
uint8_t tries = 0;
uint8_t i2c_timeout_flag = 0;
while (!(i2c_timeout_flag)) {
switch (state) {
case I2C_START:
tries++;
if (tries > 64) {
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
unlock();
return false;
}
if (0 == in_rx_cycle) {
/* disable I2C0 */
i2c_disable(I2C0);
/* enable I2C0 */
i2c_enable(I2C0);
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
/* send the start signal */
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
I2C_Unstick();
timeout = 0;
state = I2C_START;
}
} else {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
if (RESET == in_rx_cycle) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER);
state = I2C_CLEAR_ADDRESS_FLAG;
}
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) {
timeout++;
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
}
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_TRANSMIT_DATA;
} else {
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
break;
case I2C_TRANSMIT_DATA:
if (0 == in_rx_cycle) {
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
// Write out the 8 byte address
i2c_data_transmit(I2C0, read_address);
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
/* wait until BTC bit is set */
while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_START;
in_rx_cycle = 1;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
} else {
/* one byte master reception procedure (polling) */
if (number_of_byte < 2) {
/* disable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
/* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register
* (I2C_STAT0 has already been read) */
i2c_flag_get(I2C0, I2C_FLAG_ADDSEND);
/* send a stop condition to I2C bus*/
i2c_stop_on_bus(I2C0);
/* wait for the byte to be received */
while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE))
;
/* read the byte received from the EEPROM */
*p_buffer = i2c_data_receive(I2C0);
/* decrement the read bytes counter */
number_of_byte--;
timeout = 0;
} else { /* more than one byte master reception procedure (DMA) */
dma_deinit(DMA0, DMA_CH6);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t) p_buffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = number_of_byte;
dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA0, DMA_CH6, &dma_init_struct);
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
/* send the start signal */
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
I2C_Unstick();
timeout = 0;
state = I2C_START;
}
} else {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
if (RESET == in_rx_cycle) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER);
state = I2C_CLEAR_ADDRESS_FLAG;
}
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
}
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_TRANSMIT_DATA;
} else {
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
break;
case I2C_TRANSMIT_DATA:
if (0 == in_rx_cycle) {
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
// Write out the 8 byte address
i2c_data_transmit(I2C0, read_address);
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
/* wait until BTC bit is set */
while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_START;
in_rx_cycle = 1;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
} else {
/* one byte master reception procedure (polling) */
if (number_of_byte < 2) {
/* disable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
/* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register
* (I2C_STAT0 has already been read) */
i2c_flag_get(I2C0, I2C_FLAG_ADDSEND);
/* send a stop condition to I2C bus*/
i2c_stop_on_bus(I2C0);
/* wait for the byte to be received */
while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE))
;
/* read the byte received from the EEPROM */
*p_buffer = i2c_data_receive(I2C0);
/* decrement the read bytes counter */
number_of_byte--;
timeout = 0;
} else { /* more than one byte master reception procedure (DMA) */
dma_deinit(DMA0, DMA_CH6);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)p_buffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = number_of_byte;
dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA0, DMA_CH6, &dma_init_struct);
i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON);
/* enable I2C0 DMA */
i2c_dma_enable(I2C0, I2C_DMA_ON);
/* enable DMA0 channel5 */
dma_channel_enable(DMA0, DMA_CH6);
/* wait until BTC bit is set */
while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) {
}
/* send a stop condition to I2C bus*/
i2c_stop_on_bus(I2C0);
}
timeout = 0;
state = I2C_STOP;
}
break;
case I2C_STOP:
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
i2c_timeout_flag = I2C_OK;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
break;
default:
state = I2C_START;
in_rx_cycle = 0;
i2c_timeout_flag = I2C_OK;
timeout = 0;
break;
}
}
unlock();
return true;
i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON);
/* enable I2C0 DMA */
i2c_dma_enable(I2C0, I2C_DMA_ON);
/* enable DMA0 channel5 */
dma_channel_enable(DMA0, DMA_CH6);
/* wait until BTC bit is set */
while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) {}
/* send a stop condition to I2C bus*/
i2c_stop_on_bus(I2C0);
}
timeout = 0;
state = I2C_STOP;
}
break;
case I2C_STOP:
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
i2c_timeout_flag = I2C_OK;
} else {
timeout = 0;
state = I2C_START;
in_rx_cycle = 0;
}
break;
default:
state = I2C_START;
in_rx_cycle = 0;
i2c_timeout_flag = I2C_OK;
timeout = 0;
break;
}
}
unlock();
return true;
}
bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) {
if (!lock())
return false;
if (!lock())
return false;
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
i2c_interrupt_disable(I2C0, I2C_INT_EV);
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
dma_parameter_struct dma_init_struct;
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
i2c_interrupt_disable(I2C0, I2C_INT_EV);
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
dma_parameter_struct dma_init_struct;
uint8_t state = I2C_START;
uint16_t timeout = 0;
bool done = false;
bool timedout = false;
while (!(done || timedout)) {
switch (state) {
case I2C_START:
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
I2C_Unstick();
timeout = 0;
state = I2C_START;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
timeout = 0;
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) {
timeout++;
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
}
timeout = 0;
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
state = I2C_TRANSMIT_DATA;
} else {
// Dont retry as this means a NAK
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
unlock();
return false;
}
break;
case I2C_TRANSMIT_DATA:
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
/* send the EEPROM's internal address to write to : only one byte
* address */
i2c_data_transmit(I2C0, MemAddress);
timeout = 0;
} else {
timedout = true;
timeout = 0;
state = I2C_START;
}
/* wait until BTC bit is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
;
dma_deinit(DMA0, DMA_CH5);
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_addr = (uint32_t) p_buffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = number_of_byte;
dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA0, DMA_CH5, &dma_init_struct);
/* enable I2C0 DMA */
i2c_dma_enable(I2C0, I2C_DMA_ON);
/* enable DMA0 channel5 */
dma_channel_enable(DMA0, DMA_CH5);
/* wait until BTC bit is set */
while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) {
}
/* wait until BTC bit is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) {
}
state = I2C_STOP;
break;
case I2C_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
done = true;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
default:
state = I2C_START;
timeout = 0;
break;
}
}
unlock();
return timedout == false;
uint8_t state = I2C_START;
uint16_t timeout = 0;
bool done = false;
bool timedout = false;
while (!(done || timedout)) {
switch (state) {
case I2C_START:
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
I2C_Unstick();
timeout = 0;
state = I2C_START;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
timeout = 0;
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
}
timeout = 0;
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
state = I2C_TRANSMIT_DATA;
} else {
// Dont retry as this means a NAK
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
unlock();
return false;
}
break;
case I2C_TRANSMIT_DATA:
/* wait until the transmit data buffer is empty */
while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
/* send the EEPROM's internal address to write to : only one byte
* address */
i2c_data_transmit(I2C0, MemAddress);
timeout = 0;
} else {
timedout = true;
timeout = 0;
state = I2C_START;
}
/* wait until BTC bit is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC))
;
dma_deinit(DMA0, DMA_CH5);
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_addr = (uint32_t)p_buffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = number_of_byte;
dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA0, DMA_CH5, &dma_init_struct);
/* enable I2C0 DMA */
i2c_dma_enable(I2C0, I2C_DMA_ON);
/* enable DMA0 channel5 */
dma_channel_enable(DMA0, DMA_CH5);
/* wait until BTC bit is set */
while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) {}
/* wait until BTC bit is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) {}
state = I2C_STOP;
break;
case I2C_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
done = true;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
default:
state = I2C_START;
timeout = 0;
break;
}
}
unlock();
return timedout == false;
}
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1);
}
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); }
bool FRToSI2C::probe(uint16_t DevAddress) {
uint8_t temp[1];
return Mem_Read(DevAddress, 0x00, temp, sizeof(temp));
uint8_t temp[1];
return Mem_Read(DevAddress, 0x00, temp, sizeof(temp));
}
void FRToSI2C::I2C_Unstick() {
unstick_I2C();
}
void FRToSI2C::I2C_Unstick() { unstick_I2C(); }
bool FRToSI2C::lock() {
if (I2CSemaphore == nullptr) {
return false;
}
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
return true;
}
return xSemaphoreTake(I2CSemaphore, TICKS_SECOND) == pdTRUE;
if (I2CSemaphore == nullptr) {
return false;
}
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
return true;
}
return xSemaphoreTake(I2CSemaphore, TICKS_SECOND) == pdTRUE;
}
void FRToSI2C::unlock() {
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
return;
}
xSemaphoreGive(I2CSemaphore);
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
return;
}
xSemaphoreGive(I2CSemaphore);
}
bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) {
for (int index = 0; index < registersLength; index++) {
if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) {
return false;
}
if (registers[index].pause_ms) {
delay_ms(registers[index].pause_ms);
}
}
return true;
for (int index = 0; index < registersLength; index++) {
if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) {
return false;
}
if (registers[index].pause_ms) {
delay_ms(registers[index].pause_ms);
}
}
return true;
}
bool FRToSI2C::wakePart(uint16_t DevAddress) {
// wakepart is a special case where only the device address is sent
if (!lock())
return false;
// wakepart is a special case where only the device address is sent
if (!lock())
return false;
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
i2c_interrupt_disable(I2C0, I2C_INT_EV);
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
i2c_interrupt_disable(I2C0, I2C_INT_ERR);
i2c_interrupt_disable(I2C0, I2C_INT_EV);
i2c_interrupt_disable(I2C0, I2C_INT_BUF);
uint8_t state = I2C_START;
uint16_t timeout = 0;
bool done = false;
bool timedout = false;
while (!(done || timedout)) {
switch (state) {
case I2C_START:
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
I2C_Unstick();
timeout = 0;
state = I2C_START;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
timeout = 0;
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) {
timeout++;
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
}
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_STOP;
} else {
// Dont retry as this means a NAK
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
unlock();
return false;
}
break;
uint8_t state = I2C_START;
uint16_t timeout = 0;
bool done = false;
bool timedout = false;
while (!(done || timedout)) {
switch (state) {
case I2C_START:
/* i2c master sends start signal only when the bus is idle */
while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_start_on_bus(I2C0);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
I2C_Unstick();
timeout = 0;
state = I2C_START;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
timeout = 0;
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
// Address NACK'd
unlock();
return false;
}
}
if (timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_STOP;
} else {
// Dont retry as this means a NAK
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
unlock();
return false;
}
break;
case I2C_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
done = true;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
default:
state = I2C_START;
timeout = 0;
break;
}
}
unlock();
return timedout == false;
case I2C_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C0);
/* i2c master sends STOP signal successfully */
while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if (timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
done = true;
} else {
timedout = true;
done = true;
timeout = 0;
state = I2C_START;
}
break;
default:
state = I2C_START;
timeout = 0;
break;
}
}
unlock();
return timedout == false;
}

View File

@@ -8,119 +8,117 @@
#include "IRQ.h"
#include "Pins.h"
#include "int_n.h"
volatile uint8_t i2c_read_process = 0;
volatile uint8_t i2c_write_process = 0;
volatile uint8_t i2c_slave_address = 0;
volatile uint8_t i2c_error_code = 0;
volatile uint8_t i2c_read_process = 0;
volatile uint8_t i2c_write_process = 0;
volatile uint8_t i2c_slave_address = 0;
volatile uint8_t i2c_error_code = 0;
volatile uint8_t *i2c_write;
volatile uint8_t *i2c_read;
volatile uint16_t i2c_nbytes;
volatile uint16_t i2c_write_dress;
volatile uint16_t i2c_read_dress;
volatile uint8_t i2c_process_flag = 0;
void ADC0_1_IRQHandler(void) {
volatile uint8_t i2c_process_flag = 0;
void ADC0_1_IRQHandler(void) {
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
// unblock the PID controller thread
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (pidTaskNotification) {
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
// unblock the PID controller thread
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (pidTaskNotification) {
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}
volatile uint16_t PWMSafetyTimer = 0;
volatile uint8_t pendingPWM = 0;
void TIMER1_IRQHandler(void) {
volatile uint8_t pendingPWM = 0;
void TIMER1_IRQHandler(void) {
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) {
timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP);
// rollover turn on output if required
if (PWMSafetyTimer && pendingPWM) {
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50);
}
if (PWMSafetyTimer) {
PWMSafetyTimer--;
}
}
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) {
timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1);
// This is triggered on pwm setpoint trigger; we want to copy the pending
// PWM value into the output control reg
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) {
timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP);
// rollover turn on output if required
if (PWMSafetyTimer && pendingPWM) {
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50);
}
if (PWMSafetyTimer) {
PWMSafetyTimer--;
}
}
if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) {
timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1);
// This is triggered on pwm setpoint trigger; we want to copy the pending
// PWM value into the output control reg
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
if (pendingPWM) {
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM);
}
}
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
if (pendingPWM) {
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM);
}
}
}
void setTipPWM(uint8_t pulse) {
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
// disabled if the PID task is not scheduled often enough.
pendingPWM = pulse;
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
// disabled if the PID task is not scheduled often enough.
pendingPWM = pulse;
}
static bool fastPWM;
static void switchToFastPWM(void) {
fastPWM = true;
totalPWM = powerPWM + tempMeasureTicks * 2;
TIMER_CAR(TIMER1) = (uint32_t) totalPWM;
fastPWM = true;
totalPWM = powerPWM + tempMeasureTicks * 2;
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
// ~3.5 Hz rate
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2;
// 1 kHz tick rate
TIMER_PSC(TIMER1) = 12000;
/* generate an update event */
TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG;
// ~3.5 Hz rate
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2;
// 1 kHz tick rate
TIMER_PSC(TIMER1) = 12000;
/* generate an update event */
TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG;
}
static void switchToSlowPWM(void) {
fastPWM = false;
totalPWM = powerPWM + tempMeasureTicks;
TIMER_CAR(TIMER1) = (uint32_t) totalPWM;
// ~1.84 Hz rate
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks;
// 500 Hz tick rate
TIMER_PSC(TIMER1) = 24000;
/* generate an update event */
TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG;
fastPWM = false;
totalPWM = powerPWM + tempMeasureTicks;
TIMER_CAR(TIMER1) = (uint32_t)totalPWM;
// ~1.84 Hz rate
TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks;
// 500 Hz tick rate
TIMER_PSC(TIMER1) = 24000;
/* generate an update event */
TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG;
}
bool tryBetterPWM(uint8_t pwm) {
if (fastPWM && pwm == powerPWM) {
// maximum power for fast PWM reached, need to go slower to get more
switchToSlowPWM();
return true;
} else if (!fastPWM && pwm < 230) {
// 254 in fast PWM mode gives the same power as 239 in slow
// allow for some reasonable hysteresis by switching only when it goes
// below 230 (equivalent to 245 in fast mode)
switchToFastPWM();
return true;
}
return false;
if (fastPWM && pwm == powerPWM) {
// maximum power for fast PWM reached, need to go slower to get more
switchToSlowPWM();
return true;
} else if (!fastPWM && pwm < 230) {
// 254 in fast PWM mode gives the same power as 239 in slow
// allow for some reasonable hysteresis by switching only when it goes
// below 230 (equivalent to 245 in fast mode)
switchToFastPWM();
return true;
}
return false;
}
void EXTI5_9_IRQHandler(void) {
#ifdef POW_PD
if (RESET != exti_interrupt_flag_get(EXTI_5)) {
exti_interrupt_flag_clear(EXTI_5);
if (RESET != exti_interrupt_flag_get(EXTI_5)) {
exti_interrupt_flag_clear(EXTI_5);
if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
InterruptHandler::irqCallback();
}
}
}
if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
InterruptHandler::irqCallback();
}
}
}
#endif
}
// These are unused for now
void I2C0_EV_IRQHandler(void) {
}
void I2C0_EV_IRQHandler(void) {}
void I2C0_ER_IRQHandler(void) {
}
void I2C0_ER_IRQHandler(void) {}

View File

@@ -1,49 +1,49 @@
#include "BSP.h"
#include "BSP_Power.h"
#include "Model_Config.h"
#include "Pins.h"
#include "QC3.h"
#include "Settings.h"
#include "Pins.h"
#include "fusbpd.h"
#include "Model_Config.h"
#include "policy_engine.h"
#include "int_n.h"
#include "policy_engine.h"
bool FUSB302_present = false;
void power_check() {
#ifdef POW_PD
if (FUSB302_present) {
//Cant start QC until either PD works or fails
if (PolicyEngine::setupCompleteOrTimedOut() == false) {
return;
}
if (PolicyEngine::pdHasNegotiated()) {
return;
}
}
if (FUSB302_present) {
// Cant start QC until either PD works or fails
if (PolicyEngine::setupCompleteOrTimedOut() == false) {
return;
}
if (PolicyEngine::pdHasNegotiated()) {
return;
}
}
#endif
#ifdef POW_QC
QC_resync();
QC_resync();
#endif
}
uint8_t usb_pd_detect() {
#ifdef POW_PD
FUSB302_present = fusb302_detect();
FUSB302_present = fusb302_detect();
return FUSB302_present;
return FUSB302_present;
#endif
return false;
return false;
}
bool getIsPoweredByDCIN() {
//We return false until we are sure we are not using PD
if (PolicyEngine::setupCompleteOrTimedOut() == false) {
return false;
}
if (PolicyEngine::pdHasNegotiated()) {
return false; // We are using PD
}
if (hasQCNegotiated()) {
return false; // We are using QC
}
return true;
// We return false until we are sure we are not using PD
if (PolicyEngine::setupCompleteOrTimedOut() == false) {
return false;
}
if (PolicyEngine::pdHasNegotiated()) {
return false; // We are using PD
}
if (hasQCNegotiated()) {
return false; // We are using QC
}
return true;
}

View File

@@ -4,63 +4,55 @@
* Created on: 29 May 2020
* Author: Ralim
*/
#include "gd32vf103_libopt.h"
#include "BSP.h"
#include "Pins.h"
#include "QC3.h"
#include "Settings.h"
#include "gd32vf103_libopt.h"
#ifdef POW_QC
void QC_DPlusZero_Six() {
// pull down D+
gpio_bit_reset(QC_DP_LOW_GPIO_Port, QC_DP_LOW_Pin);
// pull down D+
gpio_bit_reset(QC_DP_LOW_GPIO_Port, QC_DP_LOW_Pin);
}
void QC_DNegZero_Six() {
gpio_bit_set(QC_DM_HIGH_GPIO_Port, QC_DM_HIGH_Pin);
gpio_bit_reset(QC_DM_LOW_GPIO_Port, QC_DM_LOW_Pin);
gpio_bit_set(QC_DM_HIGH_GPIO_Port, QC_DM_HIGH_Pin);
gpio_bit_reset(QC_DM_LOW_GPIO_Port, QC_DM_LOW_Pin);
}
void QC_DPlusThree_Three() {
// pull up D+
gpio_bit_set(QC_DP_LOW_GPIO_Port, QC_DP_LOW_Pin);
// pull up D+
gpio_bit_set(QC_DP_LOW_GPIO_Port, QC_DP_LOW_Pin);
}
void QC_DNegThree_Three() {
gpio_bit_set(QC_DM_LOW_GPIO_Port, QC_DM_LOW_Pin);
gpio_bit_set(QC_DM_HIGH_GPIO_Port, QC_DM_HIGH_Pin);
}
void QC_DM_PullDown() {
gpio_init(USB_DM_LOW_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, USB_DM_Pin);
}
void QC_DM_No_PullDown() {
gpio_init(USB_DM_LOW_GPIO_Port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, USB_DM_Pin);
gpio_bit_set(QC_DM_LOW_GPIO_Port, QC_DM_LOW_Pin);
gpio_bit_set(QC_DM_HIGH_GPIO_Port, QC_DM_HIGH_Pin);
}
void QC_DM_PullDown() { gpio_init(USB_DM_LOW_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, USB_DM_Pin); }
void QC_DM_No_PullDown() { gpio_init(USB_DM_LOW_GPIO_Port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, USB_DM_Pin); }
void QC_Init_GPIO() {
// Setup any GPIO into the right states for QC
//D+ pulldown as output
gpio_init(QC_DP_LOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DP_LOW_Pin);
//Make two D- pins floating
QC_DM_PullDown();
// Setup any GPIO into the right states for QC
// D+ pulldown as output
gpio_init(QC_DP_LOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DP_LOW_Pin);
// Make two D- pins floating
QC_DM_PullDown();
}
void QC_Post_Probe_En() {
//Make two D- pins outputs
gpio_init(QC_DM_LOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DM_LOW_Pin);
gpio_init(QC_DM_HIGH_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DM_HIGH_Pin);
// Make two D- pins outputs
gpio_init(QC_DM_LOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DM_LOW_Pin);
gpio_init(QC_DM_HIGH_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DM_HIGH_Pin);
}
uint8_t QC_DM_PulledDown() {
return gpio_input_bit_get(USB_DM_LOW_GPIO_Port, USB_DM_Pin) == RESET ? 1 : 0;
}
uint8_t QC_DM_PulledDown() { return gpio_input_bit_get(USB_DM_LOW_GPIO_Port, USB_DM_Pin) == RESET ? 1 : 0; }
#endif
void QC_resync() {
#ifdef POW_QC
uint8_t targetvoltage = 90;
if (systemSettings.QCIdealVoltage == 1) {
targetvoltage = 120;
} else if (systemSettings.QCIdealVoltage == 2) {
targetvoltage = 200;
}
uint8_t targetvoltage = 90;
if (systemSettings.QCIdealVoltage == 1) {
targetvoltage = 120;
} else if (systemSettings.QCIdealVoltage == 2) {
targetvoltage = 200;
}
seekQC(targetvoltage, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much
seekQC(targetvoltage, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much
#endif
}

View File

@@ -10,9 +10,8 @@
#include "gd32vf103.h"
#include <string.h>
#define ADC_NORM_CHANNELS 2
#define ADC_NORM_SAMPLES 32
uint16_t ADCReadings[ADC_NORM_SAMPLES *
ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings
#define ADC_NORM_SAMPLES 32
uint16_t ADCReadings[ADC_NORM_SAMPLES * ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings
// Functions
void setup_gpio();
@@ -23,282 +22,263 @@ void setup_timers();
void setup_iwdg();
void hardware_init() {
// GPIO
setup_gpio();
// DMA
setup_dma();
// I2C
setup_i2c();
// ADC's
setup_adc();
// Timers
setup_timers();
// Watchdog
setup_iwdg();
// GPIO
setup_gpio();
// DMA
setup_dma();
// I2C
setup_i2c();
// ADC's
setup_adc();
// Timers
setup_timers();
// Watchdog
setup_iwdg();
/* enable TIMER1 - PWM control timing*/
timer_enable(TIMER1);
timer_enable(TIMER2);
/* enable TIMER1 - PWM control timing*/
timer_enable(TIMER1);
timer_enable(TIMER2);
}
// channel 0 -> temperature sensor, 1-> VIN
uint16_t getADC(uint8_t channel) {
uint32_t sum = 0;
for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++)
sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)];
return sum >> 2;
uint32_t sum = 0;
for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++)
sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)];
return sum >> 2;
}
void setup_gpio() {
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
// Alternate function clock enable
rcu_periph_clock_enable(RCU_AF);
// Buttons as input
gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin);
gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin);
// OLED reset as output
gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ,
OLED_RESET_Pin);
gpio_bit_set(SDA_GPIO_Port, SDA_Pin);
gpio_bit_set(SDA_GPIO_Port, SCL_Pin);
// I2C as AF Open Drain
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_2MHZ,
SDA_Pin | SCL_Pin);
// PWM output as AF Push Pull
gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
PWM_Out_Pin);
// Analog Inputs ... as analog inputs
gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ,
TMP36_INPUT_Pin);
gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ,
TIP_TEMP_Pin);
gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, VIN_Pin);
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
// Alternate function clock enable
rcu_periph_clock_enable(RCU_AF);
// Buttons as input
gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin);
gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin);
// OLED reset as output
gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, OLED_RESET_Pin);
gpio_bit_set(SDA_GPIO_Port, SDA_Pin);
gpio_bit_set(SDA_GPIO_Port, SCL_Pin);
// I2C as AF Open Drain
gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_2MHZ, SDA_Pin | SCL_Pin);
// PWM output as AF Push Pull
gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin);
// Analog Inputs ... as analog inputs
gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, TMP36_INPUT_Pin);
gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, TIP_TEMP_Pin);
gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, VIN_Pin);
// Remap PB4 away from JTAG NJRST
gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE);
// Remap PB4 away from JTAG NJRST
gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE);
// TODO - rest of pins as floating
// TODO - rest of pins as floating
}
void setup_dma() {
// Setup DMA for ADC0
{
/* enable DMA0 clock */
rcu_periph_clock_enable(RCU_DMA0);
rcu_periph_clock_enable(RCU_DMA1);
/* ADC_DMA_channel configuration */
dma_parameter_struct dma_data_parameter;
// Setup DMA for ADC0
{
/* enable DMA0 clock */
rcu_periph_clock_enable(RCU_DMA0);
rcu_periph_clock_enable(RCU_DMA1);
/* ADC_DMA_channel configuration */
dma_parameter_struct dma_data_parameter;
/* ADC DMA_channel configuration */
dma_deinit(DMA0, DMA_CH0);
/* ADC DMA_channel configuration */
dma_deinit(DMA0, DMA_CH0);
/* initialize DMA data mode */
dma_data_parameter.periph_addr = (uint32_t) (&ADC_RDATA(ADC0));
dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_data_parameter.memory_addr = (uint32_t) (ADCReadings);
dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS;
dma_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH0, &dma_data_parameter);
/* initialize DMA data mode */
dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_data_parameter.memory_addr = (uint32_t)(ADCReadings);
dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS;
dma_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH0, &dma_data_parameter);
dma_circulation_enable(DMA0, DMA_CH0);
dma_circulation_enable(DMA0, DMA_CH0);
/* enable DMA channel */
dma_channel_enable(DMA0, DMA_CH0);
}
/* enable DMA channel */
dma_channel_enable(DMA0, DMA_CH0);
}
}
void setup_i2c() {
/* enable I2C0 clock */
rcu_periph_clock_enable(RCU_I2C0);
// Setup I20 at 400kHz
i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2);
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
i2c_enable(I2C0);
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
eclic_irq_enable(I2C0_EV_IRQn, 1, 0);
eclic_irq_enable(I2C0_ER_IRQn, 2, 0);
/* enable I2C0 clock */
rcu_periph_clock_enable(RCU_I2C0);
// Setup I20 at 400kHz
i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2);
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
i2c_enable(I2C0);
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
eclic_irq_enable(I2C0_EV_IRQn, 1, 0);
eclic_irq_enable(I2C0_ER_IRQn, 2, 0);
}
void setup_adc() {
// Setup ADC in normal + injected mode
// Want it to sample handle temp and input voltage normally via dma
// Then injected trigger to sample tip temp
memset(ADCReadings, 0, sizeof(ADCReadings));
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_ADC1);
adc_deinit(ADC0);
adc_deinit(ADC1);
/* config ADC clock */
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16);
// Run in normal parallel + inserted parallel
adc_mode_config(ADC0, ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL);
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE);
adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);
// Align right
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);
// Setup reading 2 channels on regular mode (Handle Temp + dc in)
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS);
adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS);
// Setup the two channels
adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL,
ADC_SAMPLETIME_71POINT5); // temp sensor
adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL,
ADC_SAMPLETIME_71POINT5); // temp sensor
adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL,
ADC_SAMPLETIME_71POINT5); // DC Input voltage
adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL,
ADC_SAMPLETIME_71POINT5); // DC Input voltage
// Setup that we want all 4 inserted readings to be the tip temp
adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4);
adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4);
for (int rank = 0; rank < 4; rank++) {
adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL,
ADC_SAMPLETIME_1POINT5);
adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL,
ADC_SAMPLETIME_1POINT5);
}
// Setup timer 1 channel 0 to trigger injected measurements
adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL,
ADC0_1_EXTTRIG_INSERTED_T1_CH0);
adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL,
ADC0_1_EXTTRIG_INSERTED_T1_CH0);
// Setup ADC in normal + injected mode
// Want it to sample handle temp and input voltage normally via dma
// Then injected trigger to sample tip temp
memset(ADCReadings, 0, sizeof(ADCReadings));
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_ADC1);
adc_deinit(ADC0);
adc_deinit(ADC1);
/* config ADC clock */
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16);
// Run in normal parallel + inserted parallel
adc_mode_config(ADC0, ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL);
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE);
adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);
// Align right
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);
// Setup reading 2 channels on regular mode (Handle Temp + dc in)
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS);
adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS);
// Setup the two channels
adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL,
ADC_SAMPLETIME_71POINT5); // temp sensor
adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL,
ADC_SAMPLETIME_71POINT5); // temp sensor
adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL,
ADC_SAMPLETIME_71POINT5); // DC Input voltage
adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL,
ADC_SAMPLETIME_71POINT5); // DC Input voltage
// Setup that we want all 4 inserted readings to be the tip temp
adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4);
adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4);
for (int rank = 0; rank < 4; rank++) {
adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, ADC_SAMPLETIME_1POINT5);
adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, ADC_SAMPLETIME_1POINT5);
}
// Setup timer 1 channel 0 to trigger injected measurements
adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T1_CH0);
adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T1_CH0);
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL,
ADC0_1_EXTTRIG_REGULAR_NONE);
adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL,
ADC0_1_EXTTRIG_REGULAR_NONE);
// Enable triggers for the ADC
adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE);
adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE);
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE);
adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE);
// Enable triggers for the ADC
adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE);
adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE);
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);
adc_watchdog_disable(ADC0);
adc_watchdog_disable(ADC1);
adc_resolution_config(ADC0, ADC_RESOLUTION_12B);
adc_resolution_config(ADC1, ADC_RESOLUTION_12B);
/* clear the ADC flag */
adc_oversample_mode_disable(ADC0);
adc_oversample_mode_disable(ADC1);
adc_enable(ADC0);
adc_calibration_enable(ADC0);
adc_enable(ADC1);
adc_calibration_enable(ADC1);
adc_dma_mode_enable(ADC0);
// Enable interrupt on end of injected readings
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
adc_interrupt_enable(ADC0, ADC_INT_EOIC);
eclic_irq_enable(ADC0_1_IRQn, 2, 0);
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL);
adc_tempsensor_vrefint_disable();
adc_watchdog_disable(ADC0);
adc_watchdog_disable(ADC1);
adc_resolution_config(ADC0, ADC_RESOLUTION_12B);
adc_resolution_config(ADC1, ADC_RESOLUTION_12B);
/* clear the ADC flag */
adc_oversample_mode_disable(ADC0);
adc_oversample_mode_disable(ADC1);
adc_enable(ADC0);
adc_calibration_enable(ADC0);
adc_enable(ADC1);
adc_calibration_enable(ADC1);
adc_dma_mode_enable(ADC0);
// Enable interrupt on end of injected readings
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);
adc_interrupt_enable(ADC0, ADC_INT_EOIC);
eclic_irq_enable(ADC0_1_IRQn, 2, 0);
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL);
adc_tempsensor_vrefint_disable();
}
void setup_timers() {
// Setup timer 1 to run the actual PWM level
/* enable timer1 clock */
rcu_periph_clock_enable(RCU_TIMER1);
rcu_periph_clock_enable(RCU_TIMER2);
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
{
// deinit to reset the timer
timer_deinit(TIMER1);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER1 configuration */
timer_initpara.prescaler = 5000;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = powerPWM + tempMeasureTicks;
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1, &timer_initpara);
// Setup timer 1 to run the actual PWM level
/* enable timer1 clock */
rcu_periph_clock_enable(RCU_TIMER1);
rcu_periph_clock_enable(RCU_TIMER2);
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
{
// deinit to reset the timer
timer_deinit(TIMER1);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER1 configuration */
timer_initpara.prescaler = 5000;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = powerPWM + tempMeasureTicks;
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1, &timer_initpara);
/* CH0 configured to implement the PWM irq's for the output control*/
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara);
/* CH0 configured to implement the PWM irq's for the output control*/
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0,
powerPWM + holdoffTicks);
timer_channel_output_mode_config(TIMER1, TIMER_CH_0,
TIMER_OC_MODE_PWM1);
timer_channel_output_shadow_config(TIMER1, TIMER_CH_0,
TIMER_OC_SHADOW_DISABLE);
/* CH1 used for irq */
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, powerPWM + holdoffTicks);
timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM1);
timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
/* CH1 used for irq */
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0);
timer_channel_output_mode_config(TIMER1, TIMER_CH_1,
TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1, TIMER_CH_1,
TIMER_OC_SHADOW_DISABLE);
// IRQ
timer_interrupt_enable(TIMER1, TIMER_INT_UP);
timer_interrupt_enable(TIMER1, TIMER_INT_CH1);
}
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0);
timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
// IRQ
timer_interrupt_enable(TIMER1, TIMER_INT_UP);
timer_interrupt_enable(TIMER1, TIMER_INT_CH1);
}
eclic_irq_enable(TIMER1_IRQn, 2, 5);
// Setup timer 2 to control the output signal
{
timer_deinit(TIMER2);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER1 configuration */
timer_initpara.prescaler = 200;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 100;
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2, &timer_initpara);
eclic_irq_enable(TIMER1_IRQn, 2, 5);
// Setup timer 2 to control the output signal
{
timer_deinit(TIMER2);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER1 configuration */
timer_initpara.prescaler = 200;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 100;
timer_initpara.clockdivision = TIMER_CKDIV_DIV4;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2, &timer_initpara);
/* CH0 configuration in PWM mode0 */
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
timer_channel_output_mode_config(TIMER2, TIMER_CH_0,
TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER2, TIMER_CH_0,
TIMER_OC_SHADOW_DISABLE);
timer_auto_reload_shadow_enable(TIMER2);
timer_enable(TIMER2);
}
/* CH0 configuration in PWM mode0 */
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0);
timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
timer_auto_reload_shadow_enable(TIMER2);
timer_enable(TIMER2);
}
}
void setup_iwdg() {
fwdgt_config(0x0FFF, FWDGT_PSC_DIV256);
fwdgt_enable();
fwdgt_config(0x0FFF, FWDGT_PSC_DIV256);
fwdgt_enable();
}
void setupFUSBIRQ() {
// Setup IRQ for USB-PD
gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,
FUSB302_IRQ_Pin);
eclic_irq_enable(EXTI5_9_IRQn, 1, 1);
/* connect key EXTI line to key GPIO pin */
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5);
// Setup IRQ for USB-PD
gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, FUSB302_IRQ_Pin);
eclic_irq_enable(EXTI5_9_IRQn, 1, 1);
/* connect key EXTI line to key GPIO pin */
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5);
/* configure key EXTI line */
exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_5);
/* configure key EXTI line */
exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_5);
}

View File

@@ -30,58 +30,58 @@
*----------------------------------------------------------*/
/* Scheduler includes. */
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
//#define ENABLE_KERNEL_DEBUG
#ifdef ENABLE_KERNEL_DEBUG
#define FREERTOS_PORT_DEBUG(...) printf(__VA_ARGS__)
#define FREERTOS_PORT_DEBUG(...) printf(__VA_ARGS__)
#else
#define FREERTOS_PORT_DEBUG(...)
#define FREERTOS_PORT_DEBUG(...)
#endif
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ SOC_TIMER_FREQ
#define configSYSTICK_CLOCK_HZ SOC_TIMER_FREQ
#endif
#ifndef configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY 0
#define configKERNEL_INTERRUPT_PRIORITY 0
#endif
#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY
// See function prvCheckMaxSysCallPrio and prvCalcMaxSysCallMTH
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 255
// See function prvCheckMaxSysCallPrio and prvCalcMaxSysCallMTH
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 255
#endif
/* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 18 )
#define portFIRST_USER_INTERRUPT_NUMBER (18)
#define SYSTICK_TICK_CONST (configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ)
#define SYSTICK_TICK_CONST (configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ)
/* Masks off all bits but the ECLIC MTH bits in the MTH register. */
#define portMTH_MASK ( 0xFFUL )
#define portMTH_MASK (0xFFUL)
/* Constants required to set up the initial stack. */
#define portINITIAL_MSTATUS ( MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL)
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
#define portINITIAL_MSTATUS (MSTATUS_MPP | MSTATUS_MPIE | MSTATUS_FS_INITIAL)
#define portINITIAL_EXC_RETURN (0xfffffffd)
/* The systick is a 64-bit counter. */
#define portMAX_BIT_NUMBER ( SysTimer_MTIMER_Msk )
#define portMAX_BIT_NUMBER (SysTimer_MTIMER_Msk)
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL )
#define portMISSED_COUNTS_FACTOR (45UL)
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/*
@@ -89,24 +89,24 @@ debugger. */
* file is weak to allow application writers to change the timer used to
* generate the tick interrupt.
*/
void vPortSetupTimerInterrupt( void );
void vPortSetupTimerInterrupt(void);
/*
* Exception handlers.
*/
void xPortSysTickHandler( void );
void xPortSysTickHandler(void);
/*
* Start first task is a separate function so it can be tested in isolation.
*/
extern void prvPortStartFirstTask( void ) __attribute__ (( naked ));
extern void prvPortStartFirstTask(void) __attribute__((naked));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
static void prvTaskExitError(void);
#define xPortSysTickHandler eclic_mtip_handler
#define xPortSysTickHandler eclic_mtip_handler
/*-----------------------------------------------------------*/
@@ -133,24 +133,24 @@ uint8_t uxMaxSysCallMTH = 255;
/*
* The number of SysTick increments that make up one tick period.
*/
#if( configUSE_TICKLESS_IDLE == 1 )
static TickType_t ulTimerCountsForOneTick = 0;
#if (configUSE_TICKLESS_IDLE == 1)
static TickType_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if( configUSE_TICKLESS_IDLE == 1 )
static TickType_t xMaximumPossibleSuppressedTicks = 0;
#if (configUSE_TICKLESS_IDLE == 1)
static TickType_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
#if( configUSE_TICKLESS_IDLE == 1 )
static TickType_t ulStoppedTimerCompensation = 0;
#if (configUSE_TICKLESS_IDLE == 1)
static TickType_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
@@ -158,8 +158,8 @@ uint8_t uxMaxSysCallMTH = 255;
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
#if (configASSERT_DEFINED == 1)
static uint8_t ucMaxSysCallPriority = 0;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
@@ -223,382 +223,356 @@ uint8_t uxMaxSysCallMTH = 255;
* portTASK_RETURN_ADDRESS
* pxCode
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) {
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_MSTATUS; /* MSTATUS */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_MSTATUS; /* MSTATUS */
/* Save code space by skipping register initialisation. */
/* Save code space by skipping register initialisation. */
#ifndef __riscv_32e
pxTopOfStack -= 22; /* X11 - X31. */
pxTopOfStack -= 22; /* X11 - X31. */
#else
pxTopOfStack -= 6; /* X11 - X15. */
pxTopOfStack -= 6; /* X11 - X15. */
#endif
*pxTopOfStack = ( StackType_t ) pvParameters; /* X10/A0 */
pxTopOfStack -= 6; /* X5 - X9 */
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* RA, X1 */
*pxTopOfStack = (StackType_t)pvParameters; /* X10/A0 */
pxTopOfStack -= 6; /* X5 - X9 */
*pxTopOfStack = (StackType_t)portTASK_RETURN_ADDRESS; /* RA, X1 */
pxTopOfStack --;
*pxTopOfStack = ( ( StackType_t ) pxCode ) ; /* PC */
pxTopOfStack--;
*pxTopOfStack = ((StackType_t)pxCode); /* PC */
return pxTopOfStack;
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
volatile uint32_t ulDummy = 0;
static void prvTaskExitError(void) {
volatile uint32_t ulDummy = 0;
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
while( ulDummy == 0 )
{
/* This file calls prvTaskExitError() after the scheduler has been
started to remove a compiler warning about the function being defined
but never called. ulDummy is used purely to quieten other warnings
about code appearing after this function is called - making ulDummy
volatile makes the compiler think the function could return and
therefore not output an 'unreachable code' warning for code that appears
after it. */
/* Sleep and wait for interrupt */
__WFI();
}
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT(uxCriticalNesting == ~0UL);
portDISABLE_INTERRUPTS();
while (ulDummy == 0) {
/* This file calls prvTaskExitError() after the scheduler has been
started to remove a compiler warning about the function being defined
but never called. ulDummy is used purely to quieten other warnings
about code appearing after this function is called - making ulDummy
volatile makes the compiler think the function could return and
therefore not output an 'unreachable code' warning for code that appears
after it. */
/* Sleep and wait for interrupt */
__WFI();
}
}
/*-----------------------------------------------------------*/
static uint8_t prvCheckMaxSysCallPrio( uint8_t max_syscall_prio )
{
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = __ECLIC_INTCTLBITS;
uint8_t lvlbits, temp;
static uint8_t prvCheckMaxSysCallPrio(uint8_t max_syscall_prio) {
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = __ECLIC_INTCTLBITS;
uint8_t lvlbits, temp;
if (nlbits <= intctlbits) {
lvlbits = nlbits;
} else {
lvlbits = intctlbits;
}
if (nlbits <= intctlbits) {
lvlbits = nlbits;
} else {
lvlbits = intctlbits;
}
temp = ((1<<lvlbits) - 1);
if (max_syscall_prio > temp) {
max_syscall_prio = temp;
}
return max_syscall_prio;
temp = ((1 << lvlbits) - 1);
if (max_syscall_prio > temp) {
max_syscall_prio = temp;
}
return max_syscall_prio;
}
static uint8_t prvCalcMaxSysCallMTH( uint8_t max_syscall_prio )
{
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = __ECLIC_INTCTLBITS;
uint8_t lvlbits, lfabits;
uint8_t maxsyscallmth = 0;
uint8_t temp;
static uint8_t prvCalcMaxSysCallMTH(uint8_t max_syscall_prio) {
uint8_t nlbits = __ECLIC_GetCfgNlbits();
uint8_t intctlbits = __ECLIC_INTCTLBITS;
uint8_t lvlbits, lfabits;
uint8_t maxsyscallmth = 0;
uint8_t temp;
if (nlbits <= intctlbits) {
lvlbits = nlbits;
} else {
lvlbits = intctlbits;
}
if (nlbits <= intctlbits) {
lvlbits = nlbits;
} else {
lvlbits = intctlbits;
}
lfabits = 8 - lvlbits;
lfabits = 8 - lvlbits;
temp = ((1<<lvlbits) - 1);
if (max_syscall_prio > temp) {
max_syscall_prio = temp;
}
temp = ((1 << lvlbits) - 1);
if (max_syscall_prio > temp) {
max_syscall_prio = temp;
}
maxsyscallmth = (max_syscall_prio << lfabits) | ((1<<lfabits) - 1);
maxsyscallmth = (max_syscall_prio << lfabits) | ((1 << lfabits) - 1);
return maxsyscallmth;
return maxsyscallmth;
}
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
{
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
BaseType_t xPortStartScheduler(void) {
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. */
configASSERT(configMAX_SYSCALL_INTERRUPT_PRIORITY);
/* Get the real MTH should be set to ECLIC MTH register */
uxMaxSysCallMTH = prvCalcMaxSysCallMTH(configMAX_SYSCALL_INTERRUPT_PRIORITY);
FREERTOS_PORT_DEBUG("Max SysCall MTH is set to 0x%x\n", uxMaxSysCallMTH);
/* Get the real MTH should be set to ECLIC MTH register */
uxMaxSysCallMTH = prvCalcMaxSysCallMTH(configMAX_SYSCALL_INTERRUPT_PRIORITY);
FREERTOS_PORT_DEBUG("Max SysCall MTH is set to 0x%x\n", uxMaxSysCallMTH);
#if( configASSERT_DEFINED == 1 )
{
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = prvCheckMaxSysCallPrio(configMAX_SYSCALL_INTERRUPT_PRIORITY);
FREERTOS_PORT_DEBUG("Max SysCall Priority is set to %d\n", ucMaxSysCallPriority);
}
#endif /* conifgASSERT_DEFINED */
#if (configASSERT_DEFINED == 1)
{
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = prvCheckMaxSysCallPrio(configMAX_SYSCALL_INTERRUPT_PRIORITY);
FREERTOS_PORT_DEBUG("Max SysCall Priority is set to %d\n", ucMaxSysCallPriority);
}
#endif /* conifgASSERT_DEFINED */
__disable_irq();
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
vPortSetupTimerInterrupt();
__disable_irq();
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
prvPortStartFirstTask();
/* Start the first task. */
prvPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. Call
vTaskSwitchContext() so link time optimisation does not remove the
symbol. */
vTaskSwitchContext();
prvTaskExitError();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. Call
vTaskSwitchContext() so link time optimisation does not remove the
symbol. */
vTaskSwitchContext();
prvTaskExitError();
/* Should not get here! */
return 0;
/* Should not get here! */
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
void vPortEndScheduler(void) {
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT(uxCriticalNesting == 1000UL);
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
void vPortEnterCritical(void) {
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if( uxCriticalNesting == 1 )
{
configASSERT( ( __ECLIC_GetMth() & portMTH_MASK ) == uxMaxSysCallMTH );
}
/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if (uxCriticalNesting == 1) {
configASSERT((__ECLIC_GetMth() & portMTH_MASK) == uxMaxSysCallMTH);
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
void vPortExitCritical(void) {
configASSERT(uxCriticalNesting);
uxCriticalNesting--;
if (uxCriticalNesting == 0) {
portENABLE_INTERRUPTS();
}
}
/*-----------------------------------------------------------*/
void vPortAssert( int32_t x )
{
TaskHandle_t th;
if ((x) == 0) {
taskDISABLE_INTERRUPTS();
void vPortAssert(int32_t x) {
TaskHandle_t th;
if ((x) == 0) {
taskDISABLE_INTERRUPTS();
#if (INCLUDE_xTaskGetCurrentTaskHandle == 1)
th = xTaskGetCurrentTaskHandle();
if (th) {
printf("Assert in task %s\n", pcTaskGetName(th));
}
th = xTaskGetCurrentTaskHandle();
if (th) {
printf("Assert in task %s\n", pcTaskGetName(th));
}
#endif
while(1) {
/* Sleep and wait for interrupt */
__WFI();
};
}
while (1) {
/* Sleep and wait for interrupt */
__WFI();
};
}
}
/*-----------------------------------------------------------*/
void xPortTaskSwitch( void )
{
portDISABLE_INTERRUPTS();
/* Clear Software IRQ, A MUST */
SysTimer_ClearSWIRQ();
vTaskSwitchContext();
portENABLE_INTERRUPTS();
void xPortTaskSwitch(void) {
portDISABLE_INTERRUPTS();
/* Clear Software IRQ, A MUST */
SysTimer_ClearSWIRQ();
vTaskSwitchContext();
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known. */
portDISABLE_INTERRUPTS();
{
SysTick_Reload(SYSTICK_TICK_CONST);
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the SWI interrupt. Pend the SWI interrupt. */
portYIELD();
}
void xPortSysTickHandler(void) {
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known. */
portDISABLE_INTERRUPTS();
{
SysTick_Reload(SYSTICK_TICK_CONST);
/* Increment the RTOS tick. */
if (xTaskIncrementTick() != pdFALSE) {
/* A context switch is required. Context switching is performed in
the SWI interrupt. Pend the SWI interrupt. */
portYIELD();
}
portENABLE_INTERRUPTS();
}
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 )
#if (configUSE_TICKLESS_IDLE == 1)
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
volatile TickType_t xModifiableIdleTime, xTickCountBeforeSleep, XLastLoadValue;
__attribute__((weak)) void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime) {
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
volatile TickType_t xModifiableIdleTime, xTickCountBeforeSleep, XLastLoadValue;
FREERTOS_PORT_DEBUG("Enter TickLess %d\n", (uint32_t)xExpectedIdleTime);
FREERTOS_PORT_DEBUG("Enter TickLess %d\n", (uint32_t)xExpectedIdleTime);
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Make sure the SysTick reload value does not overflow the counter. */
if (xExpectedIdleTime > xMaximumPossibleSuppressedTicks) {
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
SysTimer_Stop();
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
SysTimer_Stop();
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods. */
ulReloadValue = ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods. */
ulReloadValue = (ulTimerCountsForOneTick * (xExpectedIdleTime - 1UL));
if (ulReloadValue > ulStoppedTimerCompensation) {
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
__disable_irq();
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
__disable_irq();
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{
/* Restart from whatever is left in the count register to complete
this tick period. */
/* Restart SysTick. */
SysTimer_Start();
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if (eTaskConfirmSleepModeStatus() == eAbortSleep) {
/* Restart from whatever is left in the count register to complete
this tick period. */
/* Restart SysTick. */
SysTimer_Start();
/* Reset the reload register to the value required for normal tick
periods. */
SysTick_Reload(ulTimerCountsForOneTick);
/* Reset the reload register to the value required for normal tick
periods. */
SysTick_Reload(ulTimerCountsForOneTick);
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
__enable_irq();
}
else
{
xTickCountBeforeSleep = xTaskGetTickCount();
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
__enable_irq();
} else {
xTickCountBeforeSleep = xTaskGetTickCount();
/* Set the new reload value. */
SysTick_Reload(ulReloadValue);
/* Set the new reload value. */
SysTick_Reload(ulReloadValue);
/* Get System timer load value before sleep */
XLastLoadValue = SysTimer_GetLoadValue();
/* Get System timer load value before sleep */
XLastLoadValue = SysTimer_GetLoadValue();
/* Restart SysTick. */
SysTimer_Start();
ECLIC_EnableIRQ(SysTimer_IRQn);
__RWMB();
/* Restart SysTick. */
SysTimer_Start();
ECLIC_EnableIRQ(SysTimer_IRQn);
__RWMB();
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 )
{
__WFI();
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. */
__enable_irq();
/* Make sure interrupt enable is executed */
__RWMB();
__FENCE_I();
__NOP();
/* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar
time. */
__disable_irq();
/* Disable the SysTick clock. Again,
the time the SysTick is stopped for is accounted for as best it can
be, but using the tickless mode will inevitably result in some tiny
drift of the time maintained by the kernel with respect to calendar
time*/
ECLIC_DisableIRQ(SysTimer_IRQn);
/* Determine if SysTimer Interrupt is not yet happened,
(in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
if (SysTimer_GetLoadValue() >= (XLastLoadValue + ulReloadValue))
{
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
FREERTOS_PORT_DEBUG("TickLess - SysTimer Interrupt Entered!\n");
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part
ticks). */
xModifiableIdleTime = SysTimer_GetLoadValue();
if ( xModifiableIdleTime > XLastLoadValue ) {
ulCompletedSysTickDecrements = (xModifiableIdleTime - XLastLoadValue);
} else {
ulCompletedSysTickDecrements = (xModifiableIdleTime + portMAX_BIT_NUMBER - XLastLoadValue);
}
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
SysTick_Reload(ulTimerCountsForOneTick);
FREERTOS_PORT_DEBUG("TickLess - External Interrupt Happened!\n");
}
FREERTOS_PORT_DEBUG("End TickLess %d\n", (uint32_t)ulCompleteTickPeriods);
/* Restart SysTick */
vTaskStepTick( ulCompleteTickPeriods );
/* Exit with interrupts enabled. */
ECLIC_EnableIRQ(SysTimer_IRQn);
__enable_irq();
}
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING(xModifiableIdleTime);
if (xModifiableIdleTime > 0) {
__WFI();
}
configPOST_SLEEP_PROCESSING(xExpectedIdleTime);
/* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. */
__enable_irq();
/* Make sure interrupt enable is executed */
__RWMB();
__FENCE_I();
__NOP();
/* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar
time. */
__disable_irq();
/* Disable the SysTick clock. Again,
the time the SysTick is stopped for is accounted for as best it can
be, but using the tickless mode will inevitably result in some tiny
drift of the time maintained by the kernel with respect to calendar
time*/
ECLIC_DisableIRQ(SysTimer_IRQn);
/* Determine if SysTimer Interrupt is not yet happened,
(in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
if (SysTimer_GetLoadValue() >= (XLastLoadValue + ulReloadValue)) {
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
FREERTOS_PORT_DEBUG("TickLess - SysTimer Interrupt Entered!\n");
} else {
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part
ticks). */
xModifiableIdleTime = SysTimer_GetLoadValue();
if (xModifiableIdleTime > XLastLoadValue) {
ulCompletedSysTickDecrements = (xModifiableIdleTime - XLastLoadValue);
} else {
ulCompletedSysTickDecrements = (xModifiableIdleTime + portMAX_BIT_NUMBER - XLastLoadValue);
}
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
SysTick_Reload(ulTimerCountsForOneTick);
FREERTOS_PORT_DEBUG("TickLess - External Interrupt Happened!\n");
}
FREERTOS_PORT_DEBUG("End TickLess %d\n", (uint32_t)ulCompleteTickPeriods);
/* Restart SysTick */
vTaskStepTick(ulCompleteTickPeriods);
/* Exit with interrupts enabled. */
ECLIC_EnableIRQ(SysTimer_IRQn);
__enable_irq();
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
@@ -607,79 +581,77 @@ void xPortSysTickHandler( void )
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( SYSTICK_TICK_CONST );
xMaximumPossibleSuppressedTicks = portMAX_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
FREERTOS_PORT_DEBUG("CountsForOneTick, SuppressedTicks and TimerCompensation: %u, %u, %u\n", \
(uint32_t)ulTimerCountsForOneTick, (uint32_t)xMaximumPossibleSuppressedTicks, (uint32_t)ulStoppedTimerCompensation);
}
#endif /* configUSE_TICKLESS_IDLE */
TickType_t ticks = SYSTICK_TICK_CONST;
__attribute__((weak)) void vPortSetupTimerInterrupt(void) {
/* Calculate the constants required to configure the tick interrupt. */
#if (configUSE_TICKLESS_IDLE == 1)
{
ulTimerCountsForOneTick = (SYSTICK_TICK_CONST);
xMaximumPossibleSuppressedTicks = portMAX_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / (configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ);
FREERTOS_PORT_DEBUG("CountsForOneTick, SuppressedTicks and TimerCompensation: %u, %u, %u\n", (uint32_t)ulTimerCountsForOneTick, (uint32_t)xMaximumPossibleSuppressedTicks,
(uint32_t)ulStoppedTimerCompensation);
}
#endif /* configUSE_TICKLESS_IDLE */
TickType_t ticks = SYSTICK_TICK_CONST;
/* Make SWI and SysTick the lowest priority interrupts. */
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
SysTick_Config(ticks);
ECLIC_DisableIRQ(SysTimer_IRQn);
ECLIC_SetLevelIRQ(SysTimer_IRQn, configKERNEL_INTERRUPT_PRIORITY);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_EnableIRQ(SysTimer_IRQn);
/* Make SWI and SysTick the lowest priority interrupts. */
/* Stop and clear the SysTimer. SysTimer as Non-Vector Interrupt */
SysTick_Config(ticks);
ECLIC_DisableIRQ(SysTimer_IRQn);
ECLIC_SetLevelIRQ(SysTimer_IRQn, configKERNEL_INTERRUPT_PRIORITY);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_EnableIRQ(SysTimer_IRQn);
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, configKERNEL_INTERRUPT_PRIORITY);
ECLIC_EnableIRQ(SysTimerSW_IRQn);
/* Set SWI interrupt level to lowest level/priority, SysTimerSW as Vector Interrupt */
ECLIC_SetShvIRQ(SysTimerSW_IRQn, ECLIC_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimerSW_IRQn, configKERNEL_INTERRUPT_PRIORITY);
ECLIC_EnableIRQ(SysTimerSW_IRQn);
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 )
#if (configASSERT_DEFINED == 1)
void vPortValidateInterruptPriority( void )
{
uint32_t ulCurrentInterrupt;
uint8_t ucCurrentPriority;
void vPortValidateInterruptPriority(void) {
uint32_t ulCurrentInterrupt;
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
CSR_MCAUSE_Type mcause = (CSR_MCAUSE_Type)__RV_CSR_READ(CSR_MCAUSE);
/* Make sure current trap type is interrupt */
configASSERT(mcause.b.interrupt == 1);
if (mcause.b.interrupt) {
ulCurrentInterrupt = mcause.b.exccode;
/* Is the interrupt number a user defined interrupt? */
if ( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) {
/* Look up the interrupt's priority. */
ucCurrentPriority = __ECLIC_GetLevelIRQ(ulCurrentInterrupt);
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
ucMaxSysCallPriority calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
ucMaxSysCallPriority.
/* Obtain the number of the currently executing interrupt. */
CSR_MCAUSE_Type mcause = (CSR_MCAUSE_Type)__RV_CSR_READ(CSR_MCAUSE);
/* Make sure current trap type is interrupt */
configASSERT(mcause.b.interrupt == 1);
if (mcause.b.interrupt) {
ulCurrentInterrupt = mcause.b.exccode;
/* Is the interrupt number a user defined interrupt? */
if (ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER) {
/* Look up the interrupt's priority. */
ucCurrentPriority = __ECLIC_GetLevelIRQ(ulCurrentInterrupt);
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
ucMaxSysCallPriority calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
ucMaxSysCallPriority.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
ucMaxSysCallPriority.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
ucMaxSysCallPriority.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above ucMaxSysCallPriority,
and therefore also guaranteed to be invalid.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above ucMaxSysCallPriority,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority <= ucMaxSysCallPriority );
}
}
The following links provide detailed information:
http://www.freertos.org/FAQHelp.html */
configASSERT(ucCurrentPriority <= ucMaxSysCallPriority);
}
}
}
#endif /* configASSERT_DEFINED */

View File

@@ -8,32 +8,31 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "nuclei_sdk_hal.h"
#include "gd32vf103_usart.h"
#include "gd32vf103_gpio.h"
#include "gd32vf103_exti.h"
#include "gd32vf103_gpio.h"
#include "gd32vf103_usart.h"
#include "nuclei_sdk_hal.h"

View File

@@ -8,27 +8,27 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
@@ -41,192 +41,181 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
static void usb_core_reset (usb_core_regs *usb_regs)
{
/* enable core soft reset */
usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST;
static void usb_core_reset(usb_core_regs *usb_regs) {
/* enable core soft reset */
usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST;
/* wait for the core to be soft reset */
while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST);
/* wait for the core to be soft reset */
while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST)
;
/* wait for addtional 3 PHY clocks */
usb_udelay(3);
/* wait for addtional 3 PHY clocks */
usb_udelay(3);
}
/*!
\brief config USB core basic
\brief config USB core basic
\param[in] usb_basic: pointer to usb capabilities
\param[in] usb_regs: USB core registers
\param[in] usb_core: USB core
\param[out] none
\retval operation status
*/
usb_status usb_basic_init (usb_core_basic *usb_basic,
usb_core_regs *usb_regs,
usb_core_enum usb_core)
{
uint32_t i = 0, reg_base = 0;
usb_status usb_basic_init(usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core) {
uint32_t i = 0, reg_base = 0;
/* config USB default transfer mode as FIFO mode */
usb_basic->transfer_mode = USB_USE_FIFO;
/* config USB default transfer mode as FIFO mode */
usb_basic->transfer_mode = USB_USE_FIFO;
/* USB default speed is full-speed */
usb_basic->core_speed = USB_SPEED_FULL;
/* USB default speed is full-speed */
usb_basic->core_speed = USB_SPEED_FULL;
usb_basic->core_enum = usb_core;
usb_basic->core_enum = usb_core;
switch (usb_core) {
case USB_CORE_ENUM_HS:
reg_base = USBHS_REG_BASE;
switch (usb_core) {
case USB_CORE_ENUM_HS:
reg_base = USBHS_REG_BASE;
/* set the host channel numbers */
usb_basic->num_pipe = USBHS_MAX_CHANNEL_COUNT;
/* set the host channel numbers */
usb_basic->num_pipe = USBHS_MAX_CHANNEL_COUNT;
/* set the device endpoint numbers */
usb_basic->num_ep = USBHS_MAX_EP_COUNT;
/* set the device endpoint numbers */
usb_basic->num_ep = USBHS_MAX_EP_COUNT;
#ifdef USB_ULPI_PHY_ENABLED
usb_basic->phy_itf = USB_ULPI_PHY;
usb_basic->phy_itf = USB_ULPI_PHY;
#else
usb_basic->phy_itf = USB_EMBEDDED_PHY;
usb_basic->phy_itf = USB_EMBEDDED_PHY;
#endif /* USB_ULPI_PHY_ENABLED */
#ifdef USB_HS_INTERNAL_DMA_ENABLED
bp->transfer_mode = USB_USE_DMA;
bp->transfer_mode = USB_USE_DMA;
#endif /* USB_HS_INTERNAL_DMA_ENABLED */
break;
break;
case USB_CORE_ENUM_FS:
reg_base = USBFS_REG_BASE;
case USB_CORE_ENUM_FS:
reg_base = USBFS_REG_BASE;
/* set the host channel numbers */
usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT;
/* set the host channel numbers */
usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT;
/* set the device endpoint numbers */
usb_basic->num_ep = USBFS_MAX_EP_COUNT;
/* set the device endpoint numbers */
usb_basic->num_ep = USBFS_MAX_EP_COUNT;
/* USBFS core use embedded physical layer */
usb_basic->phy_itf = USB_EMBEDDED_PHY;
break;
/* USBFS core use embedded physical layer */
usb_basic->phy_itf = USB_EMBEDDED_PHY;
break;
default:
return USB_FAIL;
}
default:
return USB_FAIL;
}
usb_basic->sof_enable = USB_SOF_OUTPUT;
usb_basic->low_power = USB_LOW_POWER;
usb_basic->sof_enable = USB_SOF_OUTPUT;
usb_basic->low_power = USB_LOW_POWER;
/* assign main registers address */
*usb_regs = (usb_core_regs) {
.gr = (usb_gr*) (reg_base + USB_REG_OFFSET_CORE),
.hr = (usb_hr*) (reg_base + USB_REG_OFFSET_HOST),
.dr = (usb_dr*) (reg_base + USB_REG_OFFSET_DEV),
/* assign main registers address */
*usb_regs = (usb_core_regs){.gr = (usb_gr *)(reg_base + USB_REG_OFFSET_CORE),
.hr = (usb_hr *)(reg_base + USB_REG_OFFSET_HOST),
.dr = (usb_dr *)(reg_base + USB_REG_OFFSET_DEV),
.HPCS = (uint32_t*) (reg_base + USB_REG_OFFSET_PORT),
.PWRCLKCTL = (uint32_t*) (reg_base + USB_REG_OFFSET_PWRCLKCTL)
};
.HPCS = (uint32_t *)(reg_base + USB_REG_OFFSET_PORT),
.PWRCLKCTL = (uint32_t *)(reg_base + USB_REG_OFFSET_PWRCLKCTL)};
/* assign device endpoint registers address */
for (i = 0; i < usb_basic->num_ep; i++) {
usb_regs->er_in[i] = (usb_erin *) \
(reg_base + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP));
/* assign device endpoint registers address */
for (i = 0; i < usb_basic->num_ep; i++) {
usb_regs->er_in[i] = (usb_erin *)(reg_base + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP));
usb_regs->er_out[i] = (usb_erout *)\
(reg_base + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP));
}
usb_regs->er_out[i] = (usb_erout *)(reg_base + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP));
}
/* assign host pipe registers address */
for (i = 0; i < usb_basic->num_pipe; i++) {
usb_regs->pr[i] = (usb_pr *) \
(reg_base + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH));
/* assign host pipe registers address */
for (i = 0; i < usb_basic->num_pipe; i++) {
usb_regs->pr[i] = (usb_pr *)(reg_base + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH));
usb_regs->DFIFO[i] = (uint32_t *) \
(reg_base + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE));
}
usb_regs->DFIFO[i] = (uint32_t *)(reg_base + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE));
}
return USB_OK;
return USB_OK;
}
/*!
\brief initializes the USB controller registers and
\brief initializes the USB controller registers and
prepares the core device mode or host mode operation
\param[in] bp: usb capabilities
\param[in] core_regs: usb core registers
\param[out] none
\retval operation status
*/
usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs)
{
uint32_t reg_value = usb_regs->gr->GCCFG;
usb_status usb_core_init(usb_core_basic usb_basic, usb_core_regs *usb_regs) {
uint32_t reg_value = usb_regs->gr->GCCFG;
/* disable USB global interrupt */
usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN;
/* disable USB global interrupt */
usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN;
if (USB_ULPI_PHY == usb_basic.phy_itf) {
reg_value &= ~GCCFG_PWRON;
if (USB_ULPI_PHY == usb_basic.phy_itf) {
reg_value &= ~GCCFG_PWRON;
if (usb_basic.sof_enable) {
reg_value |= GCCFG_SOFOEN;
}
if (usb_basic.sof_enable) {
reg_value |= GCCFG_SOFOEN;
}
usb_regs->gr->GCCFG = GCCFG_SOFOEN;
usb_regs->gr->GCCFG = GCCFG_SOFOEN;
/* init the ULPI interface */
usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI);
/* init the ULPI interface */
usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI);
#ifdef USBHS_EXTERNAL_VBUS_ENABLED
/* use external VBUS driver */
usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD;
/* use external VBUS driver */
usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD;
#else
/* use internal VBUS driver */
usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD;
/* use internal VBUS driver */
usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD;
#endif
/* soft reset the core */
usb_core_reset (usb_regs);
} else {
usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY;
/* soft reset the core */
usb_core_reset(usb_regs);
} else {
usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY;
/* soft reset the core */
usb_core_reset (usb_regs);
/* soft reset the core */
usb_core_reset(usb_regs);
/* active the transceiver and enable vbus sensing */
reg_value = GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
/* active the transceiver and enable vbus sensing */
reg_value = GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
#ifndef VBUS_SENSING_ENABLED
reg_value |= GCCFG_VBUSIG;
reg_value |= GCCFG_VBUSIG;
#endif /* VBUS_SENSING_ENABLED */
/* enable SOF output */
if (usb_basic.sof_enable) {
reg_value |= GCCFG_SOFOEN;
}
usb_regs->gr->GCCFG = reg_value;
usb_mdelay(20);
/* enable SOF output */
if (usb_basic.sof_enable) {
reg_value |= GCCFG_SOFOEN;
}
if (USB_USE_DMA == usb_basic.transfer_mode) {
usb_regs->gr->GAHBCS |= GAHBCS_DMAEN;
usb_regs->gr->GAHBCS &= ~GAHBCS_BURST;
usb_regs->gr->GAHBCS |= DMA_INCR8;
}
usb_regs->gr->GCCFG = reg_value;
usb_mdelay(20);
}
if (USB_USE_DMA == usb_basic.transfer_mode) {
usb_regs->gr->GAHBCS |= GAHBCS_DMAEN;
usb_regs->gr->GAHBCS &= ~GAHBCS_BURST;
usb_regs->gr->GAHBCS |= DMA_INCR8;
}
#ifdef USE_OTG_MODE
/* enable USB OTG features */
usb_regs->gr->GUSBCS |= GUSBCS_HNPCAP | GUSBCS_SRPCAP;
/* enable USB OTG features */
usb_regs->gr->GUSBCS |= GUSBCS_HNPCAP | GUSBCS_SRPCAP;
/* enable the USB wakeup and suspend interrupts */
usb_regs->gr->GINTF = 0xBFFFFFFFU;
/* enable the USB wakeup and suspend interrupts */
usb_regs->gr->GINTF = 0xBFFFFFFFU;
usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \
GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE;
usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE;
#endif /* USE_OTG_MODE */
return USB_OK;
return USB_OK;
}
/*!
@@ -238,22 +227,18 @@ usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs)
\param[out] none
\retval operation status
*/
usb_status usb_txfifo_write (usb_core_regs *usb_regs,
uint8_t *src_buf,
uint8_t fifo_num,
uint16_t byte_count)
{
uint32_t word_count = (byte_count + 3U) / 4U;
usb_status usb_txfifo_write(usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count) {
uint32_t word_count = (byte_count + 3U) / 4U;
__IO uint32_t *fifo = usb_regs->DFIFO[fifo_num];
__IO uint32_t *fifo = usb_regs->DFIFO[fifo_num];
while (word_count-- > 0) {
*fifo = *(( uint32_t *)src_buf);
while (word_count-- > 0) {
*fifo = *((uint32_t *)src_buf);
src_buf += 4U;
}
src_buf += 4U;
}
return USB_OK;
return USB_OK;
}
/*!
@@ -264,19 +249,18 @@ usb_status usb_txfifo_write (usb_core_regs *usb_regs,
\param[out] none
\retval void type pointer
*/
void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count)
{
uint32_t word_count = (byte_count + 3U) / 4U;
void *usb_rxfifo_read(usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) {
uint32_t word_count = (byte_count + 3U) / 4U;
__IO uint32_t *fifo = usb_regs->DFIFO[0];
__IO uint32_t *fifo = usb_regs->DFIFO[0];
while (word_count-- > 0) {
*( uint32_t *)dest_buf = *fifo;
while (word_count-- > 0) {
*(uint32_t *)dest_buf = *fifo;
dest_buf += 4U;
}
dest_buf += 4U;
}
return ((void *)dest_buf);
return ((void *)dest_buf);
}
/*!
@@ -286,17 +270,17 @@ void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte
\param[out] none
\retval operation status
*/
usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num)
{
usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF;
usb_status usb_txfifo_flush(usb_core_regs *usb_regs, uint8_t fifo_num) {
usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF;
/* wait for Tx FIFO flush bit is set */
while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF);
/* wait for Tx FIFO flush bit is set */
while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF)
;
/* wait for 3 PHY clocks*/
usb_udelay(3);
/* wait for 3 PHY clocks*/
usb_udelay(3);
return USB_OK;
return USB_OK;
}
/*!
@@ -305,15 +289,15 @@ usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num)
\param[out] none
\retval operation status
*/
usb_status usb_rxfifo_flush (usb_core_regs *usb_regs)
{
usb_regs->gr->GRSTCTL = GRSTCTL_RXFF;
usb_status usb_rxfifo_flush(usb_core_regs *usb_regs) {
usb_regs->gr->GRSTCTL = GRSTCTL_RXFF;
/* wait for Rx FIFO flush bit is set */
while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF);
/* wait for Rx FIFO flush bit is set */
while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF)
;
/* wait for 3 PHY clocks */
usb_udelay(3);
/* wait for 3 PHY clocks */
usb_udelay(3);
return USB_OK;
return USB_OK;
}

View File

@@ -8,69 +8,53 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "drv_usb_hw.h"
#include "drv_usb_core.h"
#include "drv_usb_host.h"
#include "drv_usb_core.h"
#include "drv_usb_hw.h"
const uint32_t PIPE_DPID[] = {
PIPE_DPID_DATA0,
PIPE_DPID_DATA1
};
const uint32_t PIPE_DPID[] = {PIPE_DPID_DATA0, PIPE_DPID_DATA1};
//__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *pudev)
uint32_t usb_frame_even (usb_core_driver *pudev)
{
return !(pudev->regs.hr->HFINFR & 0x01U);
}
uint32_t usb_frame_even(usb_core_driver *pudev) { return !(pudev->regs.hr->HFINFR & 0x01U); }
//__STATIC_INLINE void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock)
void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock)
{
pudev->regs.hr->HCTL &= ~HCTL_CLKSEL;
pudev->regs.hr->HCTL |= clock;
void usb_phyclock_config(usb_core_driver *pudev, uint8_t clock) {
pudev->regs.hr->HCTL &= ~HCTL_CLKSEL;
pudev->regs.hr->HCTL |= clock;
}
//__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *pudev)
uint32_t usb_port_read (usb_core_driver *pudev)
{
return *pudev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
}
uint32_t usb_port_read(usb_core_driver *pudev) { return *pudev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); }
//__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *pudev)
uint32_t usb_curspeed_get (usb_core_driver *pudev)
{
return *pudev->regs.HPCS & HPCS_PS;
}
uint32_t usb_curspeed_get(usb_core_driver *pudev) { return *pudev->regs.HPCS & HPCS_PS; }
uint32_t usb_curframe_get (usb_core_driver *pudev)
{
return (pudev->regs.hr->HFINFR & 0xFFFFU);
}
uint32_t usb_curframe_get(usb_core_driver *pudev) { return (pudev->regs.hr->HFINFR & 0xFFFFU); }
/*!
\brief initializes USB core for host mode
@@ -78,118 +62,117 @@ uint32_t usb_curframe_get (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
usb_status usb_host_init (usb_core_driver *pudev)
{
uint32_t i = 0, inten = 0U;
usb_status usb_host_init(usb_core_driver *pudev) {
uint32_t i = 0, inten = 0U;
uint32_t nptxfifolen = 0U;
uint32_t ptxfifolen = 0U;
uint32_t nptxfifolen = 0U;
uint32_t ptxfifolen = 0U;
pudev->regs.gr->GUSBCS &= ~GUSBCS_FDM;
pudev->regs.gr->GUSBCS |= GUSBCS_FHM;
pudev->regs.gr->GUSBCS &= ~GUSBCS_FDM;
pudev->regs.gr->GUSBCS |= GUSBCS_FHM;
/* restart the PHY Clock */
*pudev->regs.PWRCLKCTL = 0U;
/* restart the PHY Clock */
*pudev->regs.PWRCLKCTL = 0U;
/* initialize host configuration register */
if (USB_ULPI_PHY == pudev->bp.phy_itf) {
usb_phyclock_config (pudev, HCTL_30_60MHZ);
} else {
usb_phyclock_config (pudev, HCTL_48MHZ);
}
/* initialize host configuration register */
if (USB_ULPI_PHY == pudev->bp.phy_itf) {
usb_phyclock_config(pudev, HCTL_30_60MHZ);
} else {
usb_phyclock_config(pudev, HCTL_48MHZ);
}
usb_port_reset (pudev);
usb_port_reset(pudev);
/* support FS/LS only */
pudev->regs.hr->HCTL &= ~HCTL_SPDFSLS;
/* support FS/LS only */
pudev->regs.hr->HCTL &= ~HCTL_SPDFSLS;
/* configure data FIFOs size */
/* configure data FIFOs size */
#ifdef USB_FS_CORE
if (USB_CORE_ENUM_FS == pudev->bp.core_enum) {
/* set Rx FIFO size */
pudev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE;
if (USB_CORE_ENUM_FS == pudev->bp.core_enum) {
/* set Rx FIFO size */
pudev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE;
/* set non-periodic Tx FIFO size and address */
nptxfifolen |= USB_RX_FIFO_FS_SIZE;
nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U;
pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen;
/* set non-periodic Tx FIFO size and address */
nptxfifolen |= USB_RX_FIFO_FS_SIZE;
nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U;
pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen;
/* set periodic Tx FIFO size and address */
ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_PFIFO_FS_SIZE;
ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U;
pudev->regs.gr->HPTFLEN = ptxfifolen;
}
/* set periodic Tx FIFO size and address */
ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_PFIFO_FS_SIZE;
ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U;
pudev->regs.gr->HPTFLEN = ptxfifolen;
}
#endif /* USB_FS_CORE */
#ifdef USB_HS_CORE
if (USB_CORE_HS == pudev->cfg.core) {
/* set Rx FIFO size */
pudev->regs.gr->GRFLEN = USBHS_RX_FIFO_SIZE;
if (USB_CORE_HS == pudev->cfg.core) {
/* set Rx FIFO size */
pudev->regs.gr->GRFLEN = USBHS_RX_FIFO_SIZE;
/* set non-periodic Tx FIFO size and address */
nptxfifolen |= USBHS_RX_FIFO_SIZE;
nptxfifolen |= USBHS_HTX_NPFIFO_SIZE;
pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen;
/* set non-periodic Tx FIFO size and address */
nptxfifolen |= USBHS_RX_FIFO_SIZE;
nptxfifolen |= USBHS_HTX_NPFIFO_SIZE;
pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen;
/* set periodic Tx FIFO size and address */
ptxfifolen |= USBHS_RX_FIFO_SIZE + USBHS_HTX_PFIFO_SIZE;
ptxfifolen |= USBHS_HTX_PFIFO_SIZE;
pudev->regs.gr->HPTFLEN = ptxfifolen;
}
/* set periodic Tx FIFO size and address */
ptxfifolen |= USBHS_RX_FIFO_SIZE + USBHS_HTX_PFIFO_SIZE;
ptxfifolen |= USBHS_HTX_PFIFO_SIZE;
pudev->regs.gr->HPTFLEN = ptxfifolen;
}
#endif
#ifdef USE_OTG_MODE
/* clear host set hnp enable in the usb_otg control register */
pudev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN;
/* clear host set hnp enable in the usb_otg control register */
pudev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN;
#endif
/* disable all interrupts */
pudev->regs.gr->GINTEN = 0U;
/* disable all interrupts */
pudev->regs.gr->GINTEN = 0U;
/* clear any pending USB OTG interrupts */
pudev->regs.gr->GOTGINTF = 0xFFFFFFFFU;
/* clear any pending USB OTG interrupts */
pudev->regs.gr->GOTGINTF = 0xFFFFFFFFU;
/* enable the USB wakeup and suspend interrupts */
pudev->regs.gr->GINTF = 0xBFFFFFFFU;
/* enable the USB wakeup and suspend interrupts */
pudev->regs.gr->GINTF = 0xBFFFFFFFU;
/* make sure the FIFOs are flushed */
/* make sure the FIFOs are flushed */
/* flush all Tx FIFOs in device or host mode */
usb_txfifo_flush (&pudev->regs, 0x10U);
/* flush all Tx FIFOs in device or host mode */
usb_txfifo_flush(&pudev->regs, 0x10U);
/* flush the entire Rx FIFO */
usb_rxfifo_flush (&pudev->regs);
/* flush the entire Rx FIFO */
usb_rxfifo_flush(&pudev->regs);
/* clear all pending host channel interrupts */
for (i = 0U; i < pudev->bp.num_pipe; i++) {
pudev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU;
pudev->regs.pr[i]->HCHINTEN = 0U;
}
/* clear all pending host channel interrupts */
for (i = 0U; i < pudev->bp.num_pipe; i++) {
pudev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU;
pudev->regs.pr[i]->HCHINTEN = 0U;
}
#ifndef USE_OTG_MODE
usb_portvbus_switch (pudev, 1U);
usb_portvbus_switch(pudev, 1U);
#endif /* USE_OTG_MODE */
pudev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE;
pudev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE;
/* enable host_mode-related interrupts */
if (USB_USE_FIFO == pudev->bp.transfer_mode) {
inten = GINTEN_RXFNEIE;
}
/* enable host_mode-related interrupts */
if (USB_USE_FIFO == pudev->bp.transfer_mode) {
inten = GINTEN_RXFNEIE;
}
inten |= GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE;
inten |= GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE;
pudev->regs.gr->GINTEN |= inten;
pudev->regs.gr->GINTEN |= inten;
inten = GINTEN_DISCIE | GINTEN_SOFIE;
inten = GINTEN_DISCIE | GINTEN_SOFIE;
pudev->regs.gr->GINTEN &= ~inten;
pudev->regs.gr->GINTEN &= ~inten;
pudev->regs.gr->GAHBCS |= GAHBCS_GINTEN;
pudev->regs.gr->GAHBCS |= GAHBCS_GINTEN;
return USB_OK;
return USB_OK;
}
/*!
@@ -199,27 +182,26 @@ usb_status usb_host_init (usb_core_driver *pudev)
\param[out] none
\retval none
*/
void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state)
{
uint32_t port = 0U;
void usb_portvbus_switch(usb_core_driver *pudev, uint8_t state) {
uint32_t port = 0U;
/* enable or disable the external charge pump */
usb_vbus_drive (state);
/* enable or disable the external charge pump */
usb_vbus_drive(state);
/* turn on the host port power. */
port = usb_port_read (pudev);
/* turn on the host port power. */
port = usb_port_read(pudev);
if (!(port & HPCS_PP) && (1U == state)) {
port |= HPCS_PP;
}
if (!(port & HPCS_PP) && (1U == state)) {
port |= HPCS_PP;
}
if ((port & HPCS_PP) && (0U == state)) {
port &= ~HPCS_PP;
}
if ((port & HPCS_PP) && (0U == state)) {
port &= ~HPCS_PP;
}
*pudev->regs.HPCS = port;
*pudev->regs.HPCS = port;
usb_mdelay (200U);
usb_mdelay(200U);
}
/*!
@@ -228,19 +210,18 @@ void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state)
\param[out] none
\retval operation status
*/
uint32_t usb_port_reset (usb_core_driver *pudev)
{
__IO uint32_t port = usb_port_read (pudev);
uint32_t usb_port_reset(usb_core_driver *pudev) {
__IO uint32_t port = usb_port_read(pudev);
*pudev->regs.HPCS = port | HPCS_PRST;
*pudev->regs.HPCS = port | HPCS_PRST;
usb_mdelay (100U); /* see note */
usb_mdelay(100U); /* see note */
*pudev->regs.HPCS = port & ~HPCS_PRST;
*pudev->regs.HPCS = port & ~HPCS_PRST;
usb_mdelay (20U);
usb_mdelay(20U);
return 1;
return 1;
}
/*!
@@ -250,80 +231,77 @@ uint32_t usb_port_reset (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num)
{
usb_status status = USB_OK;
usb_status usb_pipe_init(usb_core_driver *pudev, uint8_t pipe_num) {
usb_status status = USB_OK;
__IO uint32_t pp_ctl = 0U;
__IO uint32_t pp_inten = HCHINTEN_TFIE;
__IO uint32_t pp_ctl = 0U;
__IO uint32_t pp_inten = HCHINTEN_TFIE;
usb_pipe *pp = &pudev->host.pipe[pipe_num];
usb_pipe *pp = &pudev->host.pipe[pipe_num];
/* clear old interrupt conditions for this host channel */
pudev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU;
/* clear old interrupt conditions for this host channel */
pudev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU;
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pp_inten |= HCHINTEN_DMAERIE;
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pp_inten |= HCHINTEN_DMAERIE;
}
if (pp->ep.dir) {
pp_inten |= HCHINTEN_BBERIE;
}
/* enable channel interrupts required for this transfer */
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE | HCHINTEN_NAKIE;
if (!pp->ep.dir) {
pp_inten |= HCHINTEN_NYETIE;
if (pp->ping) {
pp_inten |= HCHINTEN_ACKIE;
}
}
break;
case USB_EPTYPE_INTR:
pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE;
break;
case USB_EPTYPE_ISOC:
pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE;
if (pp->ep.dir) {
pp_inten |= HCHINTEN_BBERIE;
pp_inten |= HCHINTEN_USBERIE;
}
break;
/* enable channel interrupts required for this transfer */
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \
| HCHINTEN_DTERIE | HCHINTEN_NAKIE;
default:
break;
}
if (!pp->ep.dir) {
pp_inten |= HCHINTEN_NYETIE;
pudev->regs.pr[pipe_num]->HCHINTEN = pp_inten;
if (pp->ping) {
pp_inten |= HCHINTEN_ACKIE;
}
}
break;
/* enable the top level host channel interrupt */
pudev->regs.hr->HACHINTEN |= 1U << pipe_num;
case USB_EPTYPE_INTR:
pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \
| HCHINTEN_NAKIE | HCHINTEN_REQOVRIE;
break;
/* make sure host channel interrupts are enabled */
pudev->regs.gr->GINTEN |= GINTEN_HCIE;
case USB_EPTYPE_ISOC:
pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE;
/* program the host channel control register */
pp_ctl |= PIPE_CTL_DAR(pp->dev_addr);
pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num);
pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir);
pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type);
pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW);
if (pp->ep.dir) {
pp_inten |= HCHINTEN_USBERIE;
}
break;
pp_ctl |= pp->ep.mps;
pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM;
default:
break;
}
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
pudev->regs.pr[pipe_num]->HCHINTEN = pp_inten;
/* enable the top level host channel interrupt */
pudev->regs.hr->HACHINTEN |= 1U << pipe_num;
/* make sure host channel interrupts are enabled */
pudev->regs.gr->GINTEN |= GINTEN_HCIE;
/* program the host channel control register */
pp_ctl |= PIPE_CTL_DAR(pp->dev_addr);
pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num);
pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir);
pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type);
pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW);
pp_ctl |= pp->ep.mps;
pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
return status;
return status;
}
/*!
@@ -333,93 +311,92 @@ usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num)
{
usb_status status = USB_OK;
usb_status usb_pipe_xfer(usb_core_driver *pudev, uint8_t pipe_num) {
usb_status status = USB_OK;
uint16_t dword_len = 0U;
uint16_t packet_count = 0U;
uint16_t dword_len = 0U;
uint16_t packet_count = 0U;
__IO uint32_t pp_ctl = 0U;
__IO uint32_t pp_ctl = 0U;
usb_pipe *pp = &pudev->host.pipe[pipe_num];
usb_pipe *pp = &pudev->host.pipe[pipe_num];
uint16_t max_packet_len = pp->ep.mps;
uint16_t max_packet_len = pp->ep.mps;
/* compute the expected number of packets associated to the transfer */
if (pp->xfer_len > 0U) {
packet_count = (pp->xfer_len + max_packet_len - 1U) / max_packet_len;
/* compute the expected number of packets associated to the transfer */
if (pp->xfer_len > 0U) {
packet_count = (pp->xfer_len + max_packet_len - 1U) / max_packet_len;
if (packet_count > HC_MAX_PACKET_COUNT) {
packet_count = HC_MAX_PACKET_COUNT;
pp->xfer_len = packet_count * max_packet_len;
if (packet_count > HC_MAX_PACKET_COUNT) {
packet_count = HC_MAX_PACKET_COUNT;
pp->xfer_len = packet_count * max_packet_len;
}
} else {
packet_count = 1U;
}
if (pp->ep.dir) {
pp->xfer_len = packet_count * max_packet_len;
}
/* initialize the host channel transfer information */
pudev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count);
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pudev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf;
}
pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
if (usb_frame_even(pudev)) {
pp_ctl |= HCHCTL_ODDFRM;
} else {
pp_ctl &= ~HCHCTL_ODDFRM;
}
/* set host channel enabled */
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
if (USB_USE_FIFO == pudev->bp.transfer_mode) {
if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) {
switch (pp->ep.type) {
/* non-periodic transfer */
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
dword_len = (pp->xfer_len + 3U) / 4U;
/* check if there is enough space in fifo space */
if (dword_len > (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) {
/* need to process data in nptxfempty interrupt */
pudev->regs.gr->GINTEN |= GINTEN_NPTXFEIE;
}
} else {
packet_count = 1U;
}
break;
if (pp->ep.dir) {
pp->xfer_len = packet_count * max_packet_len;
}
/* periodic transfer */
case USB_EPTYPE_INTR:
case USB_EPTYPE_ISOC:
dword_len = (pp->xfer_len + 3U) / 4U;
/* initialize the host channel transfer information */
pudev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count);
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pudev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf;
}
pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
if (usb_frame_even(pudev)) {
pp_ctl |= HCHCTL_ODDFRM;
} else {
pp_ctl &= ~HCHCTL_ODDFRM;
}
/* set host channel enabled */
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
if (USB_USE_FIFO == pudev->bp.transfer_mode) {
if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) {
switch (pp->ep.type) {
/* non-periodic transfer */
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
dword_len = (pp->xfer_len + 3U) / 4U;
/* check if there is enough space in fifo space */
if (dword_len > (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) {
/* need to process data in nptxfempty interrupt */
pudev->regs.gr->GINTEN |= GINTEN_NPTXFEIE;
}
break;
/* periodic transfer */
case USB_EPTYPE_INTR:
case USB_EPTYPE_ISOC:
dword_len = (pp->xfer_len + 3U) / 4U;
/* check if there is enough space in fifo space */
if (dword_len > (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) {
/* need to process data in ptxfempty interrupt */
pudev->regs.gr->GINTEN |= GINTEN_PTXFEIE;
}
break;
default:
break;
}
/* write packet into the tx fifo. */
usb_txfifo_write (&pudev->regs, pp->xfer_buf, pipe_num, pp->xfer_len);
/* check if there is enough space in fifo space */
if (dword_len > (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) {
/* need to process data in ptxfempty interrupt */
pudev->regs.gr->GINTEN |= GINTEN_PTXFEIE;
}
}
break;
return status;
default:
break;
}
/* write packet into the tx fifo. */
usb_txfifo_write(&pudev->regs, pp->xfer_buf, pipe_num, pp->xfer_len);
}
}
return status;
}
/*!
@@ -429,36 +406,35 @@ usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num)
{
__IO uint32_t pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
usb_status usb_pipe_halt(usb_core_driver *pudev, uint8_t pipe_num) {
__IO uint32_t pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
uint8_t ep_type = (pp_ctl & HCHCTL_EPTYPE) >> 18U;
uint8_t ep_type = (pp_ctl & HCHCTL_EPTYPE) >> 18U;
pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS;
pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS;
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
if (0U == (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) {
pp_ctl &= ~HCHCTL_CEN;
}
break;
case USB_EPTYPE_INTR:
case USB_EPTYPE_ISOC:
if (0U == (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) {
pp_ctl &= ~HCHCTL_CEN;
}
break;
default:
break;
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
if (0U == (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) {
pp_ctl &= ~HCHCTL_CEN;
}
break;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
case USB_EPTYPE_INTR:
case USB_EPTYPE_ISOC:
if (0U == (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) {
pp_ctl &= ~HCHCTL_CEN;
}
break;
return USB_OK;
default:
break;
}
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
return USB_OK;
}
/*!
@@ -468,20 +444,19 @@ usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num)
{
uint32_t pp_ctl = 0U;
usb_status usb_pipe_ping(usb_core_driver *pudev, uint8_t pipe_num) {
uint32_t pp_ctl = 0U;
pudev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U));
pudev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U));
pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
return USB_OK;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
return USB_OK;
}
/*!
@@ -490,25 +465,24 @@ usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num)
\param[out] none
\retval none
*/
void usb_host_stop (usb_core_driver *pudev)
{
uint32_t i;
__IO uint32_t pp_ctl = 0U;
void usb_host_stop(usb_core_driver *pudev) {
uint32_t i;
__IO uint32_t pp_ctl = 0U;
pudev->regs.hr->HACHINTEN = 0x0U;
pudev->regs.hr->HACHINT = 0xFFFFFFFFU;
pudev->regs.hr->HACHINTEN = 0x0U;
pudev->regs.hr->HACHINT = 0xFFFFFFFFU;
/* flush out any leftover queued requests. */
for (i = 0U; i < pudev->bp.num_pipe; i++) {
pp_ctl = pudev->regs.pr[i]->HCHCTL;
/* flush out any leftover queued requests. */
for (i = 0U; i < pudev->bp.num_pipe; i++) {
pp_ctl = pudev->regs.pr[i]->HCHCTL;
pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR);
pp_ctl |= HCHCTL_CDIS;
pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR);
pp_ctl |= HCHCTL_CDIS;
pudev->regs.pr[i]->HCHCTL = pp_ctl;
}
pudev->regs.pr[i]->HCHCTL = pp_ctl;
}
/* flush the FIFO */
usb_rxfifo_flush (&pudev->regs);
usb_txfifo_flush (&pudev->regs, 0x10U);
/* flush the FIFO */
usb_rxfifo_flush(&pudev->regs);
usb_txfifo_flush(&pudev->regs, 0x10U);
}

View File

@@ -8,27 +8,27 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_libopt.h"
@@ -36,21 +36,17 @@ OF SUCH DAMAGE.
#include "drv_usbd_int.h"
#include "usbd_transc.h"
static uint32_t usbd_int_epout (usb_core_driver *udev);
static uint32_t usbd_int_epin (usb_core_driver *udev);
static uint32_t usbd_int_rxfifo (usb_core_driver *udev);
static uint32_t usbd_int_reset (usb_core_driver *udev);
static uint32_t usbd_int_enumfinish (usb_core_driver *udev);
static uint32_t usbd_int_suspend (usb_core_driver *udev);
static uint32_t usbd_int_epout(usb_core_driver *udev);
static uint32_t usbd_int_epin(usb_core_driver *udev);
static uint32_t usbd_int_rxfifo(usb_core_driver *udev);
static uint32_t usbd_int_reset(usb_core_driver *udev);
static uint32_t usbd_int_enumfinish(usb_core_driver *udev);
static uint32_t usbd_int_suspend(usb_core_driver *udev);
static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num);
static uint32_t usbd_emptytxfifo_write(usb_core_driver *udev, uint32_t ep_num);
static const uint8_t USB_SPEED[4] = {
[DSTAT_EM_HS_PHY_30MHZ_60MHZ] = USB_SPEED_HIGH,
[DSTAT_EM_FS_PHY_30MHZ_60MHZ] = USB_SPEED_FULL,
[DSTAT_EM_FS_PHY_48MHZ] = USB_SPEED_FULL,
[DSTAT_EM_LS_PHY_6MHZ] = USB_SPEED_LOW
};
static const uint8_t USB_SPEED[4]
= {[DSTAT_EM_HS_PHY_30MHZ_60MHZ] = USB_SPEED_HIGH, [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = USB_SPEED_FULL, [DSTAT_EM_FS_PHY_48MHZ] = USB_SPEED_FULL, [DSTAT_EM_LS_PHY_6MHZ] = USB_SPEED_LOW};
__IO uint8_t setupc_flag = 0U;
@@ -62,34 +58,30 @@ __IO uint8_t setupc_flag = 0U;
\param[out] none
\retval operation status
*/
uint32_t USBD_OTG_EP1OUT_ISR_Handler (usb_core_driver *udev)
{
uint32_t oepintr = 0U;
uint32_t oeplen = 0U;
uint32_t USBD_OTG_EP1OUT_ISR_Handler(usb_core_driver *udev) {
uint32_t oepintr = 0U;
uint32_t oeplen = 0U;
oepintr = udev->regs.er_out[1]->DOEPINTF;
oepintr &= udev->regs.dr->DOEP1INTEN;
oepintr = udev->regs.er_out[1]->DOEPINTF;
oepintr &= udev->regs.dr->DOEP1INTEN;
/* Transfer complete */
if (oepintr & DOEPINTF_TF)
{
/* Clear the bit in DOEPINTn for this interrupt */
udev->regs.er_out[1]->DOEPINTF = DOEPINTF_TF;
/* Transfer complete */
if (oepintr & DOEPINTF_TF) {
/* Clear the bit in DOEPINTn for this interrupt */
udev->regs.er_out[1]->DOEPINTF = DOEPINTF_TF;
if (USB_USE_DMA == udev->bp.transfer_mode)
{
oeplen = udev->regs.er_out[1]->DOEPLEN;
if (USB_USE_DMA == udev->bp.transfer_mode) {
oeplen = udev->regs.er_out[1]->DOEPLEN;
/* ToDo : handle more than one single MPS size packet */
udev->dev.transc_out[1].xfer_count = udev->dev.transc_out[1].usb_transc - \
oeplen & DEPLEN_TLEN;
}
/* RX COMPLETE */
USBD_DCD_INT_fops->DataOutStage(udev, 1);
/* ToDo : handle more than one single MPS size packet */
udev->dev.transc_out[1].xfer_count = udev->dev.transc_out[1].usb_transc - oeplen & DEPLEN_TLEN;
}
return 1;
/* RX COMPLETE */
USBD_DCD_INT_fops->DataOutStage(udev, 1);
}
return 1;
}
/*!
@@ -98,160 +90,153 @@ uint32_t USBD_OTG_EP1OUT_ISR_Handler (usb_core_driver *udev)
\param[out] none
\retval operation status
*/
uint32_t USBD_OTG_EP1IN_ISR_Handler (usb_core_driver *udev)
{
uint32_t inten, intr, emptyen;
uint32_t USBD_OTG_EP1IN_ISR_Handler(usb_core_driver *udev) {
uint32_t inten, intr, emptyen;
inten = udev->regs.dr->DIEP1INTEN;
emptyen = udev->regs.dr->DIEPFEINTEN;
inten = udev->regs.dr->DIEP1INTEN;
emptyen = udev->regs.dr->DIEPFEINTEN;
inten |= ((emptyen >> 1 ) & 0x1) << 7;
inten |= ((emptyen >> 1) & 0x1) << 7;
intr = udev->regs.er_in[1]->DIEPINTF & inten;
intr = udev->regs.er_in[1]->DIEPINTF & inten;
if (intr & DIEPINTF_TF)
{
udev->regs.dr->DIEPFEINTEN &= ~(0x1 << 1);
if (intr & DIEPINTF_TF) {
udev->regs.dr->DIEPFEINTEN &= ~(0x1 << 1);
udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TF;
udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TF;
/* TX COMPLETE */
USBD_DCD_INT_fops->DataInStage(udev, 1);
}
/* TX COMPLETE */
USBD_DCD_INT_fops->DataInStage(udev, 1);
}
if (intr & DIEPINTF_TXFE)
{
DCD_WriteEmptyTxFifo(udev, 1);
if (intr & DIEPINTF_TXFE) {
DCD_WriteEmptyTxFifo(udev, 1);
udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TXFE;
}
udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TXFE;
}
return 1;
return 1;
}
#endif
/*!
\brief USB device-mode interrupts global service routine handler
\param[in] udev: pointer to usb device instance
\param[out] none
\retval none
*/
void usbd_isr (usb_core_driver *udev)
{
if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) {
uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN;
void usbd_isr(usb_core_driver *udev) {
if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) {
uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN;
/* there are no interrupts, avoid spurious interrupt */
if (!intr) {
return;
/* there are no interrupts, avoid spurious interrupt */
if (!intr) {
return;
}
/* OUT endpoints interrupts */
if (intr & GINTF_OEPIF) {
usbd_int_epout(udev);
}
/* IN endpoints interrupts */
if (intr & GINTF_IEPIF) {
usbd_int_epin(udev);
}
/* suspend interrupt */
if (intr & GINTF_SP) {
usbd_int_suspend(udev);
}
/* wakeup interrupt */
if (intr & GINTF_WKUPIF) {
/* inform upper layer by the resume event */
udev->dev.cur_status = udev->dev.backup_status;
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_WKUPIF;
}
/* wakeup interrupt */
if (intr & GINTF_MFIF) {
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_MFIF;
}
/* start of frame interrupt */
if (intr & GINTF_SOF) {
if (udev->dev.class_core->SOF) {
udev->dev.class_core->SOF(udev);
}
if (0U != setupc_flag) {
setupc_flag++;
if (setupc_flag >= 3U) {
usbd_setup_transc(udev);
setupc_flag = 0U;
}
}
/* OUT endpoints interrupts */
if (intr & GINTF_OEPIF) {
usbd_int_epout (udev);
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_SOF;
}
/* IN endpoints interrupts */
if (intr & GINTF_IEPIF) {
usbd_int_epin (udev);
}
/* receive FIFO not empty interrupt */
if (intr & GINTF_RXFNEIF) {
usbd_int_rxfifo(udev);
}
/* suspend interrupt */
if (intr & GINTF_SP) {
usbd_int_suspend (udev);
}
/* USB reset interrupt */
if (intr & GINTF_RST) {
usbd_int_reset(udev);
}
/* wakeup interrupt */
if (intr & GINTF_WKUPIF) {
/* inform upper layer by the resume event */
udev->dev.cur_status = udev->dev.backup_status;
/* enumeration has been done interrupt */
if (intr & GINTF_ENUMFIF) {
usbd_int_enumfinish(udev);
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_WKUPIF;
}
/* incomplete synchronization IN transfer interrupt*/
if (intr & GINTF_ISOINCIF) {
if (NULL != udev->dev.class_core->incomplete_isoc_in) {
udev->dev.class_core->incomplete_isoc_in(udev);
}
/* wakeup interrupt */
if (intr & GINTF_MFIF) {
/* Clear interrupt */
udev->regs.gr->GINTF = GINTF_ISOINCIF;
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_MFIF;
}
/* incomplete synchronization OUT transfer interrupt*/
if (intr & GINTF_ISOONCIF) {
if (NULL != udev->dev.class_core->incomplete_isoc_out) {
udev->dev.class_core->incomplete_isoc_out(udev);
}
/* start of frame interrupt */
if (intr & GINTF_SOF) {
if (udev->dev.class_core->SOF) {
udev->dev.class_core->SOF(udev);
}
if (0U != setupc_flag) {
setupc_flag ++;
if (setupc_flag >= 3U) {
usbd_setup_transc (udev);
setupc_flag = 0U;
}
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_SOF;
}
/* receive FIFO not empty interrupt */
if (intr & GINTF_RXFNEIF) {
usbd_int_rxfifo (udev);
}
/* USB reset interrupt */
if (intr & GINTF_RST) {
usbd_int_reset (udev);
}
/* enumeration has been done interrupt */
if (intr & GINTF_ENUMFIF) {
usbd_int_enumfinish (udev);
}
/* incomplete synchronization IN transfer interrupt*/
if (intr & GINTF_ISOINCIF) {
if (NULL != udev->dev.class_core->incomplete_isoc_in) {
udev->dev.class_core->incomplete_isoc_in(udev);
}
/* Clear interrupt */
udev->regs.gr->GINTF = GINTF_ISOINCIF;
}
/* incomplete synchronization OUT transfer interrupt*/
if (intr & GINTF_ISOONCIF) {
if (NULL != udev->dev.class_core->incomplete_isoc_out) {
udev->dev.class_core->incomplete_isoc_out(udev);
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_ISOONCIF;
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_ISOONCIF;
}
#ifdef VBUS_SENSING_ENABLED
/* Session request interrupt */
if (intr & GINTF_SESIF) {
udev->regs.gr->GINTF = GINTF_SESIF;
}
/* OTG mode interrupt */
if (intr & GINTF_OTGIF) {
if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) {
}
/* Clear OTG interrupt */
udev->regs.gr->GINTF = GINTF_OTGIF;
}
#endif
/* Session request interrupt */
if (intr & GINTF_SESIF) {
udev->regs.gr->GINTF = GINTF_SESIF;
}
/* OTG mode interrupt */
if (intr & GINTF_OTGIF) {
if (udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) {}
/* Clear OTG interrupt */
udev->regs.gr->GINTF = GINTF_OTGIF;
}
#endif
}
}
/*!
@@ -260,52 +245,50 @@ void usbd_isr (usb_core_driver *udev)
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_epout (usb_core_driver *udev)
{
uint32_t epintnum = 0U;
uint32_t ep_num = 0U;
static uint32_t usbd_int_epout(usb_core_driver *udev) {
uint32_t epintnum = 0U;
uint32_t ep_num = 0U;
for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) {
if (epintnum & 0x1) {
__IO uint32_t oepintr = usb_oepintr_read (udev, ep_num);
for (epintnum = usb_oepintnum_read(udev); epintnum; epintnum >>= 1, ep_num++) {
if (epintnum & 0x1) {
__IO uint32_t oepintr = usb_oepintr_read(udev, ep_num);
/* transfer complete interrupt */
if (oepintr & DOEPINTF_TF) {
/* clear the bit in DOEPINTF for this interrupt */
udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF;
/* transfer complete interrupt */
if (oepintr & DOEPINTF_TF) {
/* clear the bit in DOEPINTF for this interrupt */
udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF;
if (USB_USE_DMA == udev->bp.transfer_mode) {
__IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN;
if (USB_USE_DMA == udev->bp.transfer_mode) {
__IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN;
udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \
eplen & DEPLEN_TLEN;
}
/* inform upper layer: data ready */
usbd_out_transc (udev, ep_num);
if (USB_USE_DMA == udev->bp.transfer_mode) {
if ((0U == ep_num) && (USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) {
usb_ctlep_startout (udev);
}
}
}
/* setup phase finished interrupt (control endpoints) */
if (oepintr & DOEPINTF_STPF) {
/* inform the upper layer that a setup packet is available */
if ((0U == ep_num) && (0U != setupc_flag)) {
usbd_setup_transc (udev);
setupc_flag = 0U;
udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF;
}
}
udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - eplen & DEPLEN_TLEN;
}
}
return 1;
/* inform upper layer: data ready */
usbd_out_transc(udev, ep_num);
if (USB_USE_DMA == udev->bp.transfer_mode) {
if ((0U == ep_num) && (USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) {
usb_ctlep_startout(udev);
}
}
}
/* setup phase finished interrupt (control endpoints) */
if (oepintr & DOEPINTF_STPF) {
/* inform the upper layer that a setup packet is available */
if ((0U == ep_num) && (0U != setupc_flag)) {
usbd_setup_transc(udev);
setupc_flag = 0U;
udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF;
}
}
}
}
return 1;
}
/*!
@@ -314,37 +297,36 @@ static uint32_t usbd_int_epout (usb_core_driver *udev)
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_epin (usb_core_driver *udev)
{
uint32_t epintnum = 0U;
uint32_t ep_num = 0U;
static uint32_t usbd_int_epin(usb_core_driver *udev) {
uint32_t epintnum = 0U;
uint32_t ep_num = 0U;
for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) {
if (epintnum & 0x1U) {
__IO uint32_t iepintr = usb_iepintr_read (udev, ep_num);
for (epintnum = usb_iepintnum_read(udev); epintnum; epintnum >>= 1, ep_num++) {
if (epintnum & 0x1U) {
__IO uint32_t iepintr = usb_iepintr_read(udev, ep_num);
if (iepintr & DIEPINTF_TF) {
udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF;
if (iepintr & DIEPINTF_TF) {
udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF;
/* data transmittion is completed */
usbd_in_transc (udev, ep_num);
/* data transmittion is completed */
usbd_in_transc(udev, ep_num);
if (USB_USE_DMA == udev->bp.transfer_mode) {
if ((0U == ep_num) && (USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) {
usb_ctlep_startout (udev);
}
}
}
if (iepintr & DIEPINTF_TXFE) {
usbd_emptytxfifo_write (udev, ep_num);
udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE;
}
if (USB_USE_DMA == udev->bp.transfer_mode) {
if ((0U == ep_num) && (USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) {
usb_ctlep_startout(udev);
}
}
}
}
return 1;
if (iepintr & DIEPINTF_TXFE) {
usbd_emptytxfifo_write(udev, ep_num);
udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE;
}
}
}
return 1;
}
/*!
@@ -353,66 +335,65 @@ static uint32_t usbd_int_epin (usb_core_driver *udev)
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_rxfifo (usb_core_driver *udev)
{
usb_transc *transc = NULL;
static uint32_t usbd_int_rxfifo(usb_core_driver *udev) {
usb_transc *transc = NULL;
uint8_t data_PID = 0;
uint32_t bcount = 0;
uint8_t data_PID = 0;
uint32_t bcount = 0;
__IO uint32_t devrxstat = 0;
__IO uint32_t devrxstat = 0;
/* disable the Rx status queue non-empty interrupt */
udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
/* disable the Rx status queue non-empty interrupt */
udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
/* get the status from the top of the FIFO */
devrxstat = udev->regs.gr->GRSTATP;
/* get the status from the top of the FIFO */
devrxstat = udev->regs.gr->GRSTATP;
transc = &udev->dev.transc_out[devrxstat & GRSTATRP_EPNUM];
transc = &udev->dev.transc_out[devrxstat & GRSTATRP_EPNUM];
bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4;
data_PID = (devrxstat & GRSTATRP_DPID) >> 15;
bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4;
data_PID = (devrxstat & GRSTATRP_DPID) >> 15;
switch ((devrxstat & GRSTATRP_RPCKST) >> 17) {
case RSTAT_GOUT_NAK:
break;
switch ((devrxstat & GRSTATRP_RPCKST) >> 17) {
case RSTAT_GOUT_NAK:
break;
case RSTAT_DATA_UPDT:
if (bcount > 0) {
usb_rxfifo_read (&udev->regs, transc->xfer_buf, bcount);
case RSTAT_DATA_UPDT:
if (bcount > 0) {
usb_rxfifo_read(&udev->regs, transc->xfer_buf, bcount);
transc->xfer_buf += bcount;
transc->xfer_count += bcount;
}
break;
case RSTAT_XFER_COMP:
/* trigger the OUT enpoint interrupt */
break;
case RSTAT_SETUP_COMP:
/* trigger the OUT enpoint interrupt */
break;
case RSTAT_SETUP_UPDT:
if ((transc->ep_addr.num == 0) && (bcount == 8) && (data_PID == DPID_DATA0)) {
/* copy the setup packet received in FIFO into the setup buffer in RAM */
usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, bcount);
transc->xfer_count += bcount;
setupc_flag = 1;
}
break;
default:
break;
transc->xfer_buf += bcount;
transc->xfer_count += bcount;
}
break;
/* enable the Rx status queue level interrupt */
udev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
case RSTAT_XFER_COMP:
/* trigger the OUT enpoint interrupt */
break;
return 1;
case RSTAT_SETUP_COMP:
/* trigger the OUT enpoint interrupt */
break;
case RSTAT_SETUP_UPDT:
if ((transc->ep_addr.num == 0) && (bcount == 8) && (data_PID == DPID_DATA0)) {
/* copy the setup packet received in FIFO into the setup buffer in RAM */
usb_rxfifo_read(&udev->regs, (uint8_t *)&udev->dev.control.req, bcount);
transc->xfer_count += bcount;
setupc_flag = 1;
}
break;
default:
break;
}
/* enable the Rx status queue level interrupt */
udev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
return 1;
}
/*!
@@ -421,65 +402,57 @@ static uint32_t usbd_int_rxfifo (usb_core_driver *udev)
\param[out] none
\retval status
*/
static uint32_t usbd_int_reset (usb_core_driver *udev)
{
uint32_t i;
static uint32_t usbd_int_reset(usb_core_driver *udev) {
uint32_t i;
/* clear the remote wakeup signaling */
udev->regs.dr->DCTL &= ~DCTL_RWKUP;
/* clear the remote wakeup signaling */
udev->regs.dr->DCTL &= ~DCTL_RWKUP;
/* flush the Tx FIFO */
usb_txfifo_flush (&udev->regs, 0);
/* flush the Tx FIFO */
usb_txfifo_flush(&udev->regs, 0);
for (i = 0; i < udev->bp.num_ep; i++) {
udev->regs.er_in[i]->DIEPINTF = 0xFFU;
udev->regs.er_out[i]->DOEPINTF = 0xFFU;
}
for (i = 0; i < udev->bp.num_ep; i++) {
udev->regs.er_in[i]->DIEPINTF = 0xFFU;
udev->regs.er_out[i]->DOEPINTF = 0xFFU;
}
/* clear all pending device endpoint interrupts */
udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
/* clear all pending device endpoint interrupts */
udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
/* enable endpoint 0 interrupts */
udev->regs.dr->DAEPINTEN = 1U | (1U << 16);
/* enable endpoint 0 interrupts */
udev->regs.dr->DAEPINTEN = 1U | (1U << 16);
/* enable OUT endpoint interrupts */
udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN;
/* enable OUT endpoint interrupts */
udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN;
/* enable IN endpoint interrupts */
udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN;
/* enable IN endpoint interrupts */
udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN;
/* reset device address */
udev->regs.dr->DCFG &= ~DCFG_DAR;
udev->dev.dev_addr = 0U;
/* reset device address */
udev->regs.dr->DCFG &= ~DCFG_DAR;
udev->dev.dev_addr = 0U;
/* configure endpoint 0 to receive SETUP packets */
usb_ctlep_startout (udev);
/* configure endpoint 0 to receive SETUP packets */
usb_ctlep_startout(udev);
/* clear USB reset interrupt */
udev->regs.gr->GINTF = GINTF_RST;
/* clear USB reset interrupt */
udev->regs.gr->GINTF = GINTF_RST;
udev->dev.transc_out[0] = (usb_transc) {
.ep_type = USB_EPTYPE_CTRL,
.max_len = USB_FS_EP0_MAX_LEN
};
udev->dev.transc_out[0] = (usb_transc){.ep_type = USB_EPTYPE_CTRL, .max_len = USB_FS_EP0_MAX_LEN};
usb_transc_active (udev, &udev->dev.transc_out[0]);
usb_transc_active(udev, &udev->dev.transc_out[0]);
udev->dev.transc_in[0] = (usb_transc) {
.ep_addr = {
.dir = 1
},
udev->dev.transc_in[0] = (usb_transc){.ep_addr = {.dir = 1},
.ep_type = USB_EPTYPE_CTRL,
.max_len = USB_FS_EP0_MAX_LEN
};
.ep_type = USB_EPTYPE_CTRL,
.max_len = USB_FS_EP0_MAX_LEN};
usb_transc_active (udev, &udev->dev.transc_in[0]);
usb_transc_active(udev, &udev->dev.transc_in[0]);
/* upon reset call usr call back */
udev->dev.cur_status = USBD_DEFAULT;
/* upon reset call usr call back */
udev->dev.cur_status = USBD_DEFAULT;
return 1;
return 1;
}
/*!
@@ -488,30 +461,29 @@ static uint32_t usbd_int_reset (usb_core_driver *udev)
\param[out] none
\retval status
*/
static uint32_t usbd_int_enumfinish (usb_core_driver *udev)
{
uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U);
static uint32_t usbd_int_enumfinish(usb_core_driver *udev) {
uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U);
udev->regs.dr->DCTL &= ~DCTL_CGINAK;
udev->regs.dr->DCTL |= DCTL_CGINAK;
udev->regs.dr->DCTL &= ~DCTL_CGINAK;
udev->regs.dr->DCTL |= DCTL_CGINAK;
udev->regs.gr->GUSBCS &= ~GUSBCS_UTT;
udev->regs.gr->GUSBCS &= ~GUSBCS_UTT;
/* set USB turn-around time based on device speed and PHY interface */
if (USB_SPEED[enum_speed] == USB_SPEED_HIGH) {
udev->bp.core_speed = USB_SPEED_HIGH;
/* set USB turn-around time based on device speed and PHY interface */
if (USB_SPEED[enum_speed] == USB_SPEED_HIGH) {
udev->bp.core_speed = USB_SPEED_HIGH;
udev->regs.gr->GUSBCS |= 0x09 << 10;
} else {
udev->bp.core_speed = USB_SPEED_FULL;
udev->regs.gr->GUSBCS |= 0x09 << 10;
} else {
udev->bp.core_speed = USB_SPEED_FULL;
udev->regs.gr->GUSBCS |= 0x05 << 10;
}
udev->regs.gr->GUSBCS |= 0x05 << 10;
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_ENUMFIF;
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_ENUMFIF;
return 1;
return 1;
}
/*!
@@ -520,27 +492,26 @@ static uint32_t usbd_int_enumfinish (usb_core_driver *udev)
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_suspend (usb_core_driver *udev)
{
__IO uint8_t low_power = udev->bp.low_power;
__IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST);
__IO uint8_t is_configured = (udev->dev.cur_status == USBD_CONFIGURED)? 1U : 0U;
static uint32_t usbd_int_suspend(usb_core_driver *udev) {
__IO uint8_t low_power = udev->bp.low_power;
__IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST);
__IO uint8_t is_configured = (udev->dev.cur_status == USBD_CONFIGURED) ? 1U : 0U;
udev->dev.backup_status = udev->dev.cur_status;
udev->dev.cur_status = USBD_SUSPENDED;
udev->dev.backup_status = udev->dev.cur_status;
udev->dev.cur_status = USBD_SUSPENDED;
if (low_power && suspend && is_configured) {
/* switch-off the otg clocks */
*udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK;
if (low_power && suspend && is_configured) {
/* switch-off the otg clocks */
*udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK;
/* enter DEEP_SLEEP mode with LDO in low power mode */
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
}
/* enter DEEP_SLEEP mode with LDO in low power mode */
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_SP;
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_SP;
return 1U;
return 1U;
}
/*!
@@ -550,46 +521,44 @@ static uint32_t usbd_int_suspend (usb_core_driver *udev)
\param[out] none
\retval status
*/
static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num)
{
usb_transc *transc = NULL;
static uint32_t usbd_emptytxfifo_write(usb_core_driver *udev, uint32_t ep_num) {
usb_transc *transc = NULL;
uint32_t len = 0;
uint32_t word_count = 0;
uint32_t len = 0;
uint32_t word_count = 0;
transc = &udev->dev.transc_in[ep_num];
transc = &udev->dev.transc_in[ep_num];
len = transc->xfer_len - transc->xfer_count;
/* get the data length to write */
if (len > transc->max_len) {
len = transc->max_len;
}
word_count = (len + 3) / 4;
while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) > word_count) && (transc->xfer_count < transc->xfer_len)) {
len = transc->xfer_len - transc->xfer_count;
/* get the data length to write */
if (len > transc->max_len) {
len = transc->max_len;
len = transc->max_len;
}
/* write FIFO in word(4bytes) */
word_count = (len + 3) / 4;
while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) > word_count) && \
(transc->xfer_count < transc->xfer_len)) {
len = transc->xfer_len - transc->xfer_count;
/* write the FIFO */
usb_txfifo_write(&udev->regs, transc->xfer_buf, ep_num, len);
if (len > transc->max_len) {
len = transc->max_len;
}
transc->xfer_buf += len;
transc->xfer_count += len;
/* write FIFO in word(4bytes) */
word_count = (len + 3) / 4;
/* write the FIFO */
usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, len);
transc->xfer_buf += len;
transc->xfer_count += len;
if (transc->xfer_count == transc->xfer_len) {
/* disable the device endpoint FIFO empty interrupt */
udev->regs.dr->DIEPFEINTEN &= ~(0x01 << ep_num);
}
if (transc->xfer_count == transc->xfer_len) {
/* disable the device endpoint FIFO empty interrupt */
udev->regs.dr->DIEPFEINTEN &= ~(0x01 << ep_num);
}
}
return 1;
return 1;
}

View File

@@ -8,57 +8,53 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "drv_usbh_int.h"
#include "drv_usb_core.h"
#include "drv_usb_host.h"
#include "drv_usbh_int.h"
#if defined (__GNUC__) /*!< GNU compiler */
#pragma GCC optimize ("O0")
#if defined(__GNUC__) /*!< GNU compiler */
#pragma GCC optimize("O0")
#endif /* __GNUC__ */
static uint32_t usbh_int_port (usb_core_driver *pudev);
static uint32_t usbh_int_pipe (usb_core_driver *pudev);
static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num);
static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num);
static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev);
static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode);
static uint32_t usbh_int_port(usb_core_driver *pudev);
static uint32_t usbh_int_pipe(usb_core_driver *pudev);
static uint32_t usbh_int_pipe_in(usb_core_driver *pudev, uint32_t pp_num);
static uint32_t usbh_int_pipe_out(usb_core_driver *pudev, uint32_t pp_num);
static uint32_t usbh_int_rxfifonoempty(usb_core_driver *pudev);
static uint32_t usbh_int_txfifoempty(usb_core_driver *pudev, usb_pipe_mode pp_mode);
static inline void usb_pp_halt (usb_core_driver *pudev,
uint8_t pp_num,
uint32_t pp_int,
usb_pipe_staus pp_status)
{
pudev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE;
static inline void usb_pp_halt(usb_core_driver *pudev, uint8_t pp_num, uint32_t pp_int, usb_pipe_staus pp_status) {
pudev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE;
usb_pipe_halt(pudev, pp_num);
usb_pipe_halt(pudev, pp_num);
pudev->regs.pr[pp_num]->HCHINTF = pp_int;
pudev->regs.pr[pp_num]->HCHINTF = pp_int;
pudev->host.pipe[pp_num].pp_status = pp_status;
pudev->host.pipe[pp_num].pp_status = pp_status;
}
/*!
@@ -67,63 +63,62 @@ static inline void usb_pp_halt (usb_core_driver *pudev,
\param[out] none
\retval operation status
*/
uint32_t usbh_isr (usb_core_driver *pudev)
{
uint32_t Retval = 0U;
uint32_t usbh_isr(usb_core_driver *pudev) {
uint32_t Retval = 0U;
__IO uint32_t intr = 0U;
__IO uint32_t intr = 0U;
/* check if host mode */
if (HOST_MODE == (pudev->regs.gr->GINTF & GINTF_COPM)) {
intr = usb_coreintr_get(&pudev->regs);
/* check if host mode */
if (HOST_MODE == (pudev->regs.gr->GINTF & GINTF_COPM)) {
intr = usb_coreintr_get(&pudev->regs);
if (!intr) {
return 0;
}
if (intr & GINTF_SOF) {
usbh_int_fop->SOF(pudev);
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_SOF;
}
if (intr & GINTF_RXFNEIF) {
Retval |= usbh_int_rxfifonoempty (pudev);
}
if (intr & GINTF_NPTXFEIF) {
Retval |= usbh_int_txfifoempty (pudev, PIPE_NON_PERIOD);
}
if (intr & GINTF_PTXFEIF) {
Retval |= usbh_int_txfifoempty (pudev, PIPE_PERIOD);
}
if (intr & GINTF_HCIF) {
Retval |= usbh_int_pipe (pudev);
}
if (intr & GINTF_HPIF) {
Retval |= usbh_int_port (pudev);
}
if (intr & GINTF_DISCIF) {
pudev->host.connect_status = 0U;
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_DISCIF;
}
if (intr & GINTF_ISOONCIF) {
pudev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS;
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_ISOONCIF;
}
if (!intr) {
return 0;
}
return Retval;
if (intr & GINTF_SOF) {
usbh_int_fop->SOF(pudev);
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_SOF;
}
if (intr & GINTF_RXFNEIF) {
Retval |= usbh_int_rxfifonoempty(pudev);
}
if (intr & GINTF_NPTXFEIF) {
Retval |= usbh_int_txfifoempty(pudev, PIPE_NON_PERIOD);
}
if (intr & GINTF_PTXFEIF) {
Retval |= usbh_int_txfifoempty(pudev, PIPE_PERIOD);
}
if (intr & GINTF_HCIF) {
Retval |= usbh_int_pipe(pudev);
}
if (intr & GINTF_HPIF) {
Retval |= usbh_int_port(pudev);
}
if (intr & GINTF_DISCIF) {
pudev->host.connect_status = 0U;
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_DISCIF;
}
if (intr & GINTF_ISOONCIF) {
pudev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS;
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_ISOONCIF;
}
}
return Retval;
}
/*!
@@ -132,22 +127,21 @@ uint32_t usbh_isr (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_pipe (usb_core_driver *pudev)
{
uint32_t pp_num = 0U;
uint32_t retval = 0U;
static uint32_t usbh_int_pipe(usb_core_driver *pudev) {
uint32_t pp_num = 0U;
uint32_t retval = 0U;
for (pp_num = 0U; pp_num < pudev->bp.num_pipe; pp_num++) {
if ((pudev->regs.hr->HACHINT & HACHINT_HACHINT) & (1U << pp_num)) {
if (pudev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) {
retval |= usbh_int_pipe_in (pudev, pp_num);
} else {
retval |= usbh_int_pipe_out (pudev, pp_num);
}
}
for (pp_num = 0U; pp_num < pudev->bp.num_pipe; pp_num++) {
if ((pudev->regs.hr->HACHINT & HACHINT_HACHINT) & (1U << pp_num)) {
if (pudev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) {
retval |= usbh_int_pipe_in(pudev, pp_num);
} else {
retval |= usbh_int_pipe_out(pudev, pp_num);
}
}
}
return retval;
return retval;
}
/*!
@@ -156,51 +150,50 @@ static uint32_t usbh_int_pipe (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode)
{
uint8_t pp_num = 0U;
uint16_t word_count = 0U, len = 0U;
__IO uint32_t *txfiforeg = 0U, txfifostate = 0U;
static uint32_t usbh_int_txfifoempty(usb_core_driver *pudev, usb_pipe_mode pp_mode) {
uint8_t pp_num = 0U;
uint16_t word_count = 0U, len = 0U;
__IO uint32_t *txfiforeg = 0U, txfifostate = 0U;
if (PIPE_NON_PERIOD == pp_mode) {
txfiforeg = &pudev->regs.gr->HNPTFQSTAT;
} else if (PIPE_PERIOD == pp_mode) {
txfiforeg = &pudev->regs.hr->HPTFQSTAT;
} else {
return 0U;
if (PIPE_NON_PERIOD == pp_mode) {
txfiforeg = &pudev->regs.gr->HNPTFQSTAT;
} else if (PIPE_PERIOD == pp_mode) {
txfiforeg = &pudev->regs.hr->HPTFQSTAT;
} else {
return 0U;
}
txfifostate = *txfiforeg;
pp_num = (txfifostate & TFQSTAT_CNUM) >> 27U;
word_count = (pudev->host.pipe[pp_num].xfer_len + 3U) / 4U;
while (((txfifostate & TFQSTAT_TXFS) > word_count) && (0U != pudev->host.pipe[pp_num].xfer_len)) {
len = (txfifostate & TFQSTAT_TXFS) * 4U;
if (len > pudev->host.pipe[pp_num].xfer_len) {
/* last packet */
len = pudev->host.pipe[pp_num].xfer_len;
if (PIPE_NON_PERIOD == pp_mode) {
pudev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE;
} else {
pudev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE;
}
}
txfifostate = *txfiforeg;
pp_num = (txfifostate & TFQSTAT_CNUM) >> 27U;
word_count = (pudev->host.pipe[pp_num].xfer_len + 3U) / 4U;
usb_txfifo_write(&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, pp_num, len);
while (((txfifostate & TFQSTAT_TXFS) > word_count) && (0U != pudev->host.pipe[pp_num].xfer_len)) {
len = (txfifostate & TFQSTAT_TXFS) * 4U;
pudev->host.pipe[pp_num].xfer_buf += len;
pudev->host.pipe[pp_num].xfer_len -= len;
pudev->host.pipe[pp_num].xfer_count += len;
if (len > pudev->host.pipe[pp_num].xfer_len) {
/* last packet */
len = pudev->host.pipe[pp_num].xfer_len;
txfifostate = *txfiforeg;
}
if (PIPE_NON_PERIOD == pp_mode) {
pudev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE;
} else {
pudev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE;
}
}
word_count = (pudev->host.pipe[pp_num].xfer_len + 3U) / 4U;
usb_txfifo_write (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, pp_num, len);
pudev->host.pipe[pp_num].xfer_buf += len;
pudev->host.pipe[pp_num].xfer_len -= len;
pudev->host.pipe[pp_num].xfer_count += len;
txfifostate = *txfiforeg;
}
return 1;
return 1;
}
/*!
@@ -209,64 +202,63 @@ static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_m
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_port (usb_core_driver *pudev)
{
uint32_t retval = 0U;
static uint32_t usbh_int_port(usb_core_driver *pudev) {
uint32_t retval = 0U;
__IO uint32_t port_state = *pudev->regs.HPCS;
__IO uint32_t port_state = *pudev->regs.HPCS;
/* clear the interrupt bits in GINTSTS */
port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
/* clear the interrupt bits in GINTSTS */
port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
/* port connect detected */
if (*pudev->regs.HPCS & HPCS_PCD) {
port_state |= HPCS_PCD;
/* port connect detected */
if (*pudev->regs.HPCS & HPCS_PCD) {
port_state |= HPCS_PCD;
pudev->host.connect_status = 1U;
pudev->host.connect_status = 1U;
retval |= 1U;
}
retval |= 1U;
}
/* port enable changed */
if (*pudev->regs.HPCS & HPCS_PEDC) {
port_state |= HPCS_PEDC;
/* port enable changed */
if (*pudev->regs.HPCS & HPCS_PEDC) {
port_state |= HPCS_PEDC;
if (*pudev->regs.HPCS & HPCS_PE) {
uint32_t port_speed = usb_curspeed_get(pudev);
uint32_t clock_type = pudev->regs.hr->HCTL & HCTL_CLKSEL;
if (*pudev->regs.HPCS & HPCS_PE) {
uint32_t port_speed = usb_curspeed_get(pudev);
uint32_t clock_type = pudev->regs.hr->HCTL & HCTL_CLKSEL;
pudev->host.connect_status = 1U;
pudev->host.connect_status = 1U;
if (PORT_SPEED_LOW == port_speed) {
pudev->regs.hr->HFT = 6000U;
if (PORT_SPEED_LOW == port_speed) {
pudev->regs.hr->HFT = 6000U;
if (HCTL_6MHZ != clock_type) {
if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) {
usb_phyclock_config (pudev, HCTL_6MHZ);
}
}
} else if (PORT_SPEED_FULL == port_speed) {
pudev->regs.hr->HFT = 48000U;
if (HCTL_48MHZ != clock_type) {
usb_phyclock_config (pudev, HCTL_48MHZ);
}
} else {
/* for high speed device and others */
}
pudev->host.port_enabled = 1U;
pudev->regs.gr->GINTEN |= GINTEN_DISCIE;
} else {
pudev->host.port_enabled = 0U;
if (HCTL_6MHZ != clock_type) {
if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) {
usb_phyclock_config(pudev, HCTL_6MHZ);
}
}
} else if (PORT_SPEED_FULL == port_speed) {
pudev->regs.hr->HFT = 48000U;
if (HCTL_48MHZ != clock_type) {
usb_phyclock_config(pudev, HCTL_48MHZ);
}
} else {
/* for high speed device and others */
}
pudev->host.port_enabled = 1U;
pudev->regs.gr->GINTEN |= GINTEN_DISCIE;
} else {
pudev->host.port_enabled = 0U;
}
}
/* clear port interrupts */
*pudev->regs.HPCS = port_state;
/* clear port interrupts */
*pudev->regs.HPCS = port_state;
return retval;
return retval;
}
/*!
@@ -276,78 +268,77 @@ static uint32_t usbh_int_port (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num)
{
usb_pr *pp_reg = pudev->regs.pr[pp_num];
uint32_t usbh_int_pipe_out(usb_core_driver *pudev, uint32_t pp_num) {
usb_pr *pp_reg = pudev->regs.pr[pp_num];
usb_pipe *pp = &pudev->host.pipe[pp_num];
usb_pipe *pp = &pudev->host.pipe[pp_num];
uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN;
uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN;
if (intr_pp & HCHINTF_ACK) {
pp_reg->HCHINTF = HCHINTF_ACK;
} else if (intr_pp & HCHINTF_STALL) {
usb_pp_halt (pudev, pp_num, HCHINTF_STALL, PIPE_STALL);
} else if (intr_pp & HCHINTF_DTER) {
usb_pp_halt (pudev, pp_num, HCHINTF_DTER, PIPE_DTGERR);
pp_reg->HCHINTF = HCHINTF_NAK;
} else if (intr_pp & HCHINTF_REQOVR) {
usb_pp_halt (pudev, pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
} else if (intr_pp & HCHINTF_TF) {
if (intr_pp & HCHINTF_ACK) {
pp_reg->HCHINTF = HCHINTF_ACK;
} else if (intr_pp & HCHINTF_STALL) {
usb_pp_halt(pudev, pp_num, HCHINTF_STALL, PIPE_STALL);
} else if (intr_pp & HCHINTF_DTER) {
usb_pp_halt(pudev, pp_num, HCHINTF_DTER, PIPE_DTGERR);
pp_reg->HCHINTF = HCHINTF_NAK;
} else if (intr_pp & HCHINTF_REQOVR) {
usb_pp_halt(pudev, pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
} else if (intr_pp & HCHINTF_TF) {
pp->err_count = 0U;
usb_pp_halt(pudev, pp_num, HCHINTF_TF, PIPE_XF);
} else if (intr_pp & HCHINTF_NAK) {
pp->err_count = 0U;
usb_pp_halt(pudev, pp_num, HCHINTF_NAK, PIPE_NAK);
} else if (intr_pp & HCHINTF_USBER) {
pp->err_count++;
usb_pp_halt(pudev, pp_num, HCHINTF_USBER, PIPE_TRACERR);
} else if (intr_pp & HCHINTF_NYET) {
pp->err_count = 0U;
usb_pp_halt(pudev, pp_num, HCHINTF_NYET, PIPE_NYET);
} else if (intr_pp & HCHINTF_CH) {
pudev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE;
switch (pp->pp_status) {
case PIPE_XF:
pp->urb_state = URB_DONE;
if (USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
pp->data_toggle_out ^= 1U;
}
break;
case PIPE_NAK:
pp->urb_state = URB_NOTREADY;
break;
case PIPE_NYET:
if (1U == pudev->host.pipe[pp_num].ping) {
usb_pipe_ping(pudev, pp_num);
}
pp->urb_state = URB_NOTREADY;
break;
case PIPE_STALL:
pp->urb_state = URB_STALL;
break;
case PIPE_TRACERR:
if (3U == pp->err_count) {
pp->urb_state = URB_ERROR;
pp->err_count = 0U;
usb_pp_halt (pudev, pp_num, HCHINTF_TF, PIPE_XF);
} else if (intr_pp & HCHINTF_NAK) {
pp->err_count = 0U;
usb_pp_halt (pudev, pp_num, HCHINTF_NAK, PIPE_NAK);
} else if (intr_pp & HCHINTF_USBER) {
pp->err_count++;
usb_pp_halt (pudev, pp_num, HCHINTF_USBER, PIPE_TRACERR);
} else if (intr_pp & HCHINTF_NYET) {
pp->err_count = 0U;
usb_pp_halt (pudev, pp_num, HCHINTF_NYET, PIPE_NYET);
} else if (intr_pp & HCHINTF_CH) {
pudev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE;
}
break;
switch (pp->pp_status) {
case PIPE_XF:
pp->urb_state = URB_DONE;
if (USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
pp->data_toggle_out ^= 1U;
}
break;
case PIPE_NAK:
pp->urb_state = URB_NOTREADY;
break;
case PIPE_NYET:
if (1U == pudev->host.pipe[pp_num].ping) {
usb_pipe_ping (pudev, pp_num);
}
pp->urb_state = URB_NOTREADY;
break;
case PIPE_STALL:
pp->urb_state = URB_STALL;
break;
case PIPE_TRACERR:
if (3U == pp->err_count) {
pp->urb_state = URB_ERROR;
pp->err_count = 0U;
}
break;
default:
break;
}
pp_reg->HCHINTF = HCHINTF_CH;
default:
break;
}
return 1;
pp_reg->HCHINTF = HCHINTF_CH;
}
return 1;
}
/*!
@@ -357,112 +348,111 @@ uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num)
\param[out] none
\retval operation status
*/
uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num)
{
usb_pr *pp_reg = pudev->regs.pr[pp_num];
uint32_t usbh_int_pipe_in(usb_core_driver *pudev, uint32_t pp_num) {
usb_pr *pp_reg = pudev->regs.pr[pp_num];
usb_pipe *pp = &pudev->host.pipe[pp_num];
usb_pipe *pp = &pudev->host.pipe[pp_num];
__IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN;
__IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN;
uint8_t ep_type = (pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U;
uint8_t ep_type = (pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U;
if (intr_pp & HCHINTF_ACK) {
pp_reg->HCHINTF = HCHINTF_ACK;
} else if (intr_pp & HCHINTF_STALL) {
usb_pp_halt (pudev, pp_num, HCHINTF_STALL, PIPE_STALL);
pp_reg->HCHINTF = HCHINTF_NAK;
if (intr_pp & HCHINTF_ACK) {
pp_reg->HCHINTF = HCHINTF_ACK;
} else if (intr_pp & HCHINTF_STALL) {
usb_pp_halt(pudev, pp_num, HCHINTF_STALL, PIPE_STALL);
pp_reg->HCHINTF = HCHINTF_NAK;
/* note: When there is a 'STALL', reset also nak,
else, the pudev->host.pp_status = HC_STALL
will be overwritten by 'NAK' in code below */
intr_pp &= ~HCHINTF_NAK;
} else if (intr_pp & HCHINTF_DTER) {
usb_pp_halt (pudev, pp_num, HCHINTF_DTER, PIPE_DTGERR);
pp_reg->HCHINTF = HCHINTF_NAK;
/* note: When there is a 'STALL', reset also nak,
else, the pudev->host.pp_status = HC_STALL
will be overwritten by 'NAK' in code below */
intr_pp &= ~HCHINTF_NAK;
} else if (intr_pp & HCHINTF_DTER) {
usb_pp_halt(pudev, pp_num, HCHINTF_DTER, PIPE_DTGERR);
pp_reg->HCHINTF = HCHINTF_NAK;
}
if (intr_pp & HCHINTF_REQOVR) {
usb_pp_halt(pudev, pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
} else if (intr_pp & HCHINTF_TF) {
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pudev->host.backup_xfercount[pp_num] = pp->xfer_len - pp_reg->HCHLEN & HCHLEN_TLEN;
}
if (intr_pp & HCHINTF_REQOVR) {
usb_pp_halt (pudev, pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
} else if (intr_pp & HCHINTF_TF) {
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pudev->host.backup_xfercount[pp_num] = pp->xfer_len - pp_reg->HCHLEN & HCHLEN_TLEN;
}
pp->pp_status = PIPE_XF;
pp->err_count = 0U;
pp->pp_status = PIPE_XF;
pp->err_count = 0U;
pp_reg->HCHINTF = HCHINTF_TF;
pp_reg->HCHINTF = HCHINTF_TF;
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
usb_pp_halt(pudev, pp_num, HCHINTF_NAK, PIPE_XF);
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
usb_pp_halt (pudev, pp_num, HCHINTF_NAK, PIPE_XF);
pp->data_toggle_in ^= 1U;
break;
pp->data_toggle_in ^= 1U;
break;
case USB_EPTYPE_INTR:
pp_reg->HCHCTL |= HCHCTL_ODDFRM;
pp->urb_state = URB_DONE;
break;
case USB_EPTYPE_INTR:
pp_reg->HCHCTL |= HCHCTL_ODDFRM;
pp->urb_state = URB_DONE;
break;
default:
break;
}
} else if (intr_pp & HCHINTF_CH) {
pp_reg->HCHINTEN &= ~HCHINTEN_CHIE;
default:
break;
}
} else if (intr_pp & HCHINTF_CH) {
pp_reg->HCHINTEN &= ~HCHINTEN_CHIE;
switch (pp->pp_status) {
case PIPE_XF:
pp->urb_state = URB_DONE;
break;
switch (pp->pp_status) {
case PIPE_XF:
pp->urb_state = URB_DONE;
break;
case PIPE_STALL:
pp->urb_state = URB_STALL;
break;
case PIPE_STALL:
pp->urb_state = URB_STALL;
break;
case PIPE_TRACERR:
case PIPE_DTGERR:
pp->err_count = 0U;
pp->urb_state = URB_ERROR;
break;
case PIPE_TRACERR:
case PIPE_DTGERR:
pp->err_count = 0U;
pp->urb_state = URB_ERROR;
break;
default:
if(USB_EPTYPE_INTR == ep_type) {
pp->data_toggle_in ^= 1U;
}
break;
}
pp_reg->HCHINTF = HCHINTF_CH;
} else if (intr_pp & HCHINTF_BBER) {
pp->err_count++;
usb_pp_halt (pudev, pp_num, HCHINTF_BBER, PIPE_TRACERR);
} else if (intr_pp & HCHINTF_NAK) {
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
/* re-activate the channel */
pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS;
break;
case USB_EPTYPE_INTR:
pp_reg->HCHINTEN |= HCHINTEN_CHIE;
usb_pipe_halt(pudev, pp_num);
break;
default:
break;
}
pp->pp_status = PIPE_NAK;
pp_reg->HCHINTF = HCHINTF_NAK;
default:
if (USB_EPTYPE_INTR == ep_type) {
pp->data_toggle_in ^= 1U;
}
break;
}
return 1;
pp_reg->HCHINTF = HCHINTF_CH;
} else if (intr_pp & HCHINTF_BBER) {
pp->err_count++;
usb_pp_halt(pudev, pp_num, HCHINTF_BBER, PIPE_TRACERR);
} else if (intr_pp & HCHINTF_NAK) {
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
/* re-activate the channel */
pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS;
break;
case USB_EPTYPE_INTR:
pp_reg->HCHINTEN |= HCHINTEN_CHIE;
usb_pipe_halt(pudev, pp_num);
break;
default:
break;
}
pp->pp_status = PIPE_NAK;
pp_reg->HCHINTF = HCHINTF_NAK;
}
return 1;
}
/*!
@@ -471,66 +461,65 @@ uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num)
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev)
{
uint32_t count = 0U;
static uint32_t usbh_int_rxfifonoempty(usb_core_driver *pudev) {
uint32_t count = 0U;
__IO uint8_t pp_num = 0U;
__IO uint32_t rx_stat = 0U;
__IO uint8_t pp_num = 0U;
__IO uint32_t rx_stat = 0U;
/* disable the rx status queue level interrupt */
pudev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
/* disable the rx status queue level interrupt */
pudev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
rx_stat = pudev->regs.gr->GRSTATP;
pp_num = rx_stat & GRSTATRP_CNUM;
rx_stat = pudev->regs.gr->GRSTATP;
pp_num = rx_stat & GRSTATRP_CNUM;
switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) {
case GRXSTS_PKTSTS_IN:
count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) {
case GRXSTS_PKTSTS_IN:
count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
/* read the data into the host buffer. */
if ((count > 0U) && (NULL != pudev->host.pipe[pp_num].xfer_buf)) {
usb_rxfifo_read (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, count);
/* read the data into the host buffer. */
if ((count > 0U) && (NULL != pudev->host.pipe[pp_num].xfer_buf)) {
usb_rxfifo_read(&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, count);
/* manage multiple transfer packet */
pudev->host.pipe[pp_num].xfer_buf += count;
pudev->host.pipe[pp_num].xfer_count += count;
/* manage multiple transfer packet */
pudev->host.pipe[pp_num].xfer_buf += count;
pudev->host.pipe[pp_num].xfer_count += count;
pudev->host.backup_xfercount[pp_num] = pudev->host.pipe[pp_num].xfer_count;
pudev->host.backup_xfercount[pp_num] = pudev->host.pipe[pp_num].xfer_count;
if (pudev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) {
/* re-activate the channel when more packets are expected */
__IO uint32_t pp_ctl = pudev->regs.pr[pp_num]->HCHCTL;
if (pudev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) {
/* re-activate the channel when more packets are expected */
__IO uint32_t pp_ctl = pudev->regs.pr[pp_num]->HCHCTL;
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pudev->regs.pr[pp_num]->HCHCTL = pp_ctl;
}
}
break;
case GRXSTS_PKTSTS_IN_XFER_COMP:
break;
case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
while (count > 0U) {
rx_stat = pudev->regs.gr->GRSTATP;
count--;
}
break;
case GRXSTS_PKTSTS_CH_HALTED:
break;
default:
break;
pudev->regs.pr[pp_num]->HCHCTL = pp_ctl;
}
}
break;
/* enable the rx status queue level interrupt */
pudev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
case GRXSTS_PKTSTS_IN_XFER_COMP:
break;
return 1;
case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
while (count > 0U) {
rx_stat = pudev->regs.gr->GRSTATP;
count--;
}
break;
case GRXSTS_PKTSTS_CH_HALTED:
break;
default:
break;
}
/* enable the rx status queue level interrupt */
pudev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
return 1;
}

View File

@@ -8,49 +8,48 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_libopt.h"
#include "drv_usb_hw.h"
#include "gd32vf103_libopt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TIM_MSEC_DELAY 0x01
#define TIM_USEC_DELAY 0x02
#define TIM_MSEC_DELAY 0x01
#define TIM_USEC_DELAY 0x02
#define HOST_POWERSW_PORT_RCC RCU_GPIOD
#define HOST_POWERSW_PORT GPIOD
#define HOST_POWERSW_VBUS GPIO_PIN_13
#define HOST_POWERSW_PORT_RCC RCU_GPIOD
#define HOST_POWERSW_PORT GPIOD
#define HOST_POWERSW_VBUS GPIO_PIN_13
__IO uint32_t delay_time = 0;
__IO uint32_t delay_time = 0;
__IO uint32_t usbfs_prescaler = 0;
__IO uint32_t timer_prescaler = 5;
static void hwp_time_set (uint8_t unit);
static void hwp_delay (uint32_t ntime, uint8_t unit);
static void hwp_time_set(uint8_t unit);
static void hwp_delay(uint32_t ntime, uint8_t unit);
/*!
\brief configure USB clock
@@ -58,25 +57,24 @@ static void hwp_delay (uint32_t ntime, uint8_t unit);
\param[out] none
\retval none
*/
void usb_rcu_config (void)
{
uint32_t system_clock = rcu_clock_freq_get(CK_SYS);
if (system_clock == 48000000) {
usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1;
timer_prescaler = 3;
} else if (system_clock == 72000000) {
usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1_5;
timer_prescaler = 5;
} else if (system_clock == 96000000) {
usbfs_prescaler = RCU_CKUSB_CKPLL_DIV2;
timer_prescaler = 7;
} else {
/* reserved */
}
void usb_rcu_config(void) {
uint32_t system_clock = rcu_clock_freq_get(CK_SYS);
rcu_usb_clock_config(usbfs_prescaler);
rcu_periph_clock_enable(RCU_USBFS);
if (system_clock == 48000000) {
usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1;
timer_prescaler = 3;
} else if (system_clock == 72000000) {
usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1_5;
timer_prescaler = 5;
} else if (system_clock == 96000000) {
usbfs_prescaler = RCU_CKUSB_CKPLL_DIV2;
timer_prescaler = 7;
} else {
/* reserved */
}
rcu_usb_clock_config(usbfs_prescaler);
rcu_periph_clock_enable(RCU_USBFS);
}
/*!
@@ -85,24 +83,23 @@ void usb_rcu_config (void)
\param[out] none
\retval none
*/
void usb_intr_config (void)
{
ECLIC_SetLevelIRQ(USBFS_IRQn,1);
ECLIC_SetPriorityIRQ(USBFS_IRQn,0);
ECLIC_EnableIRQ(USBFS_IRQn);
void usb_intr_config(void) {
ECLIC_SetLevelIRQ(USBFS_IRQn, 1);
ECLIC_SetPriorityIRQ(USBFS_IRQn, 0);
ECLIC_EnableIRQ(USBFS_IRQn);
#ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
/* enable the power module clock */
rcu_periph_clock_enable(RCU_PMU);
/* enable the power module clock */
rcu_periph_clock_enable(RCU_PMU);
/* USB wakeup EXTI line configuration */
exti_interrupt_flag_clear(EXTI_18);
exti_init(EXTI_18, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_enable(EXTI_18);
/* USB wakeup EXTI line configuration */
exti_interrupt_flag_clear(EXTI_18);
exti_init(EXTI_18, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_enable(EXTI_18);
ECLIC_SetLevelIRQ(USBFS_WKUP_IRQn,3);
ECLIC_SetPriorityIRQ(USBFS_WKUP_IRQn,0);
ECLIC_EnableIRQ(USBFS_WKUP_IRQn);
ECLIC_SetLevelIRQ(USBFS_WKUP_IRQn, 3);
ECLIC_SetPriorityIRQ(USBFS_WKUP_IRQn, 0);
ECLIC_EnableIRQ(USBFS_WKUP_IRQn);
#endif /* USBHS_LOW_PWR_MGMT_SUPPORT */
}
@@ -113,18 +110,14 @@ void usb_intr_config (void)
\param[out] none
\retval none
*/
void usb_vbus_drive (uint8_t state)
{
if (0 == state)
{
/* DISABLE is needed on output of the Power Switch */
gpio_bit_reset(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
}
else
{
/*ENABLE the Power Switch by driving the Enable LOW */
gpio_bit_set(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
}
void usb_vbus_drive(uint8_t state) {
if (0 == state) {
/* DISABLE is needed on output of the Power Switch */
gpio_bit_reset(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
} else {
/*ENABLE the Power Switch by driving the Enable LOW */
gpio_bit_set(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
}
}
/*!
@@ -133,20 +126,19 @@ void usb_vbus_drive (uint8_t state)
\param[out] none
\retval none
*/
void usb_vbus_config (void)
{
rcu_periph_clock_enable(HOST_POWERSW_PORT_RCC);
void usb_vbus_config(void) {
rcu_periph_clock_enable(HOST_POWERSW_PORT_RCC);
gpio_init(HOST_POWERSW_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, HOST_POWERSW_VBUS);
gpio_init(HOST_POWERSW_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, HOST_POWERSW_VBUS);
/* by default, disable is needed on output of the power switch */
gpio_bit_set(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
/* by default, disable is needed on output of the power switch */
gpio_bit_set(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
/* Delay is need for stabilising the Vbus Low in Reset Condition,
* when Vbus=1 and Reset-button is pressed by user
*/
//usb_mdelay (1);
usb_mdelay (2);
/* Delay is need for stabilising the Vbus Low in Reset Condition,
* when Vbus=1 and Reset-button is pressed by user
*/
// usb_mdelay (1);
usb_mdelay(2);
}
/*!
@@ -155,14 +147,13 @@ void usb_vbus_config (void)
\param[out] none
\retval none
*/
void usb_timer_init (void)
{
rcu_periph_clock_enable(RCU_TIMER2);
//eclic_irq_enable(TIMER2_IRQn, 2, 0);
/*ECLIC_Register_IRQn(TIMER2_IRQn, ECLIC_VECTOR_INTERRUPT,
ECLIC_LEVEL_TRIGGER, 2, 0,
TIMER2_IRQHandler);*/
void usb_timer_init(void) {
rcu_periph_clock_enable(RCU_TIMER2);
// eclic_irq_enable(TIMER2_IRQn, 2, 0);
/*ECLIC_Register_IRQn(TIMER2_IRQn, ECLIC_VECTOR_INTERRUPT,
ECLIC_LEVEL_TRIGGER, 2, 0,
TIMER2_IRQHandler);*/
}
/*!
@@ -171,10 +162,7 @@ void usb_timer_init (void)
\param[out] none
\retval none
*/
void usb_udelay (const uint32_t usec)
{
hwp_delay(usec, TIM_USEC_DELAY);
}
void usb_udelay(const uint32_t usec) { hwp_delay(usec, TIM_USEC_DELAY); }
/*!
\brief delay in milli seconds
@@ -182,10 +170,7 @@ void usb_udelay (const uint32_t usec)
\param[out] none
\retval none
*/
void usb_mdelay (const uint32_t msec)
{
hwp_delay(msec, TIM_MSEC_DELAY);
}
void usb_mdelay(const uint32_t msec) { hwp_delay(msec, TIM_MSEC_DELAY); }
/*!
\brief timer base IRQ
@@ -193,34 +178,33 @@ void usb_mdelay (const uint32_t msec)
\param[out] none
\retval none
*/
void usb_timer_irq (void)
{
if (timer_interrupt_flag_get(TIMER2, TIMER_INT_UP) != RESET){
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
void usb_timer_irq(void) {
if (timer_interrupt_flag_get(TIMER2, TIMER_INT_UP) != RESET) {
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
if (delay_time > 0x00U){
delay_time--;
} else {
timer_disable(TIMER2);
}
if (delay_time > 0x00U) {
delay_time--;
} else {
timer_disable(TIMER2);
}
}
}
/*!
\brief delay routine based on TIM2
\param[in] ntime: delay Time
\param[in] ntime: delay Time
\param[in] unit: delay Time unit = mili sec / micro sec
\param[out] none
\retval none
*/
static void hwp_delay(uint32_t ntime, uint8_t unit)
{
delay_time = ntime;
hwp_time_set(unit);
static void hwp_delay(uint32_t ntime, uint8_t unit) {
delay_time = ntime;
hwp_time_set(unit);
while(delay_time != 0);
while (delay_time != 0)
;
timer_disable(TIMER2);
timer_disable(TIMER2);
}
/*!
@@ -229,37 +213,35 @@ static void hwp_delay(uint32_t ntime, uint8_t unit)
\param[out] none
\retval none
*/
static void hwp_time_set(uint8_t unit)
{
timer_parameter_struct timer_basestructure;
static void hwp_time_set(uint8_t unit) {
timer_parameter_struct timer_basestructure;
timer_disable(TIMER2);
timer_interrupt_disable(TIMER2, TIMER_INT_UP);
timer_disable(TIMER2);
timer_interrupt_disable(TIMER2, TIMER_INT_UP);
if (unit == TIM_USEC_DELAY) {
timer_basestructure.period = 11;
} else if(unit == TIM_MSEC_DELAY) {
timer_basestructure.period = 11999;
} else {
/* no operation */
}
if (unit == TIM_USEC_DELAY) {
timer_basestructure.period = 11;
} else if (unit == TIM_MSEC_DELAY) {
timer_basestructure.period = 11999;
} else {
/* no operation */
}
timer_basestructure.prescaler = timer_prescaler;
timer_basestructure.alignedmode = TIMER_COUNTER_EDGE;
timer_basestructure.counterdirection = TIMER_COUNTER_UP;
timer_basestructure.clockdivision = TIMER_CKDIV_DIV1;
timer_basestructure.repetitioncounter = 0;
timer_basestructure.prescaler = timer_prescaler;
timer_basestructure.alignedmode = TIMER_COUNTER_EDGE;
timer_basestructure.counterdirection = TIMER_COUNTER_UP;
timer_basestructure.clockdivision = TIMER_CKDIV_DIV1;
timer_basestructure.repetitioncounter = 0;
timer_init(TIMER2, &timer_basestructure);
timer_init(TIMER2, &timer_basestructure);
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
timer_auto_reload_shadow_enable(TIMER2);
timer_auto_reload_shadow_enable(TIMER2);
/* timer2 interrupt enable */
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
/* timer2 interrupt enable */
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
/* timer2 enable counter */
timer_enable(TIMER2);
/* timer2 enable counter */
timer_enable(TIMER2);
}

View File

@@ -8,27 +8,27 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
@@ -36,12 +36,7 @@ OF SUCH DAMAGE.
#include "drv_usb_hw.h"
/* endpoint type */
const uint32_t ep_type[] = {
[USB_EP_ATTR_CTL] = USB_EPTYPE_CTRL,
[USB_EP_ATTR_BULK] = USB_EPTYPE_BULK,
[USB_EP_ATTR_INT] = USB_EPTYPE_INTR,
[USB_EP_ATTR_ISO] = USB_EPTYPE_ISOC
};
const uint32_t ep_type[] = {[USB_EP_ATTR_CTL] = USB_EPTYPE_CTRL, [USB_EP_ATTR_BULK] = USB_EPTYPE_BULK, [USB_EP_ATTR_INT] = USB_EPTYPE_INTR, [USB_EP_ATTR_ISO] = USB_EPTYPE_ISOC};
/*!
\brief initailizes the USB device-mode stack and load the class driver
@@ -51,27 +46,26 @@ const uint32_t ep_type[] = {
\param[out] none
\retval none
*/
void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_class_core *class_core)
{
/* device descriptor, class and user callbacks */
udev->dev.class_core = class_core;
void usbd_init(usb_core_driver *udev, usb_core_enum core, usb_class_core *class_core) {
/* device descriptor, class and user callbacks */
udev->dev.class_core = class_core;
/* configure USB capabilites */
usb_basic_init (&udev->bp, &udev->regs, core);
/* configure USB capabilites */
usb_basic_init(&udev->bp, &udev->regs, core);
/* initailizes the USB core*/
usb_core_init (udev->bp, &udev->regs);
/* initailizes the USB core*/
usb_core_init(udev->bp, &udev->regs);
/* set device disconnect */
usbd_disconnect (udev);
/* set device disconnect */
usbd_disconnect(udev);
/* initailizes device mode */
usb_devcore_init (udev);
/* initailizes device mode */
usb_devcore_init(udev);
/* set device connect */
usbd_connect (udev);
udev->dev.cur_status = USBD_DEFAULT;
/* set device connect */
usbd_connect(udev);
udev->dev.cur_status = USBD_DEFAULT;
}
/*!
@@ -81,32 +75,31 @@ void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_class_core *class
\param[out] none
\retval none
*/
uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc)
{
usb_transc *transc;
uint32_t usbd_ep_setup(usb_core_driver *udev, const usb_desc_ep *ep_desc) {
usb_transc *transc;
uint8_t ep_addr = ep_desc->bEndpointAddress;
uint8_t max_len = ep_desc->wMaxPacketSize;
uint8_t ep_addr = ep_desc->bEndpointAddress;
uint8_t max_len = ep_desc->wMaxPacketSize;
/* set endpoint direction */
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
/* set endpoint direction */
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
transc->ep_addr.dir = 1U;
} else {
transc = &udev->dev.transc_out[ep_addr];
transc->ep_addr.dir = 1U;
} else {
transc = &udev->dev.transc_out[ep_addr];
transc->ep_addr.dir = 0U;
}
transc->ep_addr.dir = 0U;
}
transc->ep_addr.num = EP_ID(ep_addr);
transc->max_len = max_len;
transc->ep_type = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK];
transc->ep_addr.num = EP_ID(ep_addr);
transc->max_len = max_len;
transc->ep_type = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK];
/* active USB endpoint function */
usb_transc_active (udev, transc);
/* active USB endpoint function */
usb_transc_active(udev, transc);
return 0;
return 0;
}
/*!
@@ -119,23 +112,21 @@ uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc)
\param[out] none
\retval none
*/
uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr)
{
usb_transc *transc;
uint32_t usbd_ep_clear(usb_core_driver *udev, uint8_t ep_addr) {
usb_transc *transc;
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
/* deactive USB endpoint function */
usb_transc_deactivate (udev, transc);
/* deactive USB endpoint function */
usb_transc_deactivate(udev, transc);
return 0;
return 0;
}
/*!
\brief endpoint prepare to receive data
\param[in] udev: pointer to usb core instance
@@ -148,23 +139,22 @@ uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr)
\param[out] none
\retval none
*/
uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len)
{
usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)];
uint32_t usbd_ep_recev(usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len) {
usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)];
/* setup the transfer */
transc->xfer_buf = pbuf;
transc->xfer_len = len;
transc->xfer_count = 0;
/* setup the transfer */
transc->xfer_buf = pbuf;
transc->xfer_len = len;
transc->xfer_count = 0;
if (USB_USE_DMA == udev->bp.transfer_mode) {
transc->dma_addr = (uint32_t)pbuf;
}
if (USB_USE_DMA == udev->bp.transfer_mode) {
transc->dma_addr = (uint32_t)pbuf;
}
/* start the transfer */
usb_transc_outxfer (udev, transc);
/* start the transfer */
usb_transc_outxfer(udev, transc);
return 0;
return 0;
}
/*!
@@ -179,23 +169,22 @@ uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, u
\param[out] none
\retval none
*/
uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len)
{
usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)];
uint32_t usbd_ep_send(usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len) {
usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)];
/* setup the transfer */
transc->xfer_buf = pbuf;
transc->xfer_len = len;
transc->xfer_count = 0;
/* setup the transfer */
transc->xfer_buf = pbuf;
transc->xfer_len = len;
transc->xfer_count = 0;
if (USB_USE_DMA == udev->bp.transfer_mode) {
transc->dma_addr = (uint32_t)pbuf;
}
if (USB_USE_DMA == udev->bp.transfer_mode) {
transc->dma_addr = (uint32_t)pbuf;
}
/* start the transfer */
usb_transc_inxfer (udev, transc);
/* start the transfer */
usb_transc_inxfer(udev, transc);
return 0;
return 0;
}
/*!
@@ -208,21 +197,20 @@ uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, u
\param[out] none
\retval none
*/
uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr)
{
usb_transc *transc = NULL;
uint32_t usbd_ep_stall(usb_core_driver *udev, uint8_t ep_addr) {
usb_transc *transc = NULL;
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
transc->ep_stall = 1;
transc->ep_stall = 1;
usb_transc_stall (udev, transc);
usb_transc_stall(udev, transc);
return (0);
return (0);
}
/*!
@@ -235,21 +223,20 @@ uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr)
\param[out] none
\retval none
*/
uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr)
{
usb_transc *transc = NULL;
uint32_t usbd_ep_stall_clear(usb_core_driver *udev, uint8_t ep_addr) {
usb_transc *transc = NULL;
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
transc->ep_stall = 0;
transc->ep_stall = 0;
usb_transc_clrstall (udev, transc);
usb_transc_clrstall(udev, transc);
return (0);
return (0);
}
/*!
@@ -262,15 +249,14 @@ uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr)
\param[out] none
\retval none
*/
uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr)
{
if (EP_DIR(ep_addr)) {
usb_txfifo_flush (&udev->regs, EP_ID(ep_addr));
} else {
usb_rxfifo_flush (&udev->regs);
}
uint32_t usbd_fifo_flush(usb_core_driver *udev, uint8_t ep_addr) {
if (EP_DIR(ep_addr)) {
usb_txfifo_flush(&udev->regs, EP_ID(ep_addr));
} else {
usb_rxfifo_flush(&udev->regs);
}
return (0);
return (0);
}
/*!
@@ -280,10 +266,7 @@ uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr)
\param[out] none
\retval none
*/
void usbd_addr_set (usb_core_driver *udev, uint8_t addr)
{
usb_devaddr_set(udev, addr);
}
void usbd_addr_set(usb_core_driver *udev, uint8_t addr) { usb_devaddr_set(udev, addr); }
/*!
\brief get the received data length
@@ -292,10 +275,7 @@ void usbd_addr_set (usb_core_driver *udev, uint8_t addr)
\param[out] none
\retval USB device operation cur_status
*/
uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num)
{
return udev->dev.transc_out[ep_num].xfer_count;
}
uint16_t usbd_rxcount_get(usb_core_driver *udev, uint8_t ep_num) { return udev->dev.transc_out[ep_num].xfer_count; }
/*!
\brief device connect
@@ -303,12 +283,11 @@ uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num)
\param[out] none
\retval none
*/
void usbd_connect (usb_core_driver *udev)
{
void usbd_connect(usb_core_driver *udev) {
#ifndef USE_OTG_MODE
/* connect device */
usb_dev_connect (udev);
usb_mdelay(3);
/* connect device */
usb_dev_connect(udev);
usb_mdelay(3);
#endif /* USE_OTG_MODE */
}
@@ -319,11 +298,10 @@ void usbd_connect (usb_core_driver *udev)
\param[out] none
\retval none
*/
void usbd_disconnect (usb_core_driver *udev)
{
void usbd_disconnect(usb_core_driver *udev) {
#ifndef USE_OTG_MODE
/* disconnect device for 3ms */
usb_dev_disconnect (udev);
usb_mdelay(3);
/* disconnect device for 3ms */
usb_dev_disconnect(udev);
usb_mdelay(3);
#endif /* USE_OTG_MODE */
}

View File

@@ -8,53 +8,52 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "usbd_enum.h"
#include "usb_ch9_std.h"
static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getstatus(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setaddress(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setconfiguration(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getconfiguration(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getdescriptor(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setfeature(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_clearfeature(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_reserved(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setdescriptor(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getinterface(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setinterface(usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_synchframe(usb_core_driver *udev, usb_req *req);
static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t *_usb_dev_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t *_usb_config_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t *_usb_str_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t *_usb_bos_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len);
static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) =
{
static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = {
[USB_GET_STATUS] = _usb_std_getstatus,
[USB_CLEAR_FEATURE] = _usb_std_clearfeature,
[USB_RESERVED2] = _usb_std_reserved,
@@ -71,11 +70,8 @@ static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) =
};
/* get standard descriptor handler */
static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = {
[USB_DESCTYPE_DEV - 1] = _usb_dev_desc_get,
[USB_DESCTYPE_CONFIG - 1] = _usb_config_desc_get,
[USB_DESCTYPE_STR - 1] = _usb_str_desc_get
};
static uint8_t *(*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len)
= {[USB_DESCTYPE_DEV - 1] = _usb_dev_desc_get, [USB_DESCTYPE_CONFIG - 1] = _usb_config_desc_get, [USB_DESCTYPE_STR - 1] = _usb_str_desc_get};
/*!
\brief handle USB standard device request
@@ -84,10 +80,7 @@ static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t
\param[out] none
\retval USB device request status
*/
usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req)
{
return (*_std_dev_req[req->bRequest])(udev, req);
}
usb_reqsta usbd_standard_request(usb_core_driver *udev, usb_req *req) { return (*_std_dev_req[req->bRequest])(udev, req); }
/*!
\brief handle USB device class request
@@ -96,16 +89,15 @@ usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req)
{
if (USBD_CONFIGURED == udev->dev.cur_status) {
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
/* call device class handle function */
return (usb_reqsta)udev->dev.class_core->req_proc(udev, req);
}
usb_reqsta usbd_class_request(usb_core_driver *udev, usb_req *req) {
if (USBD_CONFIGURED == udev->dev.cur_status) {
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
/* call device class handle function */
return (usb_reqsta)udev->dev.class_core->req_proc(udev, req);
}
}
return REQ_NOTSUPP;
return REQ_NOTSUPP;
}
/*!
@@ -115,11 +107,10 @@ usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req)
{
/* added by user... */
usb_reqsta usbd_vendor_request(usb_core_driver *udev, usb_req *req) {
/* added by user... */
return REQ_SUPP;
return REQ_SUPP;
}
/*!
@@ -129,11 +120,10 @@ usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req)
{
/* no operation... */
static usb_reqsta _usb_std_reserved(usb_core_driver *udev, usb_req *req) {
/* no operation... */
return REQ_NOTSUPP;
return REQ_NOTSUPP;
}
/*!
@@ -143,11 +133,10 @@ static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req)
\param[out] len: data length pointer
\retval descriptor buffer pointer
*/
static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
*len = udev->dev.desc.dev_desc[0];
static uint8_t *_usb_dev_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len) {
*len = udev->dev.desc.dev_desc[0];
return udev->dev.desc.dev_desc;
return udev->dev.desc.dev_desc;
}
/*!
@@ -157,11 +146,10 @@ static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_
\param[out] len: data length pointer
\retval descriptor buffer pointer
*/
static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
*len = udev->dev.desc.config_desc[2];
static uint8_t *_usb_config_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len) {
*len = udev->dev.desc.config_desc[2];
return udev->dev.desc.config_desc;
return udev->dev.desc.config_desc;
}
/*!
@@ -171,11 +159,10 @@ static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint
\param[out] len: data length pointer
\retval descriptor buffer pointer
*/
static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
*len = udev->dev.desc.bos_desc[2];
static uint8_t *_usb_bos_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len) {
*len = udev->dev.desc.bos_desc[2];
return udev->dev.desc.bos_desc;
return udev->dev.desc.bos_desc;
}
/*!
@@ -185,13 +172,12 @@ static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_
\param[out] len: pointer to string length
\retval descriptor buffer pointer
*/
static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
uint8_t *desc = udev->dev.desc.strings[index];
static uint8_t *_usb_str_desc_get(usb_core_driver *udev, uint8_t index, uint16_t *len) {
uint8_t *desc = udev->dev.desc.strings[index];
*len = desc[0];
*len = desc[0];
return desc;
return desc;
}
/*!
@@ -201,67 +187,65 @@ static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req)
{
uint8_t recp = BYTE_LOW(req->wIndex);
static usb_reqsta _usb_std_getstatus(usb_core_driver *udev, usb_req *req) {
uint8_t recp = BYTE_LOW(req->wIndex);
usb_transc *transc = &udev->dev.transc_in[0];
usb_transc *transc = &udev->dev.transc_in[0];
static uint8_t status[2] = {0};
static uint8_t status[2] = {0};
switch(req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || \
(USBD_CONFIGURED == udev->dev.cur_status)) {
switch (req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || (USBD_CONFIGURED == udev->dev.cur_status)) {
if (udev->dev.pm.power_mode) {
status[0] = USB_STATUS_SELF_POWERED;
} else {
status[0] = 0U;
}
if (udev->dev.pm.power_mode) {
status[0] = USB_STATUS_SELF_POWERED;
} else {
status[0] = 0U;
}
if (udev->dev.pm.dev_remote_wakeup) {
status[0] |= USB_STATUS_REMOTE_WAKEUP;
} else {
status[0] = 0U;
}
if (udev->dev.pm.dev_remote_wakeup) {
status[0] |= USB_STATUS_REMOTE_WAKEUP;
} else {
status[0] = 0U;
}
transc->xfer_buf = status;
transc->remain_len = 2U;
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
case USB_RECPTYPE_ITF:
if ((USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) {
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
case USB_RECPTYPE_EP:
if (USBD_CONFIGURED == udev->dev.cur_status) {
if (0x80U == (recp & 0x80U)) {
status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall;
} else {
status[0] = udev->dev.transc_out[recp].ep_stall;
}
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
default:
break;
return REQ_SUPP;
}
break;
return REQ_NOTSUPP;
case USB_RECPTYPE_ITF:
if ((USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) {
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
case USB_RECPTYPE_EP:
if (USBD_CONFIGURED == udev->dev.cur_status) {
if (0x80U == (recp & 0x80U)) {
status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall;
} else {
status[0] = udev->dev.transc_out[recp].ep_stall;
}
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
@@ -271,49 +255,46 @@ static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req)
{
uint8_t ep = 0;
static usb_reqsta _usb_std_clearfeature(usb_core_driver *udev, usb_req *req) {
uint8_t ep = 0;
switch(req->bmRequestType & USB_RECPTYPE_MASK)
{
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || \
(USBD_CONFIGURED == udev->dev.cur_status)) {
switch (req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || (USBD_CONFIGURED == udev->dev.cur_status)) {
/* clear device remote wakeup feature */
if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) {
udev->dev.pm.dev_remote_wakeup = 0U;
/* clear device remote wakeup feature */
if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) {
udev->dev.pm.dev_remote_wakeup = 0U;
return REQ_SUPP;
}
}
break;
case USB_RECPTYPE_ITF:
break;
case USB_RECPTYPE_EP:
/* get endpoint address */
ep = BYTE_LOW(req->wIndex);
if (USBD_CONFIGURED == udev->dev.cur_status) {
/* clear endpoint halt feature */
if ((USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) {
usbd_ep_stall_clear (udev, ep);
udev->dev.class_core->req_proc (udev, req);
}
return REQ_SUPP;
}
break;
default:
break;
return REQ_SUPP;
}
}
break;
return REQ_NOTSUPP;
case USB_RECPTYPE_ITF:
break;
case USB_RECPTYPE_EP:
/* get endpoint address */
ep = BYTE_LOW(req->wIndex);
if (USBD_CONFIGURED == udev->dev.cur_status) {
/* clear endpoint halt feature */
if ((USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) {
usbd_ep_stall_clear(udev, ep);
udev->dev.class_core->req_proc(udev, req);
}
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
@@ -323,46 +304,43 @@ static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req)
{
uint8_t ep = 0;
static usb_reqsta _usb_std_setfeature(usb_core_driver *udev, usb_req *req) {
uint8_t ep = 0;
switch(req->bmRequestType & USB_RECPTYPE_MASK)
{
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || \
(USBD_CONFIGURED == udev->dev.cur_status)) {
/* set device remote wakeup feature */
if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) {
udev->dev.pm.dev_remote_wakeup = 1U;
}
switch (req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || (USBD_CONFIGURED == udev->dev.cur_status)) {
/* set device remote wakeup feature */
if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) {
udev->dev.pm.dev_remote_wakeup = 1U;
}
return REQ_SUPP;
}
break;
case USB_RECPTYPE_ITF:
break;
case USB_RECPTYPE_EP:
/* get endpoint address */
ep = BYTE_LOW(req->wIndex);
if (USBD_CONFIGURED == udev->dev.cur_status) {
/* set endpoint halt feature */
if ((USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) {
usbd_ep_stall (udev, ep);
}
return REQ_SUPP;
}
break;
default:
break;
return REQ_SUPP;
}
break;
return REQ_NOTSUPP;
case USB_RECPTYPE_ITF:
break;
case USB_RECPTYPE_EP:
/* get endpoint address */
ep = BYTE_LOW(req->wIndex);
if (USBD_CONFIGURED == udev->dev.cur_status) {
/* set endpoint halt feature */
if ((USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) {
usbd_ep_stall(udev, ep);
}
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
@@ -372,25 +350,24 @@ static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req)
{
if ((0U == req->wIndex) && (0U == req->wLength)) {
udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU;
static usb_reqsta _usb_std_setaddress(usb_core_driver *udev, usb_req *req) {
if ((0U == req->wIndex) && (0U == req->wLength)) {
udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU;
if (udev->dev.cur_status != USBD_CONFIGURED) {
usbd_addr_set (udev, udev->dev.dev_addr);
if (udev->dev.cur_status != USBD_CONFIGURED) {
usbd_addr_set(udev, udev->dev.dev_addr);
if (udev->dev.dev_addr) {
udev->dev.cur_status = USBD_ADDRESSED;
} else {
udev->dev.cur_status = USBD_DEFAULT;
}
if (udev->dev.dev_addr) {
udev->dev.cur_status = USBD_ADDRESSED;
} else {
udev->dev.cur_status = USBD_DEFAULT;
}
return REQ_SUPP;
}
return REQ_SUPP;
}
}
return REQ_NOTSUPP;
return REQ_NOTSUPP;
}
/*!
@@ -400,78 +377,77 @@ static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req)
{
uint8_t desc_type = 0;
uint8_t desc_index = 0;
static usb_reqsta _usb_std_getdescriptor(usb_core_driver *udev, usb_req *req) {
uint8_t desc_type = 0;
uint8_t desc_index = 0;
usb_transc *transc = &udev->dev.transc_in[0];
usb_transc *transc = &udev->dev.transc_in[0];
/* get device standard descriptor */
switch (req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
desc_type = BYTE_HIGH(req->wValue);
desc_index = BYTE_LOW(req->wValue);
/* get device standard descriptor */
switch (req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
desc_type = BYTE_HIGH(req->wValue);
desc_index = BYTE_LOW(req->wValue);
switch (desc_type) {
case USB_DESCTYPE_DEV:
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
switch (desc_type) {
case USB_DESCTYPE_DEV:
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
if (64U == req->wLength) {
transc->remain_len = 8U;
}
break;
if (64U == req->wLength) {
transc->remain_len = 8U;
}
break;
case USB_DESCTYPE_CONFIG:
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
break;
case USB_DESCTYPE_CONFIG:
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
break;
case USB_DESCTYPE_STR:
if (desc_index < STR_IDX_MAX) {
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
}
break;
case USB_DESCTYPE_STR:
if (desc_index < STR_IDX_MAX) {
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
}
break;
case USB_DESCTYPE_ITF:
case USB_DESCTYPE_EP:
case USB_DESCTYPE_DEV_QUALIFIER:
case USB_DESCTYPE_OTHER_SPD_CONFIG:
case USB_DESCTYPE_ITF_POWER:
break;
case USB_DESCTYPE_ITF:
case USB_DESCTYPE_EP:
case USB_DESCTYPE_DEV_QUALIFIER:
case USB_DESCTYPE_OTHER_SPD_CONFIG:
case USB_DESCTYPE_ITF_POWER:
break;
case USB_DESCTYPE_BOS:
transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len));
break;
default:
break;
}
break;
case USB_RECPTYPE_ITF:
/* get device class special descriptor */
return (usb_reqsta)(udev->dev.class_core->req_proc(udev, req));
case USB_RECPTYPE_EP:
break;
case USB_DESCTYPE_BOS:
transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len));
break;
default:
break;
break;
}
break;
case USB_RECPTYPE_ITF:
/* get device class special descriptor */
return (usb_reqsta)(udev->dev.class_core->req_proc(udev, req));
case USB_RECPTYPE_EP:
break;
default:
break;
}
if ((0U != transc->remain_len) && (0U != req->wLength)) {
if (transc->remain_len < req->wLength) {
if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) {
udev->dev.control.ctl_zlp = 1;
}
} else {
transc->remain_len = req->wLength;
}
if ((0U != transc->remain_len) && (0U != req->wLength)) {
if (transc->remain_len < req->wLength) {
if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) {
udev->dev.control.ctl_zlp = 1;
}
} else {
transc->remain_len = req->wLength;
}
return REQ_SUPP;
}
return REQ_SUPP;
}
return REQ_NOTSUPP;
return REQ_NOTSUPP;
}
/*!
@@ -481,10 +457,9 @@ static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req)
{
/* no handle... */
return REQ_SUPP;
static usb_reqsta _usb_std_setdescriptor(usb_core_driver *udev, usb_req *req) {
/* no handle... */
return REQ_SUPP;
}
/*!
@@ -494,34 +469,33 @@ static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req)
{
usb_transc *transc = &udev->dev.transc_in[0];
static usb_reqsta _usb_std_getconfiguration(usb_core_driver *udev, usb_req *req) {
usb_transc *transc = &udev->dev.transc_in[0];
switch (udev->dev.cur_status) {
case USBD_ADDRESSED:
if (USB_DEFAULT_CONFIG == udev->dev.config) {
transc->xfer_buf = &(udev->dev.config);
transc->remain_len = 1U;
switch (udev->dev.cur_status) {
case USBD_ADDRESSED:
if (USB_DEFAULT_CONFIG == udev->dev.config) {
transc->xfer_buf = &(udev->dev.config);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
case USBD_CONFIGURED:
if (udev->dev.config != USB_DEFAULT_CONFIG) {
transc->xfer_buf = &(udev->dev.config);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
default:
break;
return REQ_SUPP;
}
break;
return REQ_NOTSUPP;
case USBD_CONFIGURED:
if (udev->dev.config != USB_DEFAULT_CONFIG) {
transc->xfer_buf = &(udev->dev.config);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
@@ -531,50 +505,49 @@ static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req)
{
static uint8_t config;
static usb_reqsta _usb_std_setconfiguration(usb_core_driver *udev, usb_req *req) {
static uint8_t config;
config = (uint8_t)(req->wValue);
config = (uint8_t)(req->wValue);
if (config <= USBD_CFG_MAX_NUM) {
switch (udev->dev.cur_status) {
case USBD_ADDRESSED:
if (config){
udev->dev.class_core->init(udev, config);
if (config <= USBD_CFG_MAX_NUM) {
switch (udev->dev.cur_status) {
case USBD_ADDRESSED:
if (config) {
udev->dev.class_core->init(udev, config);
udev->dev.config = config;
udev->dev.cur_status = USBD_CONFIGURED;
}
udev->dev.config = config;
udev->dev.cur_status = USBD_CONFIGURED;
}
return REQ_SUPP;
return REQ_SUPP;
case USBD_CONFIGURED:
if (USB_DEFAULT_CONFIG == config) {
udev->dev.class_core->deinit(udev, config);
case USBD_CONFIGURED:
if (USB_DEFAULT_CONFIG == config) {
udev->dev.class_core->deinit(udev, config);
udev->dev.config = config;
udev->dev.cur_status = USBD_ADDRESSED;
} else if (config != udev->dev.config) {
/* clear old configuration */
udev->dev.class_core->deinit(udev, config);
udev->dev.config = config;
udev->dev.cur_status = USBD_ADDRESSED;
} else if (config != udev->dev.config) {
/* clear old configuration */
udev->dev.class_core->deinit(udev, config);
/* set new configuration */
udev->dev.config = config;
udev->dev.class_core->init(udev, config);
}
/* set new configuration */
udev->dev.config = config;
udev->dev.class_core->init(udev, config);
}
return REQ_SUPP;
return REQ_SUPP;
case USBD_DEFAULT:
break;
case USBD_DEFAULT:
break;
default:
break;
}
default:
break;
}
}
return REQ_NOTSUPP;
return REQ_NOTSUPP;
}
/*!
@@ -584,31 +557,30 @@ static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req)
{
switch (udev->dev.cur_status) {
case USBD_DEFAULT:
break;
static usb_reqsta _usb_std_getinterface(usb_core_driver *udev, usb_req *req) {
switch (udev->dev.cur_status) {
case USBD_DEFAULT:
break;
case USBD_ADDRESSED:
break;
case USBD_ADDRESSED:
break;
case USBD_CONFIGURED:
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
usb_transc *transc = &udev->dev.transc_in[0];
case USBD_CONFIGURED:
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
usb_transc *transc = &udev->dev.transc_in[0];
transc->xfer_buf = &(udev->dev.class_core->alter_set);
transc->remain_len = 1U;
transc->xfer_buf = &(udev->dev.class_core->alter_set);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
default:
break;
return REQ_SUPP;
}
break;
return REQ_NOTSUPP;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
@@ -618,28 +590,27 @@ static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req)
{
switch (udev->dev.cur_status) {
case USBD_DEFAULT:
break;
static usb_reqsta _usb_std_setinterface(usb_core_driver *udev, usb_req *req) {
switch (udev->dev.cur_status) {
case USBD_DEFAULT:
break;
case USBD_ADDRESSED:
break;
case USBD_ADDRESSED:
break;
case USBD_CONFIGURED:
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
udev->dev.class_core->alter_set = req->wValue;
case USBD_CONFIGURED:
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
udev->dev.class_core->alter_set = req->wValue;
return REQ_SUPP;
}
break;
default:
break;
return REQ_SUPP;
}
break;
return REQ_NOTSUPP;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
@@ -649,10 +620,9 @@ static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req)
{
/* no handle... */
return REQ_SUPP;
static usb_reqsta _usb_std_synchframe(usb_core_driver *udev, usb_req *req) {
/* no handle... */
return REQ_SUPP;
}
/*!
@@ -662,12 +632,11 @@ static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval none
*/
void usbd_enum_error (usb_core_driver *udev, usb_req *req)
{
usbd_ep_stall (udev, 0x80);
usbd_ep_stall (udev, 0x00);
void usbd_enum_error(usb_core_driver *udev, usb_req *req) {
usbd_ep_stall(udev, 0x80);
usbd_ep_stall(udev, 0x00);
usb_ctlep_startout(udev);
usb_ctlep_startout(udev);
}
/*!
@@ -678,19 +647,18 @@ void usbd_enum_error (usb_core_driver *udev, usb_req *req)
\param[out] none
\retval none
*/
void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t index = 0;
void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) {
uint8_t index = 0;
for (index = 0; index < len; index++) {
if ((value >> 28) < 0x0A) {
pbuf[2 * index] = (value >> 28) + '0';
} else {
pbuf[2 * index] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * index + 1] = 0;
for (index = 0; index < len; index++) {
if ((value >> 28) < 0x0A) {
pbuf[2 * index] = (value >> 28) + '0';
} else {
pbuf[2 * index] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * index + 1] = 0;
}
}

View File

@@ -8,32 +8,32 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "usbd_enum.h"
#include "usbd_transc.h"
#include "usbd_enum.h"
/*!
\brief USB send data in the control transaction
@@ -41,19 +41,18 @@ OF SUCH DAMAGE.
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_send (usb_core_driver *udev)
{
usb_transc *transc = &udev->dev.transc_in[0];
usbd_status usbd_ctl_send(usb_core_driver *udev) {
usb_transc *transc = &udev->dev.transc_in[0];
usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len);
usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len);
if (transc->remain_len > transc->max_len) {
udev->dev.control.ctl_state = USB_CTL_DATA_IN;
} else {
udev->dev.control.ctl_state = USB_CTL_LAST_DATA_IN;
}
if (transc->remain_len > transc->max_len) {
udev->dev.control.ctl_state = USB_CTL_DATA_IN;
} else {
udev->dev.control.ctl_state = USB_CTL_LAST_DATA_IN;
}
return USBD_OK;
return USBD_OK;
}
/*!
@@ -62,19 +61,18 @@ usbd_status usbd_ctl_send (usb_core_driver *udev)
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_recev (usb_core_driver *udev)
{
usb_transc *transc = &udev->dev.transc_out[0];
usbd_status usbd_ctl_recev(usb_core_driver *udev) {
usb_transc *transc = &udev->dev.transc_out[0];
usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len);
usbd_ep_recev(udev, 0U, transc->xfer_buf, transc->remain_len);
if (transc->remain_len > transc->max_len) {
udev->dev.control.ctl_state = USB_CTL_DATA_OUT;
} else {
udev->dev.control.ctl_state = USB_CTL_LAST_DATA_OUT;
}
if (transc->remain_len > transc->max_len) {
udev->dev.control.ctl_state = USB_CTL_DATA_OUT;
} else {
udev->dev.control.ctl_state = USB_CTL_LAST_DATA_OUT;
}
return USBD_OK;
return USBD_OK;
}
/*!
@@ -83,15 +81,14 @@ usbd_status usbd_ctl_recev (usb_core_driver *udev)
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_status_send (usb_core_driver *udev)
{
udev->dev.control.ctl_state = USB_CTL_STATUS_IN;
usbd_status usbd_ctl_status_send(usb_core_driver *udev) {
udev->dev.control.ctl_state = USB_CTL_STATUS_IN;
usbd_ep_send (udev, 0U, NULL, 0U);
usbd_ep_send(udev, 0U, NULL, 0U);
usb_ctlep_startout(udev);
usb_ctlep_startout(udev);
return USBD_OK;
return USBD_OK;
}
/*!
@@ -100,15 +97,14 @@ usbd_status usbd_ctl_status_send (usb_core_driver *udev)
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_status_recev (usb_core_driver *udev)
{
udev->dev.control.ctl_state = USB_CTL_STATUS_OUT;
usbd_status usbd_ctl_status_recev(usb_core_driver *udev) {
udev->dev.control.ctl_state = USB_CTL_STATUS_OUT;
usbd_ep_recev (udev, 0, NULL, 0);
usbd_ep_recev(udev, 0, NULL, 0);
usb_ctlep_startout(udev);
usb_ctlep_startout(udev);
return USBD_OK;
return USBD_OK;
}
/*!
@@ -117,47 +113,46 @@ usbd_status usbd_ctl_status_recev (usb_core_driver *udev)
\param[out] none
\retval USB device operation cur_status
*/
uint8_t usbd_setup_transc (usb_core_driver *udev)
{
usb_reqsta reqstat = REQ_NOTSUPP;
uint8_t usbd_setup_transc(usb_core_driver *udev) {
usb_reqsta reqstat = REQ_NOTSUPP;
usb_req req = udev->dev.control.req;
usb_req req = udev->dev.control.req;
switch (req.bmRequestType & USB_REQTYPE_MASK) {
/* standard device request */
case USB_REQTYPE_STRD:
reqstat = usbd_standard_request (udev, &req);
break;
switch (req.bmRequestType & USB_REQTYPE_MASK) {
/* standard device request */
case USB_REQTYPE_STRD:
reqstat = usbd_standard_request(udev, &req);
break;
/* device class request */
case USB_REQTYPE_CLASS:
reqstat = usbd_class_request (udev, &req);
break;
/* device class request */
case USB_REQTYPE_CLASS:
reqstat = usbd_class_request(udev, &req);
break;
/* vendor defined request */
case USB_REQTYPE_VENDOR:
reqstat = usbd_vendor_request (udev, &req);
break;
/* vendor defined request */
case USB_REQTYPE_VENDOR:
reqstat = usbd_vendor_request(udev, &req);
break;
default:
break;
}
default:
break;
}
if (REQ_SUPP == reqstat) {
if (req.wLength == 0) {
usbd_ctl_status_send (udev);
} else {
if (req.bmRequestType & 0x80) {
usbd_ctl_send (udev);
} else {
usbd_ctl_recev (udev);
}
}
if (REQ_SUPP == reqstat) {
if (req.wLength == 0) {
usbd_ctl_status_send(udev);
} else {
usbd_enum_error (udev, &req);
if (req.bmRequestType & 0x80) {
usbd_ctl_send(udev);
} else {
usbd_ctl_recev(udev);
}
}
} else {
usbd_enum_error(udev, &req);
}
return USBD_OK;
return USBD_OK;
}
/*!
@@ -167,39 +162,38 @@ uint8_t usbd_setup_transc (usb_core_driver *udev)
\param[out] none
\retval USB device operation cur_status
*/
uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num)
{
if (ep_num == 0) {
usb_transc *transc = &udev->dev.transc_out[0];
uint8_t usbd_out_transc(usb_core_driver *udev, uint8_t ep_num) {
if (ep_num == 0) {
usb_transc *transc = &udev->dev.transc_out[0];
switch (udev->dev.control.ctl_state) {
case USB_CTL_DATA_OUT:
/* update transfer length */
transc->remain_len -= transc->max_len;
switch (udev->dev.control.ctl_state) {
case USB_CTL_DATA_OUT:
/* update transfer length */
transc->remain_len -= transc->max_len;
usbd_ctl_recev (udev);
break;
usbd_ctl_recev(udev);
break;
case USB_CTL_LAST_DATA_OUT:
if (udev->dev.cur_status == USBD_CONFIGURED) {
if (udev->dev.class_core->data_out != NULL) {
udev->dev.class_core->data_out (udev, 0U);
}
}
transc->remain_len = 0U;
usbd_ctl_status_send (udev);
break;
default:
break;
case USB_CTL_LAST_DATA_OUT:
if (udev->dev.cur_status == USBD_CONFIGURED) {
if (udev->dev.class_core->data_out != NULL) {
udev->dev.class_core->data_out(udev, 0U);
}
} else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == USBD_CONFIGURED)) {
udev->dev.class_core->data_out (udev, ep_num);
}
}
return USBD_OK;
transc->remain_len = 0U;
usbd_ctl_status_send(udev);
break;
default:
break;
}
} else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == USBD_CONFIGURED)) {
udev->dev.class_core->data_out(udev, ep_num);
}
return USBD_OK;
}
/*!
@@ -209,46 +203,45 @@ uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num)
\param[out] none
\retval USB device operation cur_status
*/
uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num)
{
if (0U == ep_num) {
usb_transc *transc = &udev->dev.transc_in[0];
uint8_t usbd_in_transc(usb_core_driver *udev, uint8_t ep_num) {
if (0U == ep_num) {
usb_transc *transc = &udev->dev.transc_in[0];
switch (udev->dev.control.ctl_state) {
case USB_CTL_DATA_IN:
/* update transfer length */
transc->remain_len -= transc->max_len;
switch (udev->dev.control.ctl_state) {
case USB_CTL_DATA_IN:
/* update transfer length */
transc->remain_len -= transc->max_len;
usbd_ctl_send (udev);
break;
usbd_ctl_send(udev);
break;
case USB_CTL_LAST_DATA_IN:
/* last packet is MPS multiple, so send ZLP packet */
if (udev->dev.control.ctl_zlp) {
usbd_ep_send (udev, 0U, NULL, 0U);
case USB_CTL_LAST_DATA_IN:
/* last packet is MPS multiple, so send ZLP packet */
if (udev->dev.control.ctl_zlp) {
usbd_ep_send(udev, 0U, NULL, 0U);
udev->dev.control.ctl_zlp = 0U;
} else {
if (udev->dev.cur_status == USBD_CONFIGURED) {
if (udev->dev.class_core->data_in != NULL) {
udev->dev.class_core->data_in (udev, 0U);
}
}
transc->remain_len = 0U;
usbd_ctl_status_recev (udev);
}
break;
default:
break;
}
} else {
if ((udev->dev.cur_status == USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) {
udev->dev.class_core->data_in (udev, ep_num);
udev->dev.control.ctl_zlp = 0U;
} else {
if (udev->dev.cur_status == USBD_CONFIGURED) {
if (udev->dev.class_core->data_in != NULL) {
udev->dev.class_core->data_in(udev, 0U);
}
}
transc->remain_len = 0U;
usbd_ctl_status_recev(udev);
}
break;
default:
break;
}
} else {
if ((udev->dev.cur_status == USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) {
udev->dev.class_core->data_in(udev, ep_num);
}
}
return USBD_OK;
return USBD_OK;
}

View File

@@ -8,46 +8,43 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "drv_usb_hw.h"
#include "usbh_pipe.h"
#include "usbh_enum.h"
#include "usbh_core.h"
#include "drv_usb_hw.h"
#include "drv_usbh_int.h"
#include "usbh_enum.h"
#include "usbh_pipe.h"
uint8_t usbh_sof (usb_core_driver *pudev);
uint8_t usbh_sof(usb_core_driver *pudev);
usbh_int_cb usbh_int_op =
{
usbh_sof
};
usbh_int_cb usbh_int_op = {usbh_sof};
usbh_int_cb *usbh_int_fop = &usbh_int_op;
static usbh_status usbh_enum_task (usb_core_driver *pudev, usbh_host *puhost);
static usbh_status usbh_enum_task(usb_core_driver *pudev, usbh_host *puhost);
/*!
\brief USB SOF callback function from the interrupt
@@ -55,10 +52,9 @@ static usbh_status usbh_enum_task (usb_core_driver *pudev, usbh_host *puhost);
\param[out] none
\retval operation status
*/
uint8_t usbh_sof (usb_core_driver *pudev)
{
/* this callback could be used to implement a scheduler process */
return 0U;
uint8_t usbh_sof(usb_core_driver *pudev) {
/* this callback could be used to implement a scheduler process */
return 0U;
}
/*!
@@ -69,35 +65,34 @@ uint8_t usbh_sof (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
void usbh_init (usb_core_driver *pudev, usb_core_enum core, usbh_host *puhost)
{
uint8_t i = 0U;
void usbh_init(usb_core_driver *pudev, usb_core_enum core, usbh_host *puhost) {
uint8_t i = 0U;
/* host de-initializations */
usbh_deinit(pudev, puhost);
/* host de-initializations */
usbh_deinit(pudev, puhost);
pudev->host.connect_status = 0U;
pudev->host.connect_status = 0U;
for (i = 0U; i < USBFS_MAX_TX_FIFOS; i++) {
pudev->host.pipe[i].err_count = 0U;
pudev->host.pipe[i].pp_status = PIPE_IDLE;
pudev->host.backup_xfercount[i] = 0U;
}
for (i = 0U; i < USBFS_MAX_TX_FIFOS; i++) {
pudev->host.pipe[i].err_count = 0U;
pudev->host.pipe[i].pp_status = PIPE_IDLE;
pudev->host.backup_xfercount[i] = 0U;
}
pudev->host.pipe[0].ep.mps = 8U;
pudev->host.pipe[0].ep.mps = 8U;
usb_basic_init (&pudev->bp, &pudev->regs, core);
usb_basic_init(&pudev->bp, &pudev->regs, core);
#ifndef DUAL_ROLE_MODE_ENABLED
usb_core_init (pudev->bp, &pudev->regs);
usb_core_init(pudev->bp, &pudev->regs);
usb_host_init (pudev);
usb_host_init(pudev);
#endif /* DUAL_ROLE_MODE_ENABLED */
/* upon init call usr call back */
puhost->usr_cb->dev_init();
/* upon init call usr call back */
puhost->usr_cb->dev_init();
}
/*!
@@ -107,23 +102,22 @@ void usbh_init (usb_core_driver *pudev, usb_core_enum core, usbh_host *puhost)
\param[out] none
\retval operation status
*/
usbh_status usbh_deinit(usb_core_driver *pudev, usbh_host *puhost)
{
/* software init */
puhost->cur_state = HOST_DEFAULT;
puhost->backup_state = HOST_DEFAULT;
puhost->enum_state = ENUM_DEFAULT;
usbh_status usbh_deinit(usb_core_driver *pudev, usbh_host *puhost) {
/* software init */
puhost->cur_state = HOST_DEFAULT;
puhost->backup_state = HOST_DEFAULT;
puhost->enum_state = ENUM_DEFAULT;
puhost->control.ctl_state = CTL_IDLE;
puhost->control.max_len = USB_FS_EP0_MAX_LEN;
puhost->control.ctl_state = CTL_IDLE;
puhost->control.max_len = USB_FS_EP0_MAX_LEN;
puhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT;
puhost->dev_prop.speed = PORT_SPEED_FULL;
puhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT;
puhost->dev_prop.speed = PORT_SPEED_FULL;
usbh_pipe_free(pudev, puhost->control.pipe_in_num);
usbh_pipe_free(pudev, puhost->control.pipe_out_num);
usbh_pipe_free(pudev, puhost->control.pipe_in_num);
usbh_pipe_free(pudev, puhost->control.pipe_out_num);
return USBH_OK;
return USBH_OK;
}
/*!
@@ -133,129 +127,120 @@ usbh_status usbh_deinit(usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval none
*/
void usbh_core_task (usb_core_driver *pudev, usbh_host *puhost)
{
volatile usbh_status status = USBH_FAIL;
void usbh_core_task(usb_core_driver *pudev, usbh_host *puhost) {
volatile usbh_status status = USBH_FAIL;
/* check for host port events */
if (((0U == pudev->host.connect_status) || (0U == pudev->host.port_enabled)) && (HOST_DEFAULT != puhost->cur_state)) {
if (puhost->cur_state != HOST_DEV_DETACHED) {
puhost->cur_state = HOST_DEV_DETACHED;
}
/* check for host port events */
if (((0U == pudev->host.connect_status) || (0U == pudev->host.port_enabled)) && (HOST_DEFAULT != puhost->cur_state)) {
if (puhost->cur_state != HOST_DEV_DETACHED) {
puhost->cur_state = HOST_DEV_DETACHED;
}
}
switch (puhost->cur_state) {
case HOST_DEFAULT:
if (pudev->host.connect_status) {
puhost->cur_state = HOST_DETECT_DEV_SPEED;
switch (puhost->cur_state) {
case HOST_DEFAULT:
if (pudev->host.connect_status) {
puhost->cur_state = HOST_DETECT_DEV_SPEED;
usb_mdelay (100U);
// usb_mdelay (2U);
usb_port_reset (pudev);
usb_mdelay(100U);
// usb_mdelay (2U);
usb_port_reset(pudev);
puhost->usr_cb->dev_reset();
}
break;
case HOST_DETECT_DEV_SPEED:
if (pudev->host.port_enabled) {
puhost->cur_state = HOST_DEV_ATTACHED;
puhost->dev_prop.speed = usb_curspeed_get (pudev);
puhost->usr_cb->dev_speed_detected(puhost->dev_prop.speed);
usb_mdelay (50U);
}
break;
case HOST_DEV_ATTACHED:
puhost->usr_cb->dev_attach();
puhost->control.pipe_out_num = usbh_pipe_allocate(pudev, 0x00U);
puhost->control.pipe_in_num = usbh_pipe_allocate(pudev, 0x80U);
/* reset USB device */
usb_port_reset (pudev);
/* open IN control pipe */
usbh_pipe_create (pudev,
&puhost->dev_prop,
puhost->control.pipe_in_num,
USB_EPTYPE_CTRL,
puhost->control.max_len);
/* open OUT control pipe */
usbh_pipe_create (pudev,
&puhost->dev_prop,
puhost->control.pipe_out_num,
USB_EPTYPE_CTRL,
puhost->control.max_len);
puhost->cur_state = HOST_ENUM;
break;
case HOST_ENUM:
/* check for enumeration status */
if (USBH_OK == usbh_enum_task (pudev, puhost)) {
/* the function shall return USBH_OK when full enumeration is complete */
/* user callback for end of device basic enumeration */
puhost->usr_cb->dev_enumerated();
puhost->cur_state = HOST_USER_INPUT;
}
break;
case HOST_USER_INPUT:
/* the function should return user response true to move to class state */
if (USBH_USER_RESP_OK == puhost->usr_cb->dev_user_input()) {
if ((USBH_OK == puhost->class_cb->class_init(pudev, puhost))) {
puhost->cur_state = HOST_CLASS_ENUM;
}
}
break;
case HOST_CLASS_ENUM:
/* process class standard contol requests state machine */
status = puhost->class_cb->class_requests(pudev, puhost);
if (USBH_OK == status) {
puhost->cur_state = HOST_CLASS_HANDLER;
} else {
usbh_error_handler (puhost, status);
}
break;
case HOST_CLASS_HANDLER:
/* process class state machine */
status = puhost->class_cb->class_machine(pudev, puhost);
usbh_error_handler (puhost, status);
break;
case HOST_SUSPENDED:
break;
case HOST_ERROR:
/* re-initilaize host for new enumeration */
usbh_deinit (pudev, puhost);
puhost->usr_cb->dev_deinit();
puhost->class_cb->class_deinit(pudev, puhost);
break;
case HOST_DEV_DETACHED:
/* manage user disconnect operations*/
puhost->usr_cb->dev_detach();
/* re-initilaize host for new enumeration */
usbh_deinit(pudev, puhost);
puhost->usr_cb->dev_deinit();
puhost->class_cb->class_deinit(pudev, puhost);
usbh_pipe_delete(pudev);
puhost->cur_state = HOST_DEFAULT;
break;
default:
break;
puhost->usr_cb->dev_reset();
}
break;
case HOST_DETECT_DEV_SPEED:
if (pudev->host.port_enabled) {
puhost->cur_state = HOST_DEV_ATTACHED;
puhost->dev_prop.speed = usb_curspeed_get(pudev);
puhost->usr_cb->dev_speed_detected(puhost->dev_prop.speed);
usb_mdelay(50U);
}
break;
case HOST_DEV_ATTACHED:
puhost->usr_cb->dev_attach();
puhost->control.pipe_out_num = usbh_pipe_allocate(pudev, 0x00U);
puhost->control.pipe_in_num = usbh_pipe_allocate(pudev, 0x80U);
/* reset USB device */
usb_port_reset(pudev);
/* open IN control pipe */
usbh_pipe_create(pudev, &puhost->dev_prop, puhost->control.pipe_in_num, USB_EPTYPE_CTRL, puhost->control.max_len);
/* open OUT control pipe */
usbh_pipe_create(pudev, &puhost->dev_prop, puhost->control.pipe_out_num, USB_EPTYPE_CTRL, puhost->control.max_len);
puhost->cur_state = HOST_ENUM;
break;
case HOST_ENUM:
/* check for enumeration status */
if (USBH_OK == usbh_enum_task(pudev, puhost)) {
/* the function shall return USBH_OK when full enumeration is complete */
/* user callback for end of device basic enumeration */
puhost->usr_cb->dev_enumerated();
puhost->cur_state = HOST_USER_INPUT;
}
break;
case HOST_USER_INPUT:
/* the function should return user response true to move to class state */
if (USBH_USER_RESP_OK == puhost->usr_cb->dev_user_input()) {
if ((USBH_OK == puhost->class_cb->class_init(pudev, puhost))) {
puhost->cur_state = HOST_CLASS_ENUM;
}
}
break;
case HOST_CLASS_ENUM:
/* process class standard contol requests state machine */
status = puhost->class_cb->class_requests(pudev, puhost);
if (USBH_OK == status) {
puhost->cur_state = HOST_CLASS_HANDLER;
} else {
usbh_error_handler(puhost, status);
}
break;
case HOST_CLASS_HANDLER:
/* process class state machine */
status = puhost->class_cb->class_machine(pudev, puhost);
usbh_error_handler(puhost, status);
break;
case HOST_SUSPENDED:
break;
case HOST_ERROR:
/* re-initilaize host for new enumeration */
usbh_deinit(pudev, puhost);
puhost->usr_cb->dev_deinit();
puhost->class_cb->class_deinit(pudev, puhost);
break;
case HOST_DEV_DETACHED:
/* manage user disconnect operations*/
puhost->usr_cb->dev_detach();
/* re-initilaize host for new enumeration */
usbh_deinit(pudev, puhost);
puhost->usr_cb->dev_deinit();
puhost->class_cb->class_deinit(pudev, puhost);
usbh_pipe_delete(pudev);
puhost->cur_state = HOST_DEFAULT;
break;
default:
break;
}
}
/*!
@@ -265,19 +250,18 @@ void usbh_core_task (usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval none
*/
void usbh_error_handler (usbh_host *puhost, usbh_status err_type)
{
/* error unrecovered or not supported device speed */
if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) {
puhost->usr_cb->dev_error();
void usbh_error_handler(usbh_host *puhost, usbh_status err_type) {
/* error unrecovered or not supported device speed */
if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) {
puhost->usr_cb->dev_error();
puhost->cur_state = HOST_ERROR;
} else if (USBH_APPLY_DEINIT == err_type) {
puhost->cur_state = HOST_ERROR;
puhost->cur_state = HOST_ERROR;
} else if (USBH_APPLY_DEINIT == err_type) {
puhost->cur_state = HOST_ERROR;
/* user callback for initalization */
puhost->usr_cb->dev_init();
}
/* user callback for initalization */
puhost->usr_cb->dev_init();
}
}
/*!
@@ -287,155 +271,125 @@ void usbh_error_handler (usbh_host *puhost, usbh_status err_type)
\param[out] none
\retval none
*/
static usbh_status usbh_enum_task (usb_core_driver *pudev, usbh_host *puhost)
{
uint8_t str_buf[64];
static usbh_status usbh_enum_task(usb_core_driver *pudev, usbh_host *puhost) {
uint8_t str_buf[64];
usbh_status status = USBH_BUSY;
usbh_status status = USBH_BUSY;
static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U;
static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U;
switch (puhost->enum_state) {
case ENUM_DEFAULT:
/* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */
if (USBH_OK == usbh_devdesc_get (pudev, puhost, 8U)) {
switch (puhost->enum_state) {
case ENUM_DEFAULT:
/* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */
if (USBH_OK == usbh_devdesc_get(pudev, puhost, 8U)) {
puhost->control.max_len = puhost->dev_prop.dev_desc.bMaxPacketSize0;
puhost->control.max_len = puhost->dev_prop.dev_desc.bMaxPacketSize0;
/* issue reset */
usb_port_reset (pudev);
/* issue reset */
usb_port_reset(pudev);
/* modify control channels configuration for maximum packet size */
usbh_pipe_update (pudev,
puhost->control.pipe_out_num,
0U, 0U,
puhost->control.max_len);
/* modify control channels configuration for maximum packet size */
usbh_pipe_update(pudev, puhost->control.pipe_out_num, 0U, 0U, puhost->control.max_len);
usbh_pipe_update (pudev,
puhost->control.pipe_in_num,
0U, 0U,
puhost->control.max_len);
usbh_pipe_update(pudev, puhost->control.pipe_in_num, 0U, 0U, puhost->control.max_len);
puhost->enum_state = ENUM_GET_DEV_DESC;
}
break;
case ENUM_GET_DEV_DESC:
/* get full device descriptor */
if (USBH_OK == usbh_devdesc_get (pudev, puhost, USB_DEV_DESC_LEN)) {
puhost->usr_cb->dev_devdesc_assigned(&puhost->dev_prop.dev_desc);
index_mfc_str = puhost->dev_prop.dev_desc.iManufacturer;
index_prod_str = puhost->dev_prop.dev_desc.iProduct;
index_serial_str = puhost->dev_prop.dev_desc.iSerialNumber;
puhost->enum_state = ENUM_SET_ADDR;
}
break;
case ENUM_SET_ADDR:
/* set address */
if (USBH_OK == usbh_setaddress (pudev, puhost, USBH_DEV_ADDR)) {
usb_mdelay (2);
puhost->dev_prop.addr = USBH_DEV_ADDR;
/* user callback for device address assigned */
puhost->usr_cb->dev_address_set();
/* modify control channels to update device address */
usbh_pipe_update (pudev,
puhost->control.pipe_in_num,
puhost->dev_prop.addr,
0U, 0U);
usbh_pipe_update (pudev,
puhost->control.pipe_out_num,
puhost->dev_prop.addr,
0U, 0U);
puhost->enum_state = ENUM_GET_CFG_DESC;
}
break;
case ENUM_GET_CFG_DESC:
/* get standard configuration descriptor */
if (USBH_OK == usbh_cfgdesc_get (pudev, puhost, USB_CFG_DESC_LEN)) {
puhost->enum_state = ENUM_GET_CFG_DESC_SET;
}
break;
case ENUM_GET_CFG_DESC_SET:
/* get full config descriptor (config, interface, endpoints) */
if (USBH_OK == usbh_cfgdesc_get (pudev, puhost, puhost->dev_prop.cfg_desc.wTotalLength)) {
/* user callback for configuration descriptors available */
puhost->usr_cb->dev_cfgdesc_assigned (&puhost->dev_prop.cfg_desc,
puhost->dev_prop.itf_desc,
puhost->dev_prop.ep_desc[0]);
puhost->enum_state = ENUM_GET_STR_DESC;
}
break;
case ENUM_GET_STR_DESC:
if (index_mfc_str) {
if (USBH_OK == usbh_strdesc_get (pudev,
puhost,
puhost->dev_prop.dev_desc.iManufacturer,
str_buf,
0xFFU)) {
/* user callback for manufacturing string */
puhost->usr_cb->dev_mfc_str(str_buf);
index_mfc_str = 0U;
}
} else {
if (index_prod_str) {
/* check that product string is available */
if (USBH_OK == usbh_strdesc_get (pudev,
puhost,
puhost->dev_prop.dev_desc.iProduct,
str_buf,
0xFFU)) {
puhost->usr_cb->dev_prod_str(str_buf);
index_prod_str = 0U;
}
} else {
if (index_serial_str) {
if (USBH_OK == usbh_strdesc_get (pudev,
puhost,
puhost->dev_prop.dev_desc.iSerialNumber,
str_buf,
0xFFU)) {
puhost->usr_cb->dev_seral_str(str_buf);
puhost->enum_state = ENUM_SET_CONFIGURATION;
index_serial_str = 0U;
}
} else {
puhost->enum_state = ENUM_SET_CONFIGURATION;
}
}
}
break;
case ENUM_SET_CONFIGURATION:
if (USBH_OK == usbh_setcfg (pudev,
puhost,
puhost->dev_prop.cfg_desc.bConfigurationValue)) {
puhost->enum_state = ENUM_DEV_CONFIGURED;
}
break;
case ENUM_DEV_CONFIGURED:
status = USBH_OK;
break;
default:
break;
puhost->enum_state = ENUM_GET_DEV_DESC;
}
break;
return status;
case ENUM_GET_DEV_DESC:
/* get full device descriptor */
if (USBH_OK == usbh_devdesc_get(pudev, puhost, USB_DEV_DESC_LEN)) {
puhost->usr_cb->dev_devdesc_assigned(&puhost->dev_prop.dev_desc);
index_mfc_str = puhost->dev_prop.dev_desc.iManufacturer;
index_prod_str = puhost->dev_prop.dev_desc.iProduct;
index_serial_str = puhost->dev_prop.dev_desc.iSerialNumber;
puhost->enum_state = ENUM_SET_ADDR;
}
break;
case ENUM_SET_ADDR:
/* set address */
if (USBH_OK == usbh_setaddress(pudev, puhost, USBH_DEV_ADDR)) {
usb_mdelay(2);
puhost->dev_prop.addr = USBH_DEV_ADDR;
/* user callback for device address assigned */
puhost->usr_cb->dev_address_set();
/* modify control channels to update device address */
usbh_pipe_update(pudev, puhost->control.pipe_in_num, puhost->dev_prop.addr, 0U, 0U);
usbh_pipe_update(pudev, puhost->control.pipe_out_num, puhost->dev_prop.addr, 0U, 0U);
puhost->enum_state = ENUM_GET_CFG_DESC;
}
break;
case ENUM_GET_CFG_DESC:
/* get standard configuration descriptor */
if (USBH_OK == usbh_cfgdesc_get(pudev, puhost, USB_CFG_DESC_LEN)) {
puhost->enum_state = ENUM_GET_CFG_DESC_SET;
}
break;
case ENUM_GET_CFG_DESC_SET:
/* get full config descriptor (config, interface, endpoints) */
if (USBH_OK == usbh_cfgdesc_get(pudev, puhost, puhost->dev_prop.cfg_desc.wTotalLength)) {
/* user callback for configuration descriptors available */
puhost->usr_cb->dev_cfgdesc_assigned(&puhost->dev_prop.cfg_desc, puhost->dev_prop.itf_desc, puhost->dev_prop.ep_desc[0]);
puhost->enum_state = ENUM_GET_STR_DESC;
}
break;
case ENUM_GET_STR_DESC:
if (index_mfc_str) {
if (USBH_OK == usbh_strdesc_get(pudev, puhost, puhost->dev_prop.dev_desc.iManufacturer, str_buf, 0xFFU)) {
/* user callback for manufacturing string */
puhost->usr_cb->dev_mfc_str(str_buf);
index_mfc_str = 0U;
}
} else {
if (index_prod_str) {
/* check that product string is available */
if (USBH_OK == usbh_strdesc_get(pudev, puhost, puhost->dev_prop.dev_desc.iProduct, str_buf, 0xFFU)) {
puhost->usr_cb->dev_prod_str(str_buf);
index_prod_str = 0U;
}
} else {
if (index_serial_str) {
if (USBH_OK == usbh_strdesc_get(pudev, puhost, puhost->dev_prop.dev_desc.iSerialNumber, str_buf, 0xFFU)) {
puhost->usr_cb->dev_seral_str(str_buf);
puhost->enum_state = ENUM_SET_CONFIGURATION;
index_serial_str = 0U;
}
} else {
puhost->enum_state = ENUM_SET_CONFIGURATION;
}
}
}
break;
case ENUM_SET_CONFIGURATION:
if (USBH_OK == usbh_setcfg(pudev, puhost, puhost->dev_prop.cfg_desc.bConfigurationValue)) {
puhost->enum_state = ENUM_DEV_CONFIGURED;
}
break;
case ENUM_DEV_CONFIGURED:
status = USBH_OK;
break;
default:
break;
}
return status;
}

View File

@@ -8,40 +8,39 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "usbh_transc.h"
#include "usbh_enum.h"
#include "usbh_transc.h"
static void usbh_devdesc_parse (usb_desc_dev *cfg_desc, uint8_t *buf, uint16_t len);
static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf);
static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf);
static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf);
static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf);
static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len);
static void usbh_devdesc_parse(usb_desc_dev *cfg_desc, uint8_t *buf, uint16_t len);
static void usbh_cfgset_parse(usb_dev_prop *udev, uint8_t *buf);
static void usbh_cfgdesc_parse(usb_desc_config *cfg_desc, uint8_t *buf);
static void usbh_itfdesc_parse(usb_desc_itf *itf_desc, uint8_t *buf);
static void usbh_epdesc_parse(usb_desc_ep *ep_desc, uint8_t *buf);
static void usbh_strdesc_parse(uint8_t *psrc, uint8_t *pdest, uint16_t len);
/*!
\brief configure USB control status parameters
@@ -51,13 +50,12 @@ static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len);
\param[out] none
\retval none
*/
void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len)
{
/* prepare the transactions */
puhost->control.buf = buf;
puhost->control.ctl_len = len;
void usbh_ctlstate_config(usbh_host *puhost, uint8_t *buf, uint16_t len) {
/* prepare the transactions */
puhost->control.buf = buf;
puhost->control.ctl_len = len;
puhost->control.ctl_state = CTL_SETUP;
puhost->control.ctl_state = CTL_SETUP;
}
/*!
@@ -68,32 +66,26 @@ void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len)
\param[out] none
\retval operation status
*/
usbh_status usbh_devdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint8_t len)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_devdesc_get(usb_core_driver *pudev, usbh_host *puhost, uint8_t len) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_GET_DESCRIPTOR,
.wValue = USBH_DESC(USB_DESCTYPE_DEV),
.wIndex = 0U,
.wLength = len
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req
= (usb_req){.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, .bRequest = USB_GET_DESCRIPTOR, .wValue = USBH_DESC(USB_DESCTYPE_DEV), .wIndex = 0U, .wLength = len};
usbh_ctlstate_config (puhost, pudev->host.rx_buf, len);
}
usbh_ctlstate_config(puhost, pudev->host.rx_buf, len);
}
status = usbh_ctl_handler (pudev, puhost);
status = usbh_ctl_handler(pudev, puhost);
if (USBH_OK == status) {
/* commands successfully sent and response received */
usbh_devdesc_parse (&puhost->dev_prop.dev_desc, pudev->host.rx_buf, len);
}
if (USBH_OK == status) {
/* commands successfully sent and response received */
usbh_devdesc_parse(&puhost->dev_prop.dev_desc, pudev->host.rx_buf, len);
}
return status;
return status;
}
/*!
@@ -104,35 +96,29 @@ usbh_status usbh_devdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint8_t
\param[out] none
\retval operation status
*/
usbh_status usbh_cfgdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint16_t len)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_cfgdesc_get(usb_core_driver *pudev, usbh_host *puhost, uint16_t len) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_GET_DESCRIPTOR,
.wValue = USBH_DESC(USB_DESCTYPE_CONFIG),
.wIndex = 0U,
.wLength = len
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req
= (usb_req){.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, .bRequest = USB_GET_DESCRIPTOR, .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), .wIndex = 0U, .wLength = len};
usbh_ctlstate_config (puhost, pudev->host.rx_buf, len);
usbh_ctlstate_config(puhost, pudev->host.rx_buf, len);
}
status = usbh_ctl_handler(pudev, puhost);
if (USBH_OK == status) {
if (len <= USB_CFG_DESC_LEN) {
usbh_cfgdesc_parse(&puhost->dev_prop.cfg_desc, pudev->host.rx_buf);
} else {
usbh_cfgset_parse(&puhost->dev_prop, pudev->host.rx_buf);
}
}
status = usbh_ctl_handler (pudev, puhost);
if (USBH_OK == status) {
if (len <= USB_CFG_DESC_LEN) {
usbh_cfgdesc_parse (&puhost->dev_prop.cfg_desc, pudev->host.rx_buf);
} else {
usbh_cfgset_parse (&puhost->dev_prop, pudev->host.rx_buf);
}
}
return status;
return status;
}
/*!
@@ -145,36 +131,26 @@ usbh_status usbh_cfgdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint16_
\param[out] none
\retval operation status
*/
usbh_status usbh_strdesc_get (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t str_index,
uint8_t *buf,
uint16_t len)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_strdesc_get(usb_core_driver *pudev, usbh_host *puhost, uint8_t str_index, uint8_t *buf, uint16_t len) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_GET_DESCRIPTOR,
.wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index,
.wIndex = 0x0409U,
.wLength = len
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req){
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, .bRequest = USB_GET_DESCRIPTOR, .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, .wIndex = 0x0409U, .wLength = len};
usbh_ctlstate_config (puhost, pudev->host.rx_buf, len);
}
usbh_ctlstate_config(puhost, pudev->host.rx_buf, len);
}
status = usbh_ctl_handler (pudev, puhost);
status = usbh_ctl_handler(pudev, puhost);
if (USBH_OK == status) {
/* commands successfully sent and response received */
usbh_strdesc_parse (pudev->host.rx_buf, buf, len);
}
if (USBH_OK == status) {
/* commands successfully sent and response received */
usbh_strdesc_parse(pudev->host.rx_buf, buf, len);
}
return status;
return status;
}
/*!
@@ -185,27 +161,20 @@ usbh_status usbh_strdesc_get (usb_core_driver *pudev,
\param[out] none
\retval operation status
*/
usbh_status usbh_setaddress (usb_core_driver *pudev, usbh_host *puhost, uint8_t dev_addr)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_setaddress(usb_core_driver *pudev, usbh_host *puhost, uint8_t dev_addr) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_SET_ADDRESS,
.wValue = (uint16_t)dev_addr,
.wIndex = 0U,
.wLength = 0U
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req){.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, .bRequest = USB_SET_ADDRESS, .wValue = (uint16_t)dev_addr, .wIndex = 0U, .wLength = 0U};
usbh_ctlstate_config (puhost, NULL, 0U);
}
usbh_ctlstate_config(puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
status = usbh_ctl_handler(pudev, puhost);
return status;
return status;
}
/*!
@@ -216,27 +185,20 @@ usbh_status usbh_setaddress (usb_core_driver *pudev, usbh_host *puhost, uint8_t
\param[out] none
\retval operation status
*/
usbh_status usbh_setcfg (usb_core_driver *pudev, usbh_host *puhost, uint16_t config_index)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_setcfg(usb_core_driver *pudev, usbh_host *puhost, uint16_t config_index) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_SET_CONFIGURATION,
.wValue = config_index,
.wIndex = 0U,
.wLength = 0U
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req){.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, .bRequest = USB_SET_CONFIGURATION, .wValue = config_index, .wIndex = 0U, .wLength = 0U};
usbh_ctlstate_config (puhost, NULL, 0U);
}
usbh_ctlstate_config(puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
status = usbh_ctl_handler(pudev, puhost);
return status;
return status;
}
/*!
@@ -248,30 +210,20 @@ usbh_status usbh_setcfg (usb_core_driver *pudev, usbh_host *puhost, uint16_t con
\param[out] none
\retval operation status
*/
usbh_status usbh_setinterface (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t ep_num,
uint8_t set)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_setinterface(usb_core_driver *pudev, usbh_host *puhost, uint8_t ep_num, uint8_t set) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD,
.bRequest = USB_SET_INTERFACE,
.wValue = set,
.wIndex = ep_num,
.wLength = 0U
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req){.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, .bRequest = USB_SET_INTERFACE, .wValue = set, .wIndex = ep_num, .wLength = 0U};
usbh_ctlstate_config (puhost, NULL, 0U);
}
usbh_ctlstate_config(puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
status = usbh_ctl_handler(pudev, puhost);
return status;
return status;
}
/*!
@@ -283,36 +235,26 @@ usbh_status usbh_setinterface (usb_core_driver *pudev,
\param[out] none
\retval operation status
*/
usbh_status usbh_clrfeature (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t ep_addr,
uint8_t pp_num)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_clrfeature(usb_core_driver *pudev, usbh_host *puhost, uint8_t ep_addr, uint8_t pp_num) {
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD,
.bRequest = USB_CLEAR_FEATURE,
.wValue = FEATURE_SELECTOR_EP,
.wIndex = ep_addr,
.wLength = 0
};
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req){.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, .bRequest = USB_CLEAR_FEATURE, .wValue = FEATURE_SELECTOR_EP, .wIndex = ep_addr, .wLength = 0};
if (EP_DIR(ep_addr)) {
pudev->host.pipe[pp_num].data_toggle_in = 0U;
} else {
pudev->host.pipe[pp_num].data_toggle_out = 0U;
}
if (EP_DIR(ep_addr)) {
pudev->host.pipe[pp_num].data_toggle_in = 0U;
} else {
pudev->host.pipe[pp_num].data_toggle_out = 0U;
}
usbh_ctlstate_config (puhost, NULL, 0U);
}
usbh_ctlstate_config(puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
status = usbh_ctl_handler(pudev, puhost);
return status;
return status;
}
/*!
@@ -323,31 +265,25 @@ usbh_status usbh_clrfeature (usb_core_driver *pudev,
\param[out] none
\retval operation status
*/
static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len)
{
*dev_desc = (usb_desc_dev) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U)
},
static void usbh_devdesc_parse(usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) {
*dev_desc = (usb_desc_dev){.header = {.bLength = *(uint8_t *)(buf + 0U), .bDescriptorType = *(uint8_t *)(buf + 1U)},
.bcdUSB = BYTE_SWAP(buf + 2U),
.bDeviceClass = *(uint8_t *)(buf + 4U),
.bDeviceSubClass = *(uint8_t *)(buf + 5U),
.bDeviceProtocol = *(uint8_t *)(buf + 6U),
.bMaxPacketSize0 = *(uint8_t *)(buf + 7U)
};
.bcdUSB = BYTE_SWAP(buf + 2U),
.bDeviceClass = *(uint8_t *)(buf + 4U),
.bDeviceSubClass = *(uint8_t *)(buf + 5U),
.bDeviceProtocol = *(uint8_t *)(buf + 6U),
.bMaxPacketSize0 = *(uint8_t *)(buf + 7U)};
if (len > 8U) {
/* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */
dev_desc->idVendor = BYTE_SWAP(buf + 8U);
dev_desc->idProduct = BYTE_SWAP(buf + 10U);
dev_desc->bcdDevice = BYTE_SWAP(buf + 12U);
dev_desc->iManufacturer = *(uint8_t *)(buf + 14U);
dev_desc->iProduct = *(uint8_t *)(buf + 15U);
dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U);
dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U);
}
if (len > 8U) {
/* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */
dev_desc->idVendor = BYTE_SWAP(buf + 8U);
dev_desc->idProduct = BYTE_SWAP(buf + 10U);
dev_desc->bcdDevice = BYTE_SWAP(buf + 12U);
dev_desc->iManufacturer = *(uint8_t *)(buf + 14U);
dev_desc->iProduct = *(uint8_t *)(buf + 15U);
dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U);
dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U);
}
}
/*!
@@ -357,10 +293,9 @@ static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t
\param[out] none
\retval operation status
*/
static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf)
{
/* parse configuration descriptor */
*cfg_desc = (usb_desc_config) {
static void usbh_cfgdesc_parse(usb_desc_config *cfg_desc, uint8_t *buf) {
/* parse configuration descriptor */
*cfg_desc = (usb_desc_config) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U),
@@ -382,68 +317,67 @@ static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf)
\param[out] none
\retval operation status
*/
static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf)
{
usb_desc_ep *ep = NULL;
usb_desc_itf *itf = NULL, itf_value;
static void usbh_cfgset_parse(usb_dev_prop *udev, uint8_t *buf) {
usb_desc_ep * ep = NULL;
usb_desc_itf *itf = NULL, itf_value;
usb_desc_header *pdesc = (usb_desc_header *)buf;
usb_desc_header *pdesc = (usb_desc_header *)buf;
int8_t itf_index = 0U, ep_index = 0U;
uint16_t ptr;
int8_t itf_index = 0U, ep_index = 0U;
uint16_t ptr;
uint8_t prev_itf = 0U;
uint16_t prev_ep_len = 0U;
uint8_t prev_itf = 0U;
uint16_t prev_ep_len = 0U;
/* parse configuration descriptor */
usbh_cfgdesc_parse (&udev->cfg_desc, buf);
/* parse configuration descriptor */
usbh_cfgdesc_parse(&udev->cfg_desc, buf);
ptr = USB_CFG_DESC_LEN;
ptr = USB_CFG_DESC_LEN;
if (udev->cfg_desc.bNumInterfaces > USBH_MAX_INTERFACES_NUM) {
return;
}
if (udev->cfg_desc.bNumInterfaces > USBH_MAX_INTERFACES_NUM) {
return;
}
while (ptr < udev->cfg_desc.wTotalLength) {
pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr);
while (ptr < udev->cfg_desc.wTotalLength) {
pdesc = usbh_nextdesc_get((uint8_t *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) {
itf_index = *(((uint8_t *)pdesc) + 2U);
itf = &udev->itf_desc[itf_index];
if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) {
itf_index = *(((uint8_t *)pdesc) + 2U);
itf = &udev->itf_desc[itf_index];
if ((*((uint8_t *)pdesc + 3U)) < 3U) {
usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc);
if ((*((uint8_t *)pdesc + 3U)) < 3U) {
usbh_itfdesc_parse(&itf_value, (uint8_t *)pdesc);
/* parse endpoint descriptors relative to the current interface */
if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) {
return;
}
for (ep_index = 0; ep_index < itf_value.bNumEndpoints; ) {
pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESCTYPE_EP) {
ep = &udev->ep_desc[itf_index][ep_index];
if (prev_itf != itf_index) {
prev_itf = itf_index;
usbh_itfdesc_parse (itf, (uint8_t *)&itf_value);
} else {
if (prev_ep_len > BYTE_SWAP((uint8_t *)pdesc + 4U)) {
break;
} else {
usbh_itfdesc_parse (itf, (uint8_t *)&itf_value);
}
}
usbh_epdesc_parse (ep, (uint8_t *)pdesc);
prev_ep_len = BYTE_SWAP((uint8_t *)pdesc + 4U);
ep_index++;
}
}
}
/* parse endpoint descriptors relative to the current interface */
if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) {
return;
}
for (ep_index = 0; ep_index < itf_value.bNumEndpoints;) {
pdesc = usbh_nextdesc_get((void *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESCTYPE_EP) {
ep = &udev->ep_desc[itf_index][ep_index];
if (prev_itf != itf_index) {
prev_itf = itf_index;
usbh_itfdesc_parse(itf, (uint8_t *)&itf_value);
} else {
if (prev_ep_len > BYTE_SWAP((uint8_t *)pdesc + 4U)) {
break;
} else {
usbh_itfdesc_parse(itf, (uint8_t *)&itf_value);
}
}
usbh_epdesc_parse(ep, (uint8_t *)pdesc);
prev_ep_len = BYTE_SWAP((uint8_t *)pdesc + 4U);
ep_index++;
}
}
}
}
}
}
/*!
@@ -453,9 +387,8 @@ static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf)
\param[out] none
\retval operation status
*/
static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf)
{
*itf_desc = (usb_desc_itf) {
static void usbh_itfdesc_parse(usb_desc_itf *itf_desc, uint8_t *buf) {
*itf_desc = (usb_desc_itf) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U),
@@ -478,19 +411,13 @@ static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf)
\param[out] none
\retval operation status
*/
static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf)
{
*ep_desc = (usb_desc_ep) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U)
},
static void usbh_epdesc_parse(usb_desc_ep *ep_desc, uint8_t *buf) {
*ep_desc = (usb_desc_ep){.header = {.bLength = *(uint8_t *)(buf + 0U), .bDescriptorType = *(uint8_t *)(buf + 1U)},
.bEndpointAddress = *(uint8_t *)(buf + 2U),
.bmAttributes = *(uint8_t *)(buf + 3U),
.wMaxPacketSize = BYTE_SWAP(buf + 4U),
.bInterval = *(uint8_t *)(buf + 6U)
};
.bEndpointAddress = *(uint8_t *)(buf + 2U),
.bmAttributes = *(uint8_t *)(buf + 3U),
.wMaxPacketSize = BYTE_SWAP(buf + 4U),
.bInterval = *(uint8_t *)(buf + 6U)};
}
/*!
@@ -501,32 +428,31 @@ static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf)
\param[out] none
\retval operation status
*/
static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len)
{
uint16_t str_len = 0U, index = 0U;
static void usbh_strdesc_parse(uint8_t *psrc, uint8_t *pdest, uint16_t len) {
uint16_t str_len = 0U, index = 0U;
/* the unicode string descriptor is not NULL-terminated. The string length is
* computed by substracting two from the value of the first byte of the descriptor.
*/
/* the unicode string descriptor is not NULL-terminated. The string length is
* computed by substracting two from the value of the first byte of the descriptor.
*/
/* check which is lower size, the size of string or the length of bytes read from the device */
if (USB_DESCTYPE_STR == psrc[1]) {
/* make sure the descriptor is string type */
/* check which is lower size, the size of string or the length of bytes read from the device */
if (USB_DESCTYPE_STR == psrc[1]) {
/* make sure the descriptor is string type */
/* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
str_len = USB_MIN(psrc[0] - 2U, len);
/* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
str_len = USB_MIN(psrc[0] - 2U, len);
psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */
psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */
for (index = 0U; index < str_len; index += 2U) {
/* copy only the string and ignore the unicode id, hence add the src */
*pdest = psrc[index];
for (index = 0U; index < str_len; index += 2U) {
/* copy only the string and ignore the unicode id, hence add the src */
*pdest = psrc[index];
pdest++;
}
*pdest = 0U; /* mark end of string */
pdest++;
}
*pdest = 0U; /* mark end of string */
}
}
/*!
@@ -536,14 +462,12 @@ static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len)
\param[out] none
\retval operation status
*/
usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr)
{
usb_desc_header *pnext;
usb_desc_header *usbh_nextdesc_get(uint8_t *pbuf, uint16_t *ptr) {
usb_desc_header *pnext;
*ptr += ((usb_desc_header *)pbuf)->bLength;
*ptr += ((usb_desc_header *)pbuf)->bLength;
pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength);
pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength);
return (pnext);
return (pnext);
}

View File

@@ -8,33 +8,33 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "usbh_pipe.h"
static uint16_t usbh_freepipe_get (usb_core_driver *pudev);
static uint16_t usbh_freepipe_get(usb_core_driver *pudev);
/*!
\brief create a pipe
@@ -46,23 +46,18 @@ static uint16_t usbh_freepipe_get (usb_core_driver *pudev);
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_create (usb_core_driver *pudev,
usb_dev_prop *udev,
uint8_t pp_num,
uint8_t ep_type,
uint16_t ep_mpl)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
uint8_t usbh_pipe_create(usb_core_driver *pudev, usb_dev_prop *udev, uint8_t pp_num, uint8_t ep_type, uint16_t ep_mpl) {
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->dev_addr = udev->addr;
pp->dev_speed = udev->speed;
pp->ep.type = ep_type;
pp->ep.mps = ep_mpl;
pp->ping = udev->speed == PORT_SPEED_HIGH;
pp->dev_addr = udev->addr;
pp->dev_speed = udev->speed;
pp->ep.type = ep_type;
pp->ep.mps = ep_mpl;
pp->ping = udev->speed == PORT_SPEED_HIGH;
usb_pipe_init (pudev, pp_num);
usb_pipe_init(pudev, pp_num);
return HC_OK;
return HC_OK;
}
/*!
@@ -76,29 +71,24 @@ uint8_t usbh_pipe_create (usb_core_driver *pudev,
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_update (usb_core_driver *pudev,
uint8_t pp_num,
uint8_t dev_addr,
uint32_t dev_speed,
uint16_t ep_mpl)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
uint8_t usbh_pipe_update(usb_core_driver *pudev, uint8_t pp_num, uint8_t dev_addr, uint32_t dev_speed, uint16_t ep_mpl) {
usb_pipe *pp = &pudev->host.pipe[pp_num];
if ((pp->dev_addr != dev_addr) && (dev_addr)) {
pp->dev_addr = dev_addr;
}
if ((pp->dev_addr != dev_addr) && (dev_addr)) {
pp->dev_addr = dev_addr;
}
if ((pp->dev_speed != dev_speed) && (dev_speed)) {
pp->dev_speed = dev_speed;
}
if ((pp->dev_speed != dev_speed) && (dev_speed)) {
pp->dev_speed = dev_speed;
}
if ((pp->ep.mps != ep_mpl) && (ep_mpl)) {
pp->ep.mps = ep_mpl;
}
if ((pp->ep.mps != ep_mpl) && (ep_mpl)) {
pp->ep.mps = ep_mpl;
}
usb_pipe_init (pudev, pp_num);
usb_pipe_init(pudev, pp_num);
return HC_OK;
return HC_OK;
}
/*!
@@ -108,17 +98,16 @@ uint8_t usbh_pipe_update (usb_core_driver *pudev,
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr)
{
uint16_t pp_num = usbh_freepipe_get (pudev);
uint8_t usbh_pipe_allocate(usb_core_driver *pudev, uint8_t ep_addr) {
uint16_t pp_num = usbh_freepipe_get(pudev);
if (HC_ERROR != pp_num) {
pudev->host.pipe[pp_num].in_used = 1U;
pudev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr);
pudev->host.pipe[pp_num].ep.num = EP_ID(ep_addr);
}
if (HC_ERROR != pp_num) {
pudev->host.pipe[pp_num].in_used = 1U;
pudev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr);
pudev->host.pipe[pp_num].ep.num = EP_ID(ep_addr);
}
return pp_num;
return pp_num;
}
/*!
@@ -128,13 +117,12 @@ uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr)
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num)
{
if (pp_num < HC_MAX) {
pudev->host.pipe[pp_num].in_used = 0U;
}
uint8_t usbh_pipe_free(usb_core_driver *pudev, uint8_t pp_num) {
if (pp_num < HC_MAX) {
pudev->host.pipe[pp_num].in_used = 0U;
}
return USBH_OK;
return USBH_OK;
}
/*!
@@ -143,15 +131,14 @@ uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num)
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_delete (usb_core_driver *pudev)
{
uint8_t pp_num = 0U;
uint8_t usbh_pipe_delete(usb_core_driver *pudev) {
uint8_t pp_num = 0U;
for (pp_num = 2U; pp_num < HC_MAX; pp_num++) {
pudev->host.pipe[pp_num] = (usb_pipe) {0};
}
for (pp_num = 2U; pp_num < HC_MAX; pp_num++) {
pudev->host.pipe[pp_num] = (usb_pipe){0};
}
return USBH_OK;
return USBH_OK;
}
/*!
@@ -160,15 +147,14 @@ uint8_t usbh_pipe_delete (usb_core_driver *pudev)
\param[out] none
\retval operation status
*/
static uint16_t usbh_freepipe_get (usb_core_driver *pudev)
{
uint8_t pp_num = 0U;
static uint16_t usbh_freepipe_get(usb_core_driver *pudev) {
uint8_t pp_num = 0U;
for (pp_num = 0U; pp_num < HC_MAX; pp_num++) {
if (pudev->host.pipe[pp_num].in_used == 0U) {
return pp_num;
}
for (pp_num = 0U; pp_num < HC_MAX; pp_num++) {
if (pudev->host.pipe[pp_num].in_used == 0U) {
return pp_num;
}
}
return HC_ERROR;
return HC_ERROR;
}

View File

@@ -8,32 +8,32 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "drv_usb_hw.h"
#include "usbh_transc.h"
#include "drv_usb_hw.h"
/*!
\brief prepare a pipe and start a transfer
@@ -42,12 +42,11 @@ OF SUCH DAMAGE.
\param[out] none
\retval operation status
*/
static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num)
{
pudev->host.pipe[pp_num].urb_state = URB_IDLE;
pudev->host.pipe[pp_num].xfer_count = 0U;
static uint32_t usbh_request_submit(usb_core_driver *pudev, uint8_t pp_num) {
pudev->host.pipe[pp_num].urb_state = URB_IDLE;
pudev->host.pipe[pp_num].xfer_count = 0U;
return usb_pipe_xfer (pudev, pp_num);
return usb_pipe_xfer(pudev, pp_num);
}
/*!
@@ -58,15 +57,14 @@ static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num)
\param[out] none
\retval operation status
*/
usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
usbh_status usbh_ctlsetup_send(usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num) {
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->DPID = PIPE_DPID_SETUP;
pp->xfer_buf = buf;
pp->xfer_len = USB_SETUP_PACKET_LEN;
pp->DPID = PIPE_DPID_SETUP;
pp->xfer_buf = buf;
pp->xfer_len = USB_SETUP_PACKET_LEN;
return (usbh_status)usbh_request_submit (pudev, pp_num);
return (usbh_status)usbh_request_submit(pudev, pp_num);
}
/*!
@@ -78,43 +76,42 @@ usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp
\param[out] none
\retval operation status
*/
usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
usbh_status usbh_data_send(usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len) {
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->xfer_buf = buf;
pp->xfer_len = len;
pp->xfer_buf = buf;
pp->xfer_len = len;
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
if (0U == len) {
pp->data_toggle_out = 1U;
}
pp->DPID = PIPE_DPID[pp->data_toggle_out];
break;
case USB_EPTYPE_INTR:
pp->DPID = PIPE_DPID[pp->data_toggle_out];
pp->data_toggle_out ^= 1U;
break;
case USB_EPTYPE_BULK:
pp->DPID = PIPE_DPID[pp->data_toggle_out];
break;
case USB_EPTYPE_ISOC:
pp->DPID = PIPE_DPID[0];
break;
default:
break;
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
if (0U == len) {
pp->data_toggle_out = 1U;
}
usbh_request_submit (pudev, pp_num);
pp->DPID = PIPE_DPID[pp->data_toggle_out];
break;
return USBH_OK;
case USB_EPTYPE_INTR:
pp->DPID = PIPE_DPID[pp->data_toggle_out];
pp->data_toggle_out ^= 1U;
break;
case USB_EPTYPE_BULK:
pp->DPID = PIPE_DPID[pp->data_toggle_out];
break;
case USB_EPTYPE_ISOC:
pp->DPID = PIPE_DPID[0];
break;
default:
break;
}
usbh_request_submit(pudev, pp_num);
return USBH_OK;
}
/*!
@@ -126,40 +123,39 @@ usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num
\param[out] none
\retval operation status
*/
usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
usbh_status usbh_data_recev(usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len) {
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->xfer_buf = buf;
pp->xfer_len = len;
pp->xfer_buf = buf;
pp->xfer_len = len;
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
pp->DPID = PIPE_DPID[1];
break;
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
pp->DPID = PIPE_DPID[1];
break;
case USB_EPTYPE_INTR:
pp->DPID = PIPE_DPID[pp->data_toggle_in];
case USB_EPTYPE_INTR:
pp->DPID = PIPE_DPID[pp->data_toggle_in];
/* Toggle DATA PID */
pp->data_toggle_in ^= 1U;
break;
/* Toggle DATA PID */
pp->data_toggle_in ^= 1U;
break;
case USB_EPTYPE_BULK:
pp->DPID = PIPE_DPID[pp->data_toggle_in];
break;
case USB_EPTYPE_BULK:
pp->DPID = PIPE_DPID[pp->data_toggle_in];
break;
case USB_EPTYPE_ISOC:
pp->DPID = PIPE_DPID[0];
break;
case USB_EPTYPE_ISOC:
pp->DPID = PIPE_DPID[0];
break;
default:
break;
}
default:
break;
}
usbh_request_submit (pudev, pp_num);
usbh_request_submit(pudev, pp_num);
return USBH_OK;
return USBH_OK;
}
/*!
@@ -171,30 +167,28 @@ usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_nu
\param[out] none
\retval USB URB state
*/
static usb_urb_state usbh_urb_wait (usb_core_driver *pudev, usbh_host *puhost, uint8_t pp_num, uint32_t wait_time)
{
usb_urb_state urb_status = URB_IDLE;
static usb_urb_state usbh_urb_wait(usb_core_driver *pudev, usbh_host *puhost, uint8_t pp_num, uint32_t wait_time) {
usb_urb_state urb_status = URB_IDLE;
while (URB_DONE != (urb_status = usbh_urbstate_get(pudev, pp_num))) {
if (URB_NOTREADY == urb_status) {
break;
} else if (URB_STALL == urb_status) {
puhost->control.ctl_state = CTL_SETUP;
break;
} else if (URB_ERROR == urb_status) {
puhost->control.ctl_state = CTL_ERROR;
break;
} else if ((wait_time > 0U) && \
((usb_curframe_get(pudev)- puhost->control.timer) > wait_time)) {
/* timeout for in transfer */
puhost->control.ctl_state = CTL_ERROR;
break;
} else {
/* no operation, just wait */
}
while (URB_DONE != (urb_status = usbh_urbstate_get(pudev, pp_num))) {
if (URB_NOTREADY == urb_status) {
break;
} else if (URB_STALL == urb_status) {
puhost->control.ctl_state = CTL_SETUP;
break;
} else if (URB_ERROR == urb_status) {
puhost->control.ctl_state = CTL_ERROR;
break;
} else if ((wait_time > 0U) && ((usb_curframe_get(pudev) - puhost->control.timer) > wait_time)) {
/* timeout for in transfer */
puhost->control.ctl_state = CTL_ERROR;
break;
} else {
/* no operation, just wait */
}
}
return urb_status;
return urb_status;
}
/*!
@@ -204,37 +198,34 @@ static usb_urb_state usbh_urb_wait (usb_core_driver *pudev, usbh_host *puhost, u
\param[out] none
\retval none
*/
static void usbh_setup_transc (usb_core_driver *pudev, usbh_host *puhost)
{
usb_urb_state urb_status = URB_IDLE;
static void usbh_setup_transc(usb_core_driver *pudev, usbh_host *puhost) {
usb_urb_state urb_status = URB_IDLE;
/* send a SETUP packet */
usbh_ctlsetup_send (pudev,
puhost->control.setup.data,
puhost->control.pipe_out_num);
/* send a SETUP packet */
usbh_ctlsetup_send(pudev, puhost->control.setup.data, puhost->control.pipe_out_num);
urb_status = usbh_urb_wait (pudev, puhost, puhost->control.pipe_out_num, 0U);
urb_status = usbh_urb_wait(pudev, puhost, puhost->control.pipe_out_num, 0U);
if (URB_DONE == urb_status) {
uint8_t dir = (puhost->control.setup.req.bmRequestType & USB_TRX_MASK);
if (URB_DONE == urb_status) {
uint8_t dir = (puhost->control.setup.req.bmRequestType & USB_TRX_MASK);
if (puhost->control.setup.req.wLength) {
if (USB_TRX_IN == dir) {
puhost->control.ctl_state = CTL_DATA_IN;
} else {
puhost->control.ctl_state = CTL_DATA_OUT;
}
} else {
if (USB_TRX_IN == dir) {
puhost->control.ctl_state = CTL_STATUS_OUT;
} else {
puhost->control.ctl_state = CTL_STATUS_IN;
}
}
/* set the delay timer to enable timeout for data stage completion */
puhost->control.timer = usb_curframe_get(pudev);
if (puhost->control.setup.req.wLength) {
if (USB_TRX_IN == dir) {
puhost->control.ctl_state = CTL_DATA_IN;
} else {
puhost->control.ctl_state = CTL_DATA_OUT;
}
} else {
if (USB_TRX_IN == dir) {
puhost->control.ctl_state = CTL_STATUS_OUT;
} else {
puhost->control.ctl_state = CTL_STATUS_IN;
}
}
/* set the delay timer to enable timeout for data stage completion */
puhost->control.timer = usb_curframe_get(pudev);
}
}
/*!
@@ -244,22 +235,18 @@ static void usbh_setup_transc (usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval none
*/
static void usbh_data_in_transc (usb_core_driver *pudev, usbh_host *puhost)
{
usb_urb_state urb_status = URB_IDLE;
static void usbh_data_in_transc(usb_core_driver *pudev, usbh_host *puhost) {
usb_urb_state urb_status = URB_IDLE;
usbh_data_recev (pudev,
puhost->control.buf,
puhost->control.pipe_in_num,
puhost->control.ctl_len);
usbh_data_recev(pudev, puhost->control.buf, puhost->control.pipe_in_num, puhost->control.ctl_len);
urb_status = usbh_urb_wait (pudev, puhost, puhost->control.pipe_in_num, DATA_STAGE_TIMEOUT);
urb_status = usbh_urb_wait(pudev, puhost, puhost->control.pipe_in_num, DATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_STATUS_OUT;
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_STATUS_OUT;
puhost->control.timer = usb_curframe_get(pudev);
}
puhost->control.timer = usb_curframe_get(pudev);
}
}
/*!
@@ -269,24 +256,20 @@ static void usbh_data_in_transc (usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval none
*/
static void usbh_data_out_transc (usb_core_driver *pudev, usbh_host *puhost)
{
usb_urb_state urb_status = URB_IDLE;
static void usbh_data_out_transc(usb_core_driver *pudev, usbh_host *puhost) {
usb_urb_state urb_status = URB_IDLE;
pudev->host.pipe[puhost->control.pipe_out_num].data_toggle_out = 1U;
pudev->host.pipe[puhost->control.pipe_out_num].data_toggle_out = 1U;
usbh_data_send (pudev,
puhost->control.buf,
puhost->control.pipe_out_num,
puhost->control.ctl_len);
usbh_data_send(pudev, puhost->control.buf, puhost->control.pipe_out_num, puhost->control.ctl_len);
urb_status = usbh_urb_wait (pudev, puhost, puhost->control.pipe_out_num, DATA_STAGE_TIMEOUT);
urb_status = usbh_urb_wait(pudev, puhost, puhost->control.pipe_out_num, DATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_STATUS_IN;
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_STATUS_IN;
puhost->control.timer = usb_curframe_get(pudev);
}
puhost->control.timer = usb_curframe_get(pudev);
}
}
/*!
@@ -296,19 +279,18 @@ static void usbh_data_out_transc (usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval none
*/
static void usbh_status_in_transc (usb_core_driver *pudev, usbh_host *puhost)
{
uint8_t pp_num = puhost->control.pipe_in_num;
static void usbh_status_in_transc(usb_core_driver *pudev, usbh_host *puhost) {
uint8_t pp_num = puhost->control.pipe_in_num;
usb_urb_state urb_status = URB_IDLE;
usb_urb_state urb_status = URB_IDLE;
usbh_data_recev (pudev, NULL, pp_num, 0U);
usbh_data_recev(pudev, NULL, pp_num, 0U);
urb_status = usbh_urb_wait (pudev, puhost, pp_num, NODATA_STAGE_TIMEOUT);
urb_status = usbh_urb_wait(pudev, puhost, pp_num, NODATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_FINISH;
}
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_FINISH;
}
}
/*!
@@ -318,21 +300,20 @@ static void usbh_status_in_transc (usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval none
*/
static void usbh_status_out_transc (usb_core_driver *pudev, usbh_host *puhost)
{
uint8_t pp_num = puhost->control.pipe_out_num;
static void usbh_status_out_transc(usb_core_driver *pudev, usbh_host *puhost) {
uint8_t pp_num = puhost->control.pipe_out_num;
usb_urb_state urb_status = URB_IDLE;
usb_urb_state urb_status = URB_IDLE;
pudev->host.pipe[pp_num].data_toggle_out ^= 1U;
pudev->host.pipe[pp_num].data_toggle_out ^= 1U;
usbh_data_send (pudev, NULL, pp_num, 0U);
usbh_data_send(pudev, NULL, pp_num, 0U);
urb_status = usbh_urb_wait (pudev, puhost, pp_num, NODATA_STAGE_TIMEOUT);
urb_status = usbh_urb_wait(pudev, puhost, pp_num, NODATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_FINISH;
}
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_FINISH;
}
}
/*!
@@ -342,50 +323,48 @@ static void usbh_status_out_transc (usb_core_driver *pudev, usbh_host *puhost)
\param[out] none
\retval operation status
*/
usbh_status usbh_ctl_handler (usb_core_driver *pudev, usbh_host *puhost)
{
usbh_status status = USBH_BUSY;
usbh_status usbh_ctl_handler(usb_core_driver *pudev, usbh_host *puhost) {
usbh_status status = USBH_BUSY;
switch (puhost->control.ctl_state) {
case CTL_SETUP:
usbh_setup_transc (pudev, puhost);
break;
switch (puhost->control.ctl_state) {
case CTL_SETUP:
usbh_setup_transc(pudev, puhost);
break;
case CTL_DATA_IN:
usbh_data_in_transc (pudev, puhost);
break;
case CTL_DATA_IN:
usbh_data_in_transc(pudev, puhost);
break;
case CTL_DATA_OUT:
usbh_data_out_transc (pudev, puhost);
break;
case CTL_DATA_OUT:
usbh_data_out_transc(pudev, puhost);
break;
case CTL_STATUS_IN:
usbh_status_in_transc (pudev, puhost);
break;
case CTL_STATUS_IN:
usbh_status_in_transc(pudev, puhost);
break;
case CTL_STATUS_OUT:
usbh_status_out_transc (pudev, puhost);
break;
case CTL_STATUS_OUT:
usbh_status_out_transc(pudev, puhost);
break;
case CTL_FINISH:
puhost->control.ctl_state = CTL_IDLE;
case CTL_FINISH:
puhost->control.ctl_state = CTL_IDLE;
status = USBH_OK;
break;
status = USBH_OK;
break;
case CTL_ERROR:
if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) {
/* do the transmission again, starting from SETUP packet */
puhost->control.ctl_state = CTL_SETUP;
} else {
status = USBH_FAIL;
}
break;
default:
break;
case CTL_ERROR:
if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) {
/* do the transmission again, starting from SETUP packet */
puhost->control.ctl_state = CTL_SETUP;
} else {
status = USBH_FAIL;
}
break;
return status;
default:
break;
}
return status;
}

View File

@@ -8,34 +8,34 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_bkp.h"
/* BKP register bits offset */
#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U)
#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U)
/*!
\brief reset BKP registers
@@ -43,11 +43,10 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void bkp_deinit(void)
{
/* reset BKP domain register*/
rcu_bkp_reset_enable();
rcu_bkp_reset_disable();
void bkp_deinit(void) {
/* reset BKP domain register*/
rcu_bkp_reset_enable();
rcu_bkp_reset_disable();
}
/*!
@@ -59,15 +58,14 @@ void bkp_deinit(void)
\param[out] none
\retval none
*/
void bkp_data_write(bkp_data_register_enum register_number, uint16_t data)
{
if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
BKP_DATA10_41(register_number - 1U) = data;
}else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
BKP_DATA0_9(register_number - 1U) = data;
}else{
/* illegal parameters */
}
void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) {
if ((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)) {
BKP_DATA10_41(register_number - 1U) = data;
} else if ((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)) {
BKP_DATA0_9(register_number - 1U) = data;
} else {
/* illegal parameters */
}
}
/*!
@@ -78,19 +76,18 @@ void bkp_data_write(bkp_data_register_enum register_number, uint16_t data)
\param[out] none
\retval data of BKP data register
*/
uint16_t bkp_data_read(bkp_data_register_enum register_number)
{
uint16_t data = 0U;
/* get the data from the BKP data register */
if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
data = BKP_DATA10_41(register_number - 1U);
}else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
data = BKP_DATA0_9(register_number - 1U);
}else{
/* illegal parameters */
}
return data;
uint16_t bkp_data_read(bkp_data_register_enum register_number) {
uint16_t data = 0U;
/* get the data from the BKP data register */
if ((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)) {
data = BKP_DATA10_41(register_number - 1U);
} else if ((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)) {
data = BKP_DATA0_9(register_number - 1U);
} else {
/* illegal parameters */
}
return data;
}
/*!
@@ -99,10 +96,7 @@ uint16_t bkp_data_read(bkp_data_register_enum register_number)
\param[out] none
\retval none
*/
void bkp_rtc_calibration_output_enable(void)
{
BKP_OCTL |= (uint16_t)BKP_OCTL_COEN;
}
void bkp_rtc_calibration_output_enable(void) { BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; }
/*!
\brief disable RTC clock calibration output
@@ -110,10 +104,7 @@ void bkp_rtc_calibration_output_enable(void)
\param[out] none
\retval none
*/
void bkp_rtc_calibration_output_disable(void)
{
BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN;
}
void bkp_rtc_calibration_output_disable(void) { BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; }
/*!
\brief enable RTC alarm or second signal output
@@ -121,10 +112,7 @@ void bkp_rtc_calibration_output_disable(void)
\param[out] none
\retval none
*/
void bkp_rtc_signal_output_enable(void)
{
BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN;
}
void bkp_rtc_signal_output_enable(void) { BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; }
/*!
\brief disable RTC alarm or second signal output
@@ -132,10 +120,7 @@ void bkp_rtc_signal_output_enable(void)
\param[out] none
\retval none
*/
void bkp_rtc_signal_output_disable(void)
{
BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN;
}
void bkp_rtc_signal_output_disable(void) { BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; }
/*!
\brief select RTC output
@@ -146,33 +131,31 @@ void bkp_rtc_signal_output_disable(void)
\param[out] none
\retval none
*/
void bkp_rtc_output_select(uint16_t outputsel)
{
uint16_t ctl = 0U;
/* configure BKP_OCTL_ROSEL with outputsel */
ctl = BKP_OCTL;
ctl &= (uint16_t)~BKP_OCTL_ROSEL;
ctl |= outputsel;
BKP_OCTL = ctl;
void bkp_rtc_output_select(uint16_t outputsel) {
uint16_t ctl = 0U;
/* configure BKP_OCTL_ROSEL with outputsel */
ctl = BKP_OCTL;
ctl &= (uint16_t)~BKP_OCTL_ROSEL;
ctl |= outputsel;
BKP_OCTL = ctl;
}
/*!
\brief set RTC clock calibration value
\brief set RTC clock calibration value
\param[in] value: RTC clock calibration value
\arg 0x00 - 0x7F
\param[out] none
\retval none
*/
void bkp_rtc_calibration_value_set(uint8_t value)
{
uint16_t ctl;
/* configure BKP_OCTL_RCCV with value */
ctl = BKP_OCTL;
ctl &= (uint16_t)~BKP_OCTL_RCCV;
ctl |= (uint16_t)OCTL_RCCV(value);
BKP_OCTL = ctl;
void bkp_rtc_calibration_value_set(uint8_t value) {
uint16_t ctl;
/* configure BKP_OCTL_RCCV with value */
ctl = BKP_OCTL;
ctl &= (uint16_t)~BKP_OCTL_RCCV;
ctl |= (uint16_t)OCTL_RCCV(value);
BKP_OCTL = ctl;
}
/*!
@@ -181,10 +164,7 @@ void bkp_rtc_calibration_value_set(uint8_t value)
\param[out] none
\retval none
*/
void bkp_tamper_detection_enable(void)
{
BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN;
}
void bkp_tamper_detection_enable(void) { BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN; }
/*!
\brief disable tamper detection
@@ -192,10 +172,7 @@ void bkp_tamper_detection_enable(void)
\param[out] none
\retval none
*/
void bkp_tamper_detection_disable(void)
{
BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN;
}
void bkp_tamper_detection_disable(void) { BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN; }
/*!
\brief set tamper pin active level
@@ -206,15 +183,14 @@ void bkp_tamper_detection_disable(void)
\param[out] none
\retval none
*/
void bkp_tamper_active_level_set(uint16_t level)
{
uint16_t ctl = 0U;
/* configure BKP_TPCTL_TPAL with level */
ctl = BKP_TPCTL;
ctl &= (uint16_t)~BKP_TPCTL_TPAL;
ctl |= level;
BKP_TPCTL = ctl;
void bkp_tamper_active_level_set(uint16_t level) {
uint16_t ctl = 0U;
/* configure BKP_TPCTL_TPAL with level */
ctl = BKP_TPCTL;
ctl &= (uint16_t)~BKP_TPCTL_TPAL;
ctl |= level;
BKP_TPCTL = ctl;
}
/*!
@@ -223,10 +199,7 @@ void bkp_tamper_active_level_set(uint16_t level)
\param[out] none
\retval none
*/
void bkp_interrupt_enable(void)
{
BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE;
}
void bkp_interrupt_enable(void) { BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE; }
/*!
\brief disable tamper interrupt
@@ -234,10 +207,7 @@ void bkp_interrupt_enable(void)
\param[out] none
\retval none
*/
void bkp_interrupt_disable(void)
{
BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE;
}
void bkp_interrupt_disable(void) { BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE; }
/*!
\brief get tamper flag state
@@ -245,13 +215,12 @@ void bkp_interrupt_disable(void)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus bkp_flag_get(void)
{
if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){
return SET;
}else{
return RESET;
}
FlagStatus bkp_flag_get(void) {
if (RESET != (BKP_TPCS & BKP_FLAG_TAMPER)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -260,10 +229,7 @@ FlagStatus bkp_flag_get(void)
\param[out] none
\retval none
*/
void bkp_flag_clear(void)
{
BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
}
void bkp_flag_clear(void) { BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); }
/*!
\brief get tamper interrupt flag state
@@ -271,13 +237,12 @@ void bkp_flag_clear(void)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus bkp_interrupt_flag_get(void)
{
if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){
return SET;
}else{
return RESET;
}
FlagStatus bkp_interrupt_flag_get(void) {
if (RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -286,7 +251,4 @@ FlagStatus bkp_interrupt_flag_get(void)
\param[out] none
\retval none
*/
void bkp_interrupt_flag_clear(void)
{
BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
}
void bkp_interrupt_flag_clear(void) { BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); }

View File

@@ -34,8 +34,8 @@ OF SUCH DAMAGE.
#include "gd32vf103_crc.h"
#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U)
#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U)
/*!
\brief deinit CRC calculation unit
@@ -43,11 +43,10 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void crc_deinit(void)
{
CRC_DATA = CRC_DATA_RESET_VALUE;
CRC_FDATA = CRC_FDATA_RESET_VALUE;
CRC_CTL = (uint32_t)CRC_CTL_RST;
void crc_deinit(void) {
CRC_DATA = CRC_DATA_RESET_VALUE;
CRC_FDATA = CRC_FDATA_RESET_VALUE;
CRC_CTL = (uint32_t)CRC_CTL_RST;
}
/*!
@@ -56,10 +55,7 @@ void crc_deinit(void)
\param[out] none
\retval none
*/
void crc_data_register_reset(void)
{
CRC_CTL |= (uint32_t)CRC_CTL_RST;
}
void crc_data_register_reset(void) { CRC_CTL |= (uint32_t)CRC_CTL_RST; }
/*!
\brief read the value of the data register
@@ -67,11 +63,10 @@ void crc_data_register_reset(void)
\param[out] none
\retval 32-bit value of the data register
*/
uint32_t crc_data_register_read(void)
{
uint32_t data;
data = CRC_DATA;
return (data);
uint32_t crc_data_register_read(void) {
uint32_t data;
data = CRC_DATA;
return (data);
}
/*!
@@ -80,11 +75,10 @@ uint32_t crc_data_register_read(void)
\param[out] none
\retval 8-bit value of the free data register
*/
uint8_t crc_free_data_register_read(void)
{
uint8_t fdata;
fdata = (uint8_t)CRC_FDATA;
return (fdata);
uint8_t crc_free_data_register_read(void) {
uint8_t fdata;
fdata = (uint8_t)CRC_FDATA;
return (fdata);
}
/*!
@@ -93,10 +87,7 @@ uint8_t crc_free_data_register_read(void)
\param[out] none
\retval none
*/
void crc_free_data_register_write(uint8_t free_data)
{
CRC_FDATA = (uint32_t)free_data;
}
void crc_free_data_register_write(uint8_t free_data) { CRC_FDATA = (uint32_t)free_data; }
/*!
\brief calculate the CRC value of a 32-bit data
@@ -104,10 +95,9 @@ void crc_free_data_register_write(uint8_t free_data)
\param[out] none
\retval 32-bit value calculated by CRC
*/
uint32_t crc_single_data_calculate(uint32_t sdata)
{
CRC_DATA = sdata;
return (CRC_DATA);
uint32_t crc_single_data_calculate(uint32_t sdata) {
CRC_DATA = sdata;
return (CRC_DATA);
}
/*!
@@ -117,11 +107,10 @@ uint32_t crc_single_data_calculate(uint32_t sdata)
\param[out] none
\retval 32-bit value calculated by CRC
*/
uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size)
{
uint32_t index;
for(index = 0U; index < size; index++){
CRC_DATA = array[index];
}
return (CRC_DATA);
uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) {
uint32_t index;
for (index = 0U; index < size; index++) {
CRC_DATA = array[index];
}
return (CRC_DATA);
}

View File

@@ -8,36 +8,36 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_dac.h"
/* DAC register bit offset */
#define DAC1_REG_OFFSET ((uint32_t)16U)
#define DH_12BIT_OFFSET ((uint32_t)16U)
#define DH_8BIT_OFFSET ((uint32_t)8U)
#define DAC1_REG_OFFSET ((uint32_t)16U)
#define DH_12BIT_OFFSET ((uint32_t)16U)
#define DH_8BIT_OFFSET ((uint32_t)8U)
/*!
\brief deinitialize DAC
@@ -45,10 +45,9 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void dac_deinit(void)
{
rcu_periph_reset_enable(RCU_DACRST);
rcu_periph_reset_disable(RCU_DACRST);
void dac_deinit(void) {
rcu_periph_reset_enable(RCU_DACRST);
rcu_periph_reset_disable(RCU_DACRST);
}
/*!
@@ -57,14 +56,13 @@ void dac_deinit(void)
\param[out] none
\retval none
*/
void dac_enable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL |= DAC_CTL_DEN0;
}else{
DAC_CTL |= DAC_CTL_DEN1;
}
}
void dac_enable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL |= DAC_CTL_DEN0;
} else {
DAC_CTL |= DAC_CTL_DEN1;
}
}
/*!
\brief disable DAC
@@ -72,13 +70,12 @@ void dac_enable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_disable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL &= ~DAC_CTL_DEN0;
}else{
DAC_CTL &= ~DAC_CTL_DEN1;
}
void dac_disable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL &= ~DAC_CTL_DEN0;
} else {
DAC_CTL &= ~DAC_CTL_DEN1;
}
}
/*!
@@ -87,13 +84,12 @@ void dac_disable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_dma_enable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL |= DAC_CTL_DDMAEN0;
}else{
DAC_CTL |= DAC_CTL_DDMAEN1;
}
void dac_dma_enable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL |= DAC_CTL_DDMAEN0;
} else {
DAC_CTL |= DAC_CTL_DDMAEN1;
}
}
/*!
@@ -102,13 +98,12 @@ void dac_dma_enable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_dma_disable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL &= ~DAC_CTL_DDMAEN0;
}else{
DAC_CTL &= ~DAC_CTL_DDMAEN1;
}
void dac_dma_disable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL &= ~DAC_CTL_DDMAEN0;
} else {
DAC_CTL &= ~DAC_CTL_DDMAEN1;
}
}
/*!
@@ -117,13 +112,12 @@ void dac_dma_disable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_output_buffer_enable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL &= ~DAC_CTL_DBOFF0;
}else{
DAC_CTL &= ~DAC_CTL_DBOFF1;
}
void dac_output_buffer_enable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL &= ~DAC_CTL_DBOFF0;
} else {
DAC_CTL &= ~DAC_CTL_DBOFF1;
}
}
/*!
@@ -132,13 +126,12 @@ void dac_output_buffer_enable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_output_buffer_disable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL |= DAC_CTL_DBOFF0;
}else{
DAC_CTL |= DAC_CTL_DBOFF1;
}
void dac_output_buffer_disable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL |= DAC_CTL_DBOFF0;
} else {
DAC_CTL |= DAC_CTL_DBOFF1;
}
}
/*!
@@ -147,17 +140,16 @@ void dac_output_buffer_disable(uint32_t dac_periph)
\param[out] none
\retval DAC output data
*/
uint16_t dac_output_value_get(uint32_t dac_periph)
{
uint16_t data = 0U;
if(DAC0 == dac_periph){
/* store the DAC0 output value */
data = (uint16_t)DAC0_DO;
}else{
/* store the DAC1 output value */
data = (uint16_t)DAC1_DO;
}
return data;
uint16_t dac_output_value_get(uint32_t dac_periph) {
uint16_t data = 0U;
if (DAC0 == dac_periph) {
/* store the DAC0 output value */
data = (uint16_t)DAC0_DO;
} else {
/* store the DAC1 output value */
data = (uint16_t)DAC1_DO;
}
return data;
}
/*!
@@ -172,43 +164,42 @@ uint16_t dac_output_value_get(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data)
{
if(DAC0 == dac_periph){
switch(dac_align){
/* data right 12 bit alignment */
case DAC_ALIGN_12B_R:
DAC0_R12DH = data;
break;
/* data left 12 bit alignment */
case DAC_ALIGN_12B_L:
DAC0_L12DH = data;
break;
/* data right 8 bit alignment */
case DAC_ALIGN_8B_R:
DAC0_R8DH = data;
break;
default:
break;
}
}else{
switch(dac_align){
/* data right 12 bit alignment */
case DAC_ALIGN_12B_R:
DAC1_R12DH = data;
break;
/* data left 12 bit alignment */
case DAC_ALIGN_12B_L:
DAC1_L12DH = data;
break;
/* data right 8 bit alignment */
case DAC_ALIGN_8B_R:
DAC1_R8DH = data;
break;
default:
break;
}
void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) {
if (DAC0 == dac_periph) {
switch (dac_align) {
/* data right 12 bit alignment */
case DAC_ALIGN_12B_R:
DAC0_R12DH = data;
break;
/* data left 12 bit alignment */
case DAC_ALIGN_12B_L:
DAC0_L12DH = data;
break;
/* data right 8 bit alignment */
case DAC_ALIGN_8B_R:
DAC0_R8DH = data;
break;
default:
break;
}
} else {
switch (dac_align) {
/* data right 12 bit alignment */
case DAC_ALIGN_12B_R:
DAC1_R12DH = data;
break;
/* data left 12 bit alignment */
case DAC_ALIGN_12B_L:
DAC1_L12DH = data;
break;
/* data right 8 bit alignment */
case DAC_ALIGN_8B_R:
DAC1_R8DH = data;
break;
default:
break;
}
}
}
/*!
@@ -217,13 +208,12 @@ void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data)
\param[out] none
\retval none
*/
void dac_trigger_enable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL |= DAC_CTL_DTEN0;
}else{
DAC_CTL |= DAC_CTL_DTEN1;
}
void dac_trigger_enable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL |= DAC_CTL_DTEN0;
} else {
DAC_CTL |= DAC_CTL_DTEN1;
}
}
/*!
@@ -232,13 +222,12 @@ void dac_trigger_enable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_trigger_disable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_CTL &= ~DAC_CTL_DTEN0;
}else{
DAC_CTL &= ~DAC_CTL_DTEN1;
}
void dac_trigger_disable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_CTL &= ~DAC_CTL_DTEN0;
} else {
DAC_CTL &= ~DAC_CTL_DTEN1;
}
}
/*!
@@ -257,17 +246,16 @@ void dac_trigger_disable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)
{
if(DAC0 == dac_periph){
/* configure DAC0 trigger source */
DAC_CTL &= ~DAC_CTL_DTSEL0;
DAC_CTL |= triggersource;
}else{
/* configure DAC1 trigger source */
DAC_CTL &= ~DAC_CTL_DTSEL1;
DAC_CTL |= (triggersource << DAC1_REG_OFFSET);
}
void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource) {
if (DAC0 == dac_periph) {
/* configure DAC0 trigger source */
DAC_CTL &= ~DAC_CTL_DTSEL0;
DAC_CTL |= triggersource;
} else {
/* configure DAC1 trigger source */
DAC_CTL &= ~DAC_CTL_DTSEL1;
DAC_CTL |= (triggersource << DAC1_REG_OFFSET);
}
}
/*!
@@ -275,13 +263,12 @@ void dac_trigger_source_config(uint32_t dac_periph,uint32_t triggersource)
\param[in] dac_periph: DACx(x = 0,1)
\retval none
*/
void dac_software_trigger_enable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_SWT |= DAC_SWT_SWTR0;
}else{
DAC_SWT |= DAC_SWT_SWTR1;
}
void dac_software_trigger_enable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_SWT |= DAC_SWT_SWTR0;
} else {
DAC_SWT |= DAC_SWT_SWTR1;
}
}
/*!
@@ -290,13 +277,12 @@ void dac_software_trigger_enable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_software_trigger_disable(uint32_t dac_periph)
{
if(DAC0 == dac_periph){
DAC_SWT &= ~DAC_SWT_SWTR0;
}else{
DAC_SWT &= ~DAC_SWT_SWTR1;
}
void dac_software_trigger_disable(uint32_t dac_periph) {
if (DAC0 == dac_periph) {
DAC_SWT &= ~DAC_SWT_SWTR0;
} else {
DAC_SWT &= ~DAC_SWT_SWTR1;
}
}
/*!
@@ -310,17 +296,16 @@ void dac_software_trigger_disable(uint32_t dac_periph)
\param[out] none
\retval none
*/
void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode)
{
if(DAC0 == dac_periph){
/* configure DAC0 wave mode */
DAC_CTL &= ~DAC_CTL_DWM0;
DAC_CTL |= wave_mode;
}else{
/* configure DAC1 wave mode */
DAC_CTL &= ~DAC_CTL_DWM1;
DAC_CTL |= (wave_mode << DAC1_REG_OFFSET);
}
void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) {
if (DAC0 == dac_periph) {
/* configure DAC0 wave mode */
DAC_CTL &= ~DAC_CTL_DWM0;
DAC_CTL |= wave_mode;
} else {
/* configure DAC1 wave mode */
DAC_CTL &= ~DAC_CTL_DWM1;
DAC_CTL |= (wave_mode << DAC1_REG_OFFSET);
}
}
/*!
@@ -343,17 +328,16 @@ void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode)
\param[out] none
\retval none
*/
void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width)
{
if(DAC0 == dac_periph){
/* configure DAC0 wave bit width */
DAC_CTL &= ~DAC_CTL_DWBW0;
DAC_CTL |= bit_width;
}else{
/* configure DAC1 wave bit width */
DAC_CTL &= ~DAC_CTL_DWBW1;
DAC_CTL |= (bit_width << DAC1_REG_OFFSET);
}
void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) {
if (DAC0 == dac_periph) {
/* configure DAC0 wave bit width */
DAC_CTL &= ~DAC_CTL_DWBW0;
DAC_CTL |= bit_width;
} else {
/* configure DAC1 wave bit width */
DAC_CTL &= ~DAC_CTL_DWBW1;
DAC_CTL |= (bit_width << DAC1_REG_OFFSET);
}
}
/*!
@@ -376,17 +360,16 @@ void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width)
\param[out] none
\retval none
*/
void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits)
{
if(DAC0 == dac_periph){
/* configure DAC0 LFSR noise mode */
DAC_CTL &= ~DAC_CTL_DWBW0;
DAC_CTL |= unmask_bits;
}else{
/* configure DAC1 LFSR noise mode */
DAC_CTL &= ~DAC_CTL_DWBW1;
DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET);
}
void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) {
if (DAC0 == dac_periph) {
/* configure DAC0 LFSR noise mode */
DAC_CTL &= ~DAC_CTL_DWBW0;
DAC_CTL |= unmask_bits;
} else {
/* configure DAC1 LFSR noise mode */
DAC_CTL &= ~DAC_CTL_DWBW1;
DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET);
}
}
/*!
@@ -409,17 +392,16 @@ void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits)
\param[out] none
\retval none
*/
void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude)
{
if(DAC0 == dac_periph){
/* configure DAC0 triangle noise mode */
DAC_CTL &= ~DAC_CTL_DWBW0;
DAC_CTL |= amplitude;
}else{
/* configure DAC1 triangle noise mode */
DAC_CTL &= ~DAC_CTL_DWBW1;
DAC_CTL |= (amplitude << DAC1_REG_OFFSET);
}
void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) {
if (DAC0 == dac_periph) {
/* configure DAC0 triangle noise mode */
DAC_CTL &= ~DAC_CTL_DWBW0;
DAC_CTL |= amplitude;
} else {
/* configure DAC1 triangle noise mode */
DAC_CTL &= ~DAC_CTL_DWBW1;
DAC_CTL |= (amplitude << DAC1_REG_OFFSET);
}
}
/*!
@@ -428,11 +410,10 @@ void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude)
\param[out] none
\retval none
*/
void dac_concurrent_enable(void)
{
uint32_t ctl = 0U;
ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
DAC_CTL |= (ctl);
void dac_concurrent_enable(void) {
uint32_t ctl = 0U;
ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
DAC_CTL |= (ctl);
}
/*!
@@ -441,11 +422,10 @@ void dac_concurrent_enable(void)
\param[out] none
\retval none
*/
void dac_concurrent_disable(void)
{
uint32_t ctl = 0U;
ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
DAC_CTL &= (~ctl);
void dac_concurrent_disable(void) {
uint32_t ctl = 0U;
ctl = DAC_CTL_DEN0 | DAC_CTL_DEN1;
DAC_CTL &= (~ctl);
}
/*!
@@ -454,11 +434,10 @@ void dac_concurrent_disable(void)
\param[out] none
\retval none
*/
void dac_concurrent_software_trigger_enable(void)
{
uint32_t swt = 0U;
swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
DAC_SWT |= (swt);
void dac_concurrent_software_trigger_enable(void) {
uint32_t swt = 0U;
swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
DAC_SWT |= (swt);
}
/*!
@@ -467,11 +446,10 @@ void dac_concurrent_software_trigger_enable(void)
\param[out] none
\retval none
*/
void dac_concurrent_software_trigger_disable(void)
{
uint32_t swt = 0U;
swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
DAC_SWT &= (~swt);
void dac_concurrent_software_trigger_disable(void) {
uint32_t swt = 0U;
swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1;
DAC_SWT &= (~swt);
}
/*!
@@ -480,11 +458,10 @@ void dac_concurrent_software_trigger_disable(void)
\param[out] none
\retval none
*/
void dac_concurrent_output_buffer_enable(void)
{
uint32_t ctl = 0U;
ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
DAC_CTL &= (~ctl);
void dac_concurrent_output_buffer_enable(void) {
uint32_t ctl = 0U;
ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
DAC_CTL &= (~ctl);
}
/*!
@@ -493,11 +470,10 @@ void dac_concurrent_output_buffer_enable(void)
\param[out] none
\retval none
*/
void dac_concurrent_output_buffer_disable(void)
{
uint32_t ctl = 0U;
ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
DAC_CTL |= (ctl);
void dac_concurrent_output_buffer_disable(void) {
uint32_t ctl = 0U;
ctl = DAC_CTL_DBOFF0 | DAC_CTL_DBOFF1;
DAC_CTL |= (ctl);
}
/*!
@@ -512,26 +488,25 @@ void dac_concurrent_output_buffer_disable(void)
\param[out] none
\retval none
*/
void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1)
{
uint32_t data = 0U;
switch(dac_align){
/* data right 12b alignment */
case DAC_ALIGN_12B_R:
data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
DACC_R12DH = data;
break;
/* data left 12b alignment */
case DAC_ALIGN_12B_L:
data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
DACC_L12DH = data;
break;
/* data right 8b alignment */
case DAC_ALIGN_8B_R:
data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0;
DACC_R8DH = data;
break;
default:
break;
}
void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) {
uint32_t data = 0U;
switch (dac_align) {
/* data right 12b alignment */
case DAC_ALIGN_12B_R:
data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
DACC_R12DH = data;
break;
/* data left 12b alignment */
case DAC_ALIGN_12B_L:
data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0;
DACC_L12DH = data;
break;
/* data right 8b alignment */
case DAC_ALIGN_8B_R:
data = ((uint32_t)data1 << DH_8BIT_OFFSET) | data0;
DACC_R8DH = data;
break;
default:
break;
}
}

View File

@@ -8,27 +8,27 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
@@ -40,10 +40,7 @@ OF SUCH DAMAGE.
\param[out] none
\retval DBG_ID code
*/
uint32_t dbg_id_get(void)
{
return DBG_ID;
}
uint32_t dbg_id_get(void) { return DBG_ID; }
/*!
\brief enable low power behavior when the mcu is in debug mode
@@ -55,10 +52,7 @@ uint32_t dbg_id_get(void)
\param[out] none
\retval none
*/
void dbg_low_power_enable(uint32_t dbg_low_power)
{
DBG_CTL |= dbg_low_power;
}
void dbg_low_power_enable(uint32_t dbg_low_power) { DBG_CTL |= dbg_low_power; }
/*!
\brief disable low power behavior when the mcu is in debug mode
@@ -70,10 +64,7 @@ void dbg_low_power_enable(uint32_t dbg_low_power)
\param[out] none
\retval none
*/
void dbg_low_power_disable(uint32_t dbg_low_power)
{
DBG_CTL &= ~dbg_low_power;
}
void dbg_low_power_disable(uint32_t dbg_low_power) { DBG_CTL &= ~dbg_low_power; }
/*!
\brief enable peripheral behavior when the mcu is in debug mode
@@ -87,10 +78,7 @@ void dbg_low_power_disable(uint32_t dbg_low_power)
\param[out] none
\retval none
*/
void dbg_periph_enable(dbg_periph_enum dbg_periph)
{
DBG_CTL |= (uint32_t)dbg_periph;
}
void dbg_periph_enable(dbg_periph_enum dbg_periph) { DBG_CTL |= (uint32_t)dbg_periph; }
/*!
\brief disable peripheral behavior when the mcu is in debug mode
@@ -104,7 +92,4 @@ void dbg_periph_enable(dbg_periph_enum dbg_periph)
\param[out] none
\retval none
*/
void dbg_periph_disable(dbg_periph_enum dbg_periph)
{
DBG_CTL &= ~(uint32_t)dbg_periph;
}
void dbg_periph_disable(dbg_periph_enum dbg_periph) { DBG_CTL &= ~(uint32_t)dbg_periph; }

View File

@@ -8,33 +8,34 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_dma.h"
#define DMA_WRONG_HANDLE while(1){}
#define DMA_WRONG_HANDLE \
while (1) {}
/* check whether peripheral matches channels or not */
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
@@ -49,20 +50,19 @@ static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_e
\param[out] none
\retval none
*/
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
/* disable DMA a channel */
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
/* reset DMA channel registers */
DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
/* disable DMA a channel */
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
/* reset DMA channel registers */
DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
}
/*!
@@ -71,18 +71,17 @@ void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_struct_para_init(dma_parameter_struct* init_struct)
{
/* set the DMA struct with the default values */
init_struct->periph_addr = 0U;
init_struct->periph_width = 0U;
init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
init_struct->memory_addr = 0U;
init_struct->memory_width = 0U;
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
init_struct->number = 0U;
init_struct->direction = DMA_PERIPHERAL_TO_MEMORY;
init_struct->priority = DMA_PRIORITY_LOW;
void dma_struct_para_init(dma_parameter_struct *init_struct) {
/* set the DMA struct with the default values */
init_struct->periph_addr = 0U;
init_struct->periph_width = 0U;
init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
init_struct->memory_addr = 0U;
init_struct->memory_width = 0U;
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
init_struct->number = 0U;
init_struct->direction = DMA_PERIPHERAL_TO_MEMORY;
init_struct->priority = DMA_PRIORITY_LOW;
}
/*!
@@ -105,49 +104,48 @@ void dma_struct_para_init(dma_parameter_struct* init_struct)
\param[out] none
\retval none
*/
void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct)
{
uint32_t ctl;
void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct) {
uint32_t ctl;
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
/* configure peripheral base address */
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
/* configure peripheral base address */
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
/* configure memory base address */
DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
/* configure memory base address */
DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
/* configure the number of remaining data to be transferred */
DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
/* configure the number of remaining data to be transferred */
DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
/* configure peripheral transfer width,memory transfer width and priority */
ctl = DMA_CHCTL(dma_periph, channelx);
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
DMA_CHCTL(dma_periph, channelx) = ctl;
/* configure peripheral transfer width,memory transfer width and priority */
ctl = DMA_CHCTL(dma_periph, channelx);
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
DMA_CHCTL(dma_periph, channelx) = ctl;
/* configure peripheral increasing mode */
if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
}else{
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
}
/* configure peripheral increasing mode */
if (DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
}
/* configure memory increasing mode */
if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
}else{
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
}
/* configure memory increasing mode */
if (DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
} else {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
}
/* configure the direction of data transfer */
if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
}else{
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
}
/* configure the direction of data transfer */
if (DMA_PERIPHERAL_TO_MEMORY == init_struct->direction) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
}
}
/*!
@@ -160,13 +158,12 @@ void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_stru
\param[out] none
\retval none
*/
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
}
/*!
@@ -179,13 +176,12 @@ void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
}
/*!
@@ -198,13 +194,12 @@ void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
}
/*!
@@ -217,13 +212,12 @@ void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
}
/*!
@@ -236,13 +230,12 @@ void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx
\param[out] none
\retval none
*/
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
}
/*!
@@ -255,13 +248,12 @@ void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
}
/*!
@@ -275,13 +267,12 @@ void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHPADDR(dma_periph, channelx) = address;
DMA_CHPADDR(dma_periph, channelx) = address;
}
/*!
@@ -295,13 +286,12 @@ void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, u
\param[out] none
\retval none
*/
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHMADDR(dma_periph, channelx) = address;
DMA_CHMADDR(dma_periph, channelx) = address;
}
/*!
@@ -315,13 +305,12 @@ void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, u
\param[out] none
\retval none
*/
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
}
/*!
@@ -334,13 +323,12 @@ void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx,
\param[out] none
\retval uint32_t: the number of remaining data to be transferred by the DMA
*/
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
return (uint32_t)DMA_CHCNT(dma_periph, channelx);
return (uint32_t)DMA_CHCNT(dma_periph, channelx);
}
/*!
@@ -359,20 +347,19 @@ uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
{
uint32_t ctl;
void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) {
uint32_t ctl;
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PRIO;
ctl |= priority;
DMA_CHCTL(dma_periph, channelx) = ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PRIO;
ctl |= priority;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
@@ -390,20 +377,19 @@ void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_
\param[out] none
\retval none
*/
void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth)
{
uint32_t ctl;
void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) {
uint32_t ctl;
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_MWIDTH;
ctl |= mwidth;
DMA_CHCTL(dma_periph, channelx) = ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_MWIDTH;
ctl |= mwidth;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
@@ -421,20 +407,19 @@ void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uin
\param[out] none
\retval none
*/
void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth)
{
uint32_t ctl;
void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) {
uint32_t ctl;
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PWIDTH;
ctl |= pwidth;
DMA_CHCTL(dma_periph, channelx) = ctl;
/* acquire DMA_CHxCTL register */
ctl = DMA_CHCTL(dma_periph, channelx);
/* assign regiser */
ctl &= ~DMA_CHXCTL_PWIDTH;
ctl |= pwidth;
DMA_CHCTL(dma_periph, channelx) = ctl;
}
/*!
@@ -447,13 +432,12 @@ void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, ui
\param[out] none
\retval none
*/
void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
}
/*!
@@ -466,13 +450,12 @@ void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
}
/*!
@@ -485,13 +468,12 @@ void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
}
/*!
@@ -504,13 +486,12 @@ void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
}
/*!
@@ -527,17 +508,16 @@ void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
\param[out] none
\retval none
*/
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
if(DMA_PERIPHERAL_TO_MEMORY == direction){
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
}
if (DMA_PERIPHERAL_TO_MEMORY == direction) {
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
} else {
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
}
}
/*!
@@ -556,17 +536,16 @@ void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channel
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
FlagStatus reval;
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) {
FlagStatus reval;
if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
reval = SET;
}else{
reval = RESET;
}
if (RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))) {
reval = SET;
} else {
reval = RESET;
}
return reval;
return reval;
}
/*!
@@ -585,10 +564,7 @@ FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t
\param[out] none
\retval none
*/
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
}
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) { DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); }
/*!
\brief check DMA flag and interrupt enable bit is set or not
@@ -605,36 +581,35 @@ void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t fla
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) {
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
switch(flag){
case DMA_INT_FLAG_FTF:
/* check whether the full transfer finish interrupt flag is set and enabled */
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
break;
case DMA_INT_FLAG_HTF:
/* check whether the half transfer finish interrupt flag is set and enabled */
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
break;
case DMA_INT_FLAG_ERR:
/* check whether the error interrupt flag is set and enabled */
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
break;
default:
DMA_WRONG_HANDLE
}
switch (flag) {
case DMA_INT_FLAG_FTF:
/* check whether the full transfer finish interrupt flag is set and enabled */
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
break;
case DMA_INT_FLAG_HTF:
/* check whether the half transfer finish interrupt flag is set and enabled */
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
break;
case DMA_INT_FLAG_ERR:
/* check whether the error interrupt flag is set and enabled */
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
break;
default:
DMA_WRONG_HANDLE
}
/* when the interrupt flag is set and enabled, return SET */
if(interrupt_flag && interrupt_enable){
return SET;
}else{
return RESET;
}
/* when the interrupt flag is set and enabled, return SET */
if (interrupt_flag && interrupt_enable) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -653,10 +628,7 @@ FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx
\param[out] none
\retval none
*/
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
{
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
}
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) { DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); }
/*!
\brief enable DMA interrupt
@@ -673,13 +645,12 @@ void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, ui
\param[out] none
\retval none
*/
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) |= source;
DMA_CHCTL(dma_periph, channelx) |= source;
}
/*!
@@ -697,13 +668,12 @@ void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32
\param[out] none
\retval none
*/
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
{
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
DMA_WRONG_HANDLE
}
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) {
if (ERROR == dma_periph_and_channel_check(dma_periph, channelx)) {
DMA_WRONG_HANDLE
}
DMA_CHCTL(dma_periph, channelx) &= ~source;
DMA_CHCTL(dma_periph, channelx) &= ~source;
}
/*!
@@ -716,16 +686,15 @@ void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint3
\param[out] none
\retval none
*/
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
{
ErrStatus val = SUCCESS;
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx) {
ErrStatus val = SUCCESS;
if(DMA1 == dma_periph){
/* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
if(channelx > DMA_CH4){
val = ERROR;
}
if (DMA1 == dma_periph) {
/* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
if (channelx > DMA_CH4) {
val = ERROR;
}
}
return val;
return val;
}

View File

@@ -34,10 +34,9 @@ OF SUCH DAMAGE.
#include "gd32vf103_eclic.h"
#include "riscv_encoding.h"
#define REG_DBGMCU2 ((uint32_t)0xE0042008)
#define REG_DBGMCU2 ((uint32_t)0xE0042008)
#define REG_DBGMCU2EN ((uint32_t)0xE004200C)
/*!
\brief set the priority group
\param[in] prigroup: specify the priority group
@@ -49,10 +48,7 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void eclic_priority_group_set(uint32_t prigroup) {
ECLIC_SetCfgNlbits(prigroup);
}
void eclic_priority_group_set(uint32_t prigroup) { ECLIC_SetCfgNlbits(prigroup); }
/*!
\brief enable the interrupt request
@@ -63,9 +59,9 @@ void eclic_priority_group_set(uint32_t prigroup) {
\retval none
*/
void eclic_irq_enable(uint32_t source, uint8_t level, uint8_t priority) {
ECLIC_EnableIRQ(source);
ECLIC_SetLevelIRQ(source, level);
ECLIC_SetPriorityIRQ(source, priority);
ECLIC_EnableIRQ(source);
ECLIC_SetLevelIRQ(source, level);
ECLIC_SetPriorityIRQ(source, priority);
}
/*!
@@ -74,9 +70,7 @@ void eclic_irq_enable(uint32_t source, uint8_t level, uint8_t priority) {
\param[out] none
\retval none
*/
void eclic_irq_disable(uint32_t source) {
ECLIC_DisableIRQ(source);
}
void eclic_irq_disable(uint32_t source) { ECLIC_DisableIRQ(source); }
/*!
\brief reset system
@@ -86,6 +80,5 @@ void eclic_irq_disable(uint32_t source) {
*/
void eclic_system_reset(void) {
REG32(REG_DBGMCU2EN) = 0x4b5a6978;
REG32(REG_DBGMCU2) = 0x1;
REG32(REG_DBGMCU2) = 0x1;
}

View File

@@ -35,18 +35,18 @@ OF SUCH DAMAGE.
#include "gd32vf103_exmc.h"
/* EXMC bank0 register reset value */
#define BANK0_SNCTL0_REGION_RESET ((uint32_t)0x000030DAU)
#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU)
#define BANK0_SNCTL0_REGION_RESET ((uint32_t)0x000030DAU)
#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU)
/* EXMC register bit offset */
#define SNCTL_NRMUX_OFFSET ((uint32_t)1U)
#define SNCTL_WREN_OFFSET ((uint32_t)12U)
#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U)
#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U)
#define SNCTL_NRMUX_OFFSET ((uint32_t)1U)
#define SNCTL_WREN_OFFSET ((uint32_t)12U)
#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U)
#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U)
#define SNTCFG_AHLD_OFFSET ((uint32_t)4U)
#define SNTCFG_DSET_OFFSET ((uint32_t)8U)
#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U)
#define SNTCFG_AHLD_OFFSET ((uint32_t)4U)
#define SNTCFG_DSET_OFFSET ((uint32_t)8U)
#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U)
/*!
\brief deinitialize EXMC NOR/SRAM region
@@ -55,14 +55,13 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void exmc_norsram_deinit(uint32_t norsram_region)
{
/* reset the registers */
if(EXMC_BANK0_NORSRAM_REGION0 == norsram_region){
EXMC_SNCTL(norsram_region) = BANK0_SNCTL0_REGION_RESET;
}
void exmc_norsram_deinit(uint32_t norsram_region) {
/* reset the registers */
if (EXMC_BANK0_NORSRAM_REGION0 == norsram_region) {
EXMC_SNCTL(norsram_region) = BANK0_SNCTL0_REGION_RESET;
}
EXMC_SNTCFG(norsram_region) = BANK0_SNTCFG_RESET;
EXMC_SNTCFG(norsram_region) = BANK0_SNTCFG_RESET;
}
/*!
@@ -71,23 +70,22 @@ void exmc_norsram_deinit(uint32_t norsram_region)
\param[out] exmc_norsram_init_struct: the initialized structure exmc_norsram_parameter_struct pointer
\retval none
*/
void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
{
/* configure the structure with default value */
exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0;
exmc_norsram_init_struct->address_data_mux = ENABLE;
exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM;
exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
exmc_norsram_init_struct->memory_write = ENABLE;
exmc_norsram_init_struct->nwait_signal = ENABLE;
exmc_norsram_init_struct->asyn_wait = DISABLE;
void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct *exmc_norsram_init_struct) {
/* configure the structure with default value */
exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0;
exmc_norsram_init_struct->address_data_mux = ENABLE;
exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM;
exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
exmc_norsram_init_struct->memory_write = ENABLE;
exmc_norsram_init_struct->nwait_signal = ENABLE;
exmc_norsram_init_struct->asyn_wait = DISABLE;
/* read/write timing configure */
exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
/* read/write timing configure */
exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
}
/*!
@@ -105,38 +103,32 @@ void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_i
\param[out] none
\retval none
*/
void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
{
uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U;
void exmc_norsram_init(exmc_norsram_parameter_struct *exmc_norsram_init_struct) {
uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U;
/* get the register value */
snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region);
/* get the register value */
snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region);
/* clear relative bits */
snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_NRWTPOL |
EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_NRMUX));
/* clear relative bits */
snctl &= ((uint32_t) ~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_NRMUX));
snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
exmc_norsram_init_struct->memory_type |
exmc_norsram_init_struct->databus_width |
exmc_norsram_init_struct->nwait_polarity |
(exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
(exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
(exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET);
snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | exmc_norsram_init_struct->memory_type | exmc_norsram_init_struct->databus_width
| exmc_norsram_init_struct->nwait_polarity | (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET)
| (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET);
sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
(((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
(((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
(((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT );
sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U) & EXMC_SNTCFG_ASET)
| (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET) & EXMC_SNTCFG_AHLD)
| (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNTCFG_DSET)
| (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U) << SNTCFG_BUSLAT_OFFSET) & EXMC_SNTCFG_BUSLAT);
/* nor flash access enable */
if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
snctl |= (uint32_t)EXMC_SNCTL_NREN;
}
/* nor flash access enable */
if (EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type) {
snctl |= (uint32_t)EXMC_SNCTL_NREN;
}
/* configure the registers */
EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl;
EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg;
/* configure the registers */
EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl;
EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg;
}
/*!
@@ -146,10 +138,7 @@ void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
\param[out] none
\retval none
*/
void exmc_norsram_enable(uint32_t norsram_region)
{
EXMC_SNCTL(norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN;
}
void exmc_norsram_enable(uint32_t norsram_region) { EXMC_SNCTL(norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN; }
/*!
\brief disable EXMC NOR/PSRAM bank region
@@ -158,7 +147,4 @@ void exmc_norsram_enable(uint32_t norsram_region)
\param[out] none
\retval none
*/
void exmc_norsram_disable(uint32_t norsram_region)
{
EXMC_SNCTL(norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
}
void exmc_norsram_disable(uint32_t norsram_region) { EXMC_SNCTL(norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN; }

View File

@@ -34,7 +34,7 @@ OF SUCH DAMAGE.
#include "gd32vf103_exti.h"
#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U)
#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U)
/*!
\brief deinitialize the EXTI
@@ -42,14 +42,13 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void exti_deinit(void)
{
/* reset the value of all the EXTI registers */
EXTI_INTEN = EXTI_REG_RESET_VALUE;
EXTI_EVEN = EXTI_REG_RESET_VALUE;
EXTI_RTEN = EXTI_REG_RESET_VALUE;
EXTI_FTEN = EXTI_REG_RESET_VALUE;
EXTI_SWIEV = EXTI_REG_RESET_VALUE;
void exti_deinit(void) {
/* reset the value of all the EXTI registers */
EXTI_INTEN = EXTI_REG_RESET_VALUE;
EXTI_EVEN = EXTI_REG_RESET_VALUE;
EXTI_RTEN = EXTI_REG_RESET_VALUE;
EXTI_FTEN = EXTI_REG_RESET_VALUE;
EXTI_SWIEV = EXTI_REG_RESET_VALUE;
}
/*!
@@ -70,44 +69,43 @@ void exti_deinit(void)
\param[out] none
\retval none
*/
void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type)
{
/* reset the EXTI line x */
EXTI_INTEN &= ~(uint32_t) linex;
EXTI_EVEN &= ~(uint32_t) linex;
EXTI_RTEN &= ~(uint32_t) linex;
EXTI_FTEN &= ~(uint32_t) linex;
void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) {
/* reset the EXTI line x */
EXTI_INTEN &= ~(uint32_t)linex;
EXTI_EVEN &= ~(uint32_t)linex;
EXTI_RTEN &= ~(uint32_t)linex;
EXTI_FTEN &= ~(uint32_t)linex;
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
switch (mode) {
case EXTI_INTERRUPT:
EXTI_INTEN |= (uint32_t) linex;
break;
case EXTI_EVENT:
EXTI_EVEN |= (uint32_t) linex;
break;
default:
break;
}
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
switch (mode) {
case EXTI_INTERRUPT:
EXTI_INTEN |= (uint32_t)linex;
break;
case EXTI_EVENT:
EXTI_EVEN |= (uint32_t)linex;
break;
default:
break;
}
/* set the EXTI trigger type */
switch (trig_type) {
case EXTI_TRIG_RISING:
EXTI_RTEN |= (uint32_t) linex;
EXTI_FTEN &= ~(uint32_t) linex;
break;
case EXTI_TRIG_FALLING:
EXTI_RTEN &= ~(uint32_t) linex;
EXTI_FTEN |= (uint32_t) linex;
break;
case EXTI_TRIG_BOTH:
EXTI_RTEN |= (uint32_t) linex;
EXTI_FTEN |= (uint32_t) linex;
break;
case EXTI_TRIG_NONE:
default:
break;
}
/* set the EXTI trigger type */
switch (trig_type) {
case EXTI_TRIG_RISING:
EXTI_RTEN |= (uint32_t)linex;
EXTI_FTEN &= ~(uint32_t)linex;
break;
case EXTI_TRIG_FALLING:
EXTI_RTEN &= ~(uint32_t)linex;
EXTI_FTEN |= (uint32_t)linex;
break;
case EXTI_TRIG_BOTH:
EXTI_RTEN |= (uint32_t)linex;
EXTI_FTEN |= (uint32_t)linex;
break;
case EXTI_TRIG_NONE:
default:
break;
}
}
/*!
@@ -118,10 +116,7 @@ void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum tr
\param[out] none
\retval none
*/
void exti_interrupt_enable(exti_line_enum linex)
{
EXTI_INTEN |= (uint32_t) linex;
}
void exti_interrupt_enable(exti_line_enum linex) { EXTI_INTEN |= (uint32_t)linex; }
/*!
\brief enable the events from EXTI line x
@@ -131,10 +126,7 @@ void exti_interrupt_enable(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_event_enable(exti_line_enum linex)
{
EXTI_EVEN |= (uint32_t) linex;
}
void exti_event_enable(exti_line_enum linex) { EXTI_EVEN |= (uint32_t)linex; }
/*!
\brief disable the interrupt from EXTI line x
@@ -144,10 +136,7 @@ void exti_event_enable(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_interrupt_disable(exti_line_enum linex)
{
EXTI_INTEN &= ~(uint32_t) linex;
}
void exti_interrupt_disable(exti_line_enum linex) { EXTI_INTEN &= ~(uint32_t)linex; }
/*!
\brief disable the events from EXTI line x
@@ -157,10 +146,7 @@ void exti_interrupt_disable(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_event_disable(exti_line_enum linex)
{
EXTI_EVEN &= ~(uint32_t) linex;
}
void exti_event_disable(exti_line_enum linex) { EXTI_EVEN &= ~(uint32_t)linex; }
/*!
\brief get EXTI lines flag
@@ -170,13 +156,12 @@ void exti_event_disable(exti_line_enum linex)
\param[out] none
\retval FlagStatus: status of flag (RESET or SET)
*/
FlagStatus exti_flag_get(exti_line_enum linex)
{
if (RESET != (EXTI_PD & (uint32_t) linex)) {
return SET;
} else {
return RESET;
}
FlagStatus exti_flag_get(exti_line_enum linex) {
if (RESET != (EXTI_PD & (uint32_t)linex)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -187,10 +172,7 @@ FlagStatus exti_flag_get(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_flag_clear(exti_line_enum linex)
{
EXTI_PD = (uint32_t) linex;
}
void exti_flag_clear(exti_line_enum linex) { EXTI_PD = (uint32_t)linex; }
/*!
\brief get EXTI lines flag when the interrupt flag is set
@@ -200,18 +182,17 @@ void exti_flag_clear(exti_line_enum linex)
\param[out] none
\retval FlagStatus: status of flag (RESET or SET)
*/
FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
{
uint32_t flag_left, flag_right;
FlagStatus exti_interrupt_flag_get(exti_line_enum linex) {
uint32_t flag_left, flag_right;
flag_left = EXTI_PD & (uint32_t) linex;
flag_right = EXTI_INTEN & (uint32_t) linex;
flag_left = EXTI_PD & (uint32_t)linex;
flag_right = EXTI_INTEN & (uint32_t)linex;
if ((RESET != flag_left) && (RESET != flag_right)) {
return SET;
} else {
return RESET;
}
if ((RESET != flag_left) && (RESET != flag_right)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -222,10 +203,7 @@ FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_interrupt_flag_clear(exti_line_enum linex)
{
EXTI_PD = (uint32_t) linex;
}
void exti_interrupt_flag_clear(exti_line_enum linex) { EXTI_PD = (uint32_t)linex; }
/*!
\brief enable EXTI software interrupt event
@@ -235,10 +213,7 @@ void exti_interrupt_flag_clear(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_software_interrupt_enable(exti_line_enum linex)
{
EXTI_SWIEV |= (uint32_t) linex;
}
void exti_software_interrupt_enable(exti_line_enum linex) { EXTI_SWIEV |= (uint32_t)linex; }
/*!
\brief disable EXTI software interrupt event
@@ -248,7 +223,4 @@ void exti_software_interrupt_enable(exti_line_enum linex)
\param[out] none
\retval none
*/
void exti_software_interrupt_disable(exti_line_enum linex)
{
EXTI_SWIEV &= ~(uint32_t) linex;
}
void exti_software_interrupt_disable(exti_line_enum linex) { EXTI_SWIEV &= ~(uint32_t)linex; }

View File

@@ -43,14 +43,13 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void fmc_wscnt_set(uint32_t wscnt)
{
uint32_t reg;
void fmc_wscnt_set(uint32_t wscnt) {
uint32_t reg;
reg = FMC_WS;
/* set the wait state counter value */
reg &= ~FMC_WS_WSCNT;
FMC_WS = (reg | wscnt);
reg = FMC_WS;
/* set the wait state counter value */
reg &= ~FMC_WS_WSCNT;
FMC_WS = (reg | wscnt);
}
/*!
@@ -59,13 +58,12 @@ void fmc_wscnt_set(uint32_t wscnt)
\param[out] none
\retval none
*/
void fmc_unlock(void)
{
if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){
/* write the FMC unlock key */
FMC_KEY0 = UNLOCK_KEY0;
FMC_KEY0 = UNLOCK_KEY1;
}
void fmc_unlock(void) {
if ((RESET != (FMC_CTL0 & FMC_CTL0_LK))) {
/* write the FMC unlock key */
FMC_KEY0 = UNLOCK_KEY0;
FMC_KEY0 = UNLOCK_KEY1;
}
}
/*!
@@ -74,35 +72,32 @@ void fmc_unlock(void)
\param[out] none
\retval none
*/
void fmc_lock(void)
{
/* set the LK bit */
FMC_CTL0 |= FMC_CTL0_LK;
void fmc_lock(void) {
/* set the LK bit */
FMC_CTL0 |= FMC_CTL0_LK;
}
/*!
\brief FMC erase page
\param[in] page_address: the page address to be erased.
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum fmc_page_erase(uint32_t page_address)
{
fmc_state_enum fmc_state;
fmc_state_enum fmc_page_erase(uint32_t page_address) {
fmc_state_enum fmc_state;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* if the last operation is completed, start page erase */
if (FMC_READY == fmc_state) {
FMC_CTL0 |= FMC_CTL0_PER;
FMC_ADDR0 = page_address;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* if the last operation is completed, start page erase */
if (FMC_READY == fmc_state) {
FMC_CTL0 |= FMC_CTL0_PER;
FMC_ADDR0 = page_address;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PER bit */
FMC_CTL0 &= ~FMC_CTL0_PER;
}
/* return the FMC state */
return fmc_state;
/* reset the PER bit */
FMC_CTL0 &= ~FMC_CTL0_PER;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -111,22 +106,21 @@ fmc_state_enum fmc_page_erase(uint32_t page_address)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum fmc_mass_erase(void)
{
fmc_state_enum fmc_state;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum fmc_mass_erase(void) {
fmc_state_enum fmc_state;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* start whole chip erase */
FMC_CTL0 |= FMC_CTL0_MER;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the MER bit */
FMC_CTL0 &= ~FMC_CTL0_MER;
}
/* return the FMC state */
return fmc_state;
if (FMC_READY == fmc_state) {
/* start whole chip erase */
FMC_CTL0 |= FMC_CTL0_MER;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the MER bit */
FMC_CTL0 &= ~FMC_CTL0_MER;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -136,22 +130,21 @@ fmc_state_enum fmc_mass_erase(void)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
{
fmc_state_enum fmc_state = FMC_READY;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) {
fmc_state_enum fmc_state = FMC_READY;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the PG bit to start program */
FMC_CTL0 |= FMC_CTL0_PG;
REG32(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL0 &= ~FMC_CTL0_PG;
}
/* return the FMC state */
return fmc_state;
if (FMC_READY == fmc_state) {
/* set the PG bit to start program */
FMC_CTL0 |= FMC_CTL0_PG;
REG32(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL0 &= ~FMC_CTL0_PG;
}
/* return the FMC state */
return fmc_state;
}
/*
\brief FMC program a half word at the corresponding address
@@ -160,22 +153,21 @@ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
{
fmc_state_enum fmc_state = FMC_READY;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) {
fmc_state_enum fmc_state = FMC_READY;
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the PG bit to start program */
FMC_CTL0 |= FMC_CTL0_PG;
REG16(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL0 &= ~FMC_CTL0_PG;
}
/* return the FMC state */
return fmc_state;
if (FMC_READY == fmc_state) {
/* set the PG bit to start program */
FMC_CTL0 |= FMC_CTL0_PG;
REG16(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* reset the PG bit */
FMC_CTL0 &= ~FMC_CTL0_PG;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -184,17 +176,15 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data)
\param[out] none
\retval none
*/
void ob_unlock(void)
{
if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){
/* write the FMC key */
FMC_OBKEY = UNLOCK_KEY0;
FMC_OBKEY = UNLOCK_KEY1;
}
void ob_unlock(void) {
if (RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)) {
/* write the FMC key */
FMC_OBKEY = UNLOCK_KEY0;
FMC_OBKEY = UNLOCK_KEY1;
}
/* wait until OBWEN bit is set by hardware */
while (RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)) {
}
/* wait until OBWEN bit is set by hardware */
while (RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)) {}
}
/*!
@@ -203,10 +193,9 @@ void ob_unlock(void)
\param[out] none
\retval none
*/
void ob_lock(void)
{
/* reset the OBWEN bit */
FMC_CTL0 &= ~FMC_CTL0_OBWEN;
void ob_lock(void) {
/* reset the OBWEN bit */
FMC_CTL0 &= ~FMC_CTL0_OBWEN;
}
/*!
@@ -216,48 +205,47 @@ void ob_lock(void)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_erase(void)
{
uint16_t temp_spc = FMC_NSPC;
fmc_state_enum ob_erase(void) {
uint16_t temp_spc = FMC_NSPC;
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* check the option byte security protection value */
if(RESET != ob_spc_get()){
temp_spc = FMC_USPC;
/* check the option byte security protection value */
if (RESET != ob_spc_get()) {
temp_spc = FMC_USPC;
}
if (FMC_READY == fmc_state) {
/* start erase the option byte */
FMC_CTL0 |= FMC_CTL0_OBER;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if (FMC_READY == fmc_state) {
/* reset the OBER bit */
FMC_CTL0 &= ~FMC_CTL0_OBER;
/* set the OBPG bit */
FMC_CTL0 |= FMC_CTL0_OBPG;
/* no security protection */
OB_SPC = (uint16_t)temp_spc;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
} else {
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
}
if(FMC_READY == fmc_state){
/* start erase the option byte */
FMC_CTL0 |= FMC_CTL0_OBER;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* reset the OBER bit */
FMC_CTL0 &= ~FMC_CTL0_OBER;
/* set the OBPG bit */
FMC_CTL0 |= FMC_CTL0_OBPG;
/* no security protection */
OB_SPC = (uint16_t) temp_spc;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
}else{
if(FMC_TOERR != fmc_state){
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
}
}
/* return the FMC state */
return fmc_state;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -271,54 +259,53 @@ fmc_state_enum ob_erase(void)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
{
uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3;
fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) {
uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3;
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
ob_wp = (uint32_t) (~ob_wp);
temp_wp0 = (uint16_t) (ob_wp & OB_WP0_WP0);
temp_wp1 = (uint16_t) ((ob_wp & OB_WP1_WP1) >> 8U);
temp_wp2 = (uint16_t) ((ob_wp & OB_WP2_WP2) >> 16U);
temp_wp3 = (uint16_t) ((ob_wp & OB_WP3_WP3) >> 24U);
ob_wp = (uint32_t)(~ob_wp);
temp_wp0 = (uint16_t)(ob_wp & OB_WP0_WP0);
temp_wp1 = (uint16_t)((ob_wp & OB_WP1_WP1) >> 8U);
temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U);
temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U);
if(FMC_READY == fmc_state){
if (FMC_READY == fmc_state) {
/* set the OBPG bit*/
FMC_CTL0 |= FMC_CTL0_OBPG;
/* set the OBPG bit*/
FMC_CTL0 |= FMC_CTL0_OBPG;
if(0xFFU != temp_wp0){
OB_WP0 = temp_wp0;
if (0xFFU != temp_wp0) {
OB_WP0 = temp_wp0;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){
OB_WP1 = temp_wp1;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){
OB_WP2 = temp_wp2;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){
OB_WP3 = temp_wp3;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if(FMC_TOERR != fmc_state){
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
/* return the FMC state */
return fmc_state;
if ((FMC_READY == fmc_state) && (0xFFU != temp_wp1)) {
OB_WP1 = temp_wp1;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if ((FMC_READY == fmc_state) && (0xFFU != temp_wp2)) {
OB_WP2 = temp_wp2;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if ((FMC_READY == fmc_state) && (0xFFU != temp_wp3)) {
OB_WP3 = temp_wp3;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
}
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -330,42 +317,41 @@ fmc_state_enum ob_write_protection_enable(uint32_t ob_wp)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
{
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum ob_security_protection_config(uint8_t ob_spc) {
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
FMC_CTL0 |= FMC_CTL0_OBER;
FMC_CTL0 |= FMC_CTL0_START;
if (FMC_READY == fmc_state) {
FMC_CTL0 |= FMC_CTL0_OBER;
FMC_CTL0 |= FMC_CTL0_START;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* reset the OBER bit */
FMC_CTL0 &= ~FMC_CTL0_OBER;
if (FMC_READY == fmc_state) {
/* reset the OBER bit */
FMC_CTL0 &= ~FMC_CTL0_OBER;
/* start the option byte program */
FMC_CTL0 |= FMC_CTL0_OBPG;
/* start the option byte program */
FMC_CTL0 |= FMC_CTL0_OBPG;
OB_SPC = (uint16_t) ob_spc;
OB_SPC = (uint16_t)ob_spc;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
}else{
if (FMC_TOERR != fmc_state) {
/* reset the OBER bit */
FMC_CTL0 &= ~FMC_CTL0_OBER;
}
}
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
} else {
if (FMC_TOERR != fmc_state) {
/* reset the OBER bit */
FMC_CTL0 &= ~FMC_CTL0_OBER;
}
}
/* return the FMC state */
return fmc_state;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -384,31 +370,30 @@ fmc_state_enum ob_security_protection_config(uint8_t ob_spc)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot)
{
fmc_state_enum fmc_state = FMC_READY;
uint8_t temp;
fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) {
fmc_state_enum fmc_state = FMC_READY;
uint8_t temp;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if (FMC_READY == fmc_state) {
/* set the OBPG bit*/
FMC_CTL0 |= FMC_CTL0_OBPG;
temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK);
OB_USER = (uint16_t)temp;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the OBPG bit*/
FMC_CTL0 |= FMC_CTL0_OBPG;
temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK);
OB_USER = (uint16_t) temp;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_TOERR != fmc_state){
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
/* return the FMC state */
return fmc_state;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -419,23 +404,23 @@ fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum ob_data_program(uint32_t address, uint8_t data) {
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_READY == fmc_state){
/* set the OBPG bit */
FMC_CTL0 |= FMC_CTL0_OBPG;
REG16(address) = data;
if (FMC_READY == fmc_state) {
/* set the OBPG bit */
FMC_CTL0 |= FMC_CTL0_OBPG;
REG16(address) = data;
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
/* wait for the FMC ready */
fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT);
if(FMC_TOERR != fmc_state){
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
if (FMC_TOERR != fmc_state) {
/* reset the OBPG bit */
FMC_CTL0 &= ~FMC_CTL0_OBPG;
}
/* return the FMC state */
return fmc_state;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -444,10 +429,9 @@ fmc_state_enum ob_data_program(uint32_t address, uint8_t data) {
\param[out] none
\retval the FMC user option byte values
*/
uint8_t ob_user_get(void)
{
/* return the FMC user option byte value */
return (uint8_t) (FMC_OBSTAT >> 2U);
uint8_t ob_user_get(void) {
/* return the FMC user option byte value */
return (uint8_t)(FMC_OBSTAT >> 2U);
}
/*!
@@ -456,10 +440,7 @@ uint8_t ob_user_get(void)
\param[out] none
\retval ob_data
*/
uint16_t ob_data_get(void)
{
return (uint16_t) (FMC_OBSTAT >> 10U);
}
uint16_t ob_data_get(void) { return (uint16_t)(FMC_OBSTAT >> 10U); }
/*!
\brief get the FMC option byte write protection
@@ -467,10 +448,9 @@ uint16_t ob_data_get(void)
\param[out] none
\retval the FMC write protection option byte value
*/
uint32_t ob_write_protection_get(void)
{
/* return the FMC write protection option byte value */
return FMC_WP;
uint32_t ob_write_protection_get(void) {
/* return the FMC write protection option byte value */
return FMC_WP;
}
/*!
@@ -479,16 +459,15 @@ uint32_t ob_write_protection_get(void)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus ob_spc_get(void)
{
FlagStatus spc_state = RESET;
FlagStatus ob_spc_get(void) {
FlagStatus spc_state = RESET;
if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){
spc_state = SET;
}else{
spc_state = RESET;
}
return spc_state;
if (RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)) {
spc_state = SET;
} else {
spc_state = RESET;
}
return spc_state;
}
/*!
@@ -500,10 +479,7 @@ FlagStatus ob_spc_get(void)
\param[out] none
\retval none
*/
void fmc_interrupt_enable(uint32_t interrupt)
{
FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt));
}
void fmc_interrupt_enable(uint32_t interrupt) { FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); }
/*!
\brief disable FMC interrupt
@@ -514,10 +490,7 @@ void fmc_interrupt_enable(uint32_t interrupt)
\param[out] none
\retval none
*/
void fmc_interrupt_disable(uint32_t interrupt)
{
FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt));
}
void fmc_interrupt_disable(uint32_t interrupt) { FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); }
/*!
\brief check flag is set or not
@@ -531,13 +504,12 @@ void fmc_interrupt_disable(uint32_t interrupt)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fmc_flag_get(uint32_t flag)
{
if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){
return SET;
} else {
return RESET;
}
FlagStatus fmc_flag_get(uint32_t flag) {
if (RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -550,10 +522,7 @@ FlagStatus fmc_flag_get(uint32_t flag)
\param[out] none
\retval none
*/
void fmc_flag_clear(uint32_t flag)
{
FMC_REG_VAL(flag) = (!FMC_REG_VAL(flag)) | BIT(FMC_BIT_POS(flag));
}
void fmc_flag_clear(uint32_t flag) { FMC_REG_VAL(flag) = (!FMC_REG_VAL(flag)) | BIT(FMC_BIT_POS(flag)); }
/*!
\brief get FMC interrupt flag state
@@ -565,23 +534,22 @@ void fmc_flag_clear(uint32_t flag)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag)
{
FlagStatus ret1 = RESET;
FlagStatus ret2 = RESET;
FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) {
FlagStatus ret1 = RESET;
FlagStatus ret2 = RESET;
if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){
/* get the staus of interrupt flag */
ret1 = (FlagStatus) (FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag)));
/* get the staus of interrupt enale bit */
ret2 = (FlagStatus) (FMC_CTL0 & BIT(FMC_BIT_POS1(flag)));
}
if (FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)) {
/* get the staus of interrupt flag */
ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag)));
/* get the staus of interrupt enale bit */
ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag)));
}
if(ret1 && ret2){
return SET;
}else{
return RESET;
}
if (ret1 && ret2) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -594,10 +562,7 @@ FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag)
\param[out] none
\retval none
*/
void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag)
{
FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag));
}
void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) { FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); }
/*!
\brief get the FMC state
@@ -605,23 +570,22 @@ void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum fmc_state_get(void)
{
fmc_state_enum fmc_state = FMC_READY;
fmc_state_enum fmc_state_get(void) {
fmc_state_enum fmc_state = FMC_READY;
if((uint32_t) 0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){
fmc_state = FMC_BUSY;
}else{
if((uint32_t) 0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){
fmc_state = FMC_WPERR;
}else{
if((uint32_t) 0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){
fmc_state = FMC_PGERR;
}
}
if ((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)) {
fmc_state = FMC_BUSY;
} else {
if ((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)) {
fmc_state = FMC_WPERR;
} else {
if ((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))) {
fmc_state = FMC_PGERR;
}
}
/* return the FMC state */
return fmc_state;
}
/* return the FMC state */
return fmc_state;
}
/*!
@@ -630,20 +594,19 @@ fmc_state_enum fmc_state_get(void)
\param[out] none
\retval state of FMC, refer to fmc_state_enum
*/
fmc_state_enum fmc_ready_wait(uint32_t timeout)
{
fmc_state_enum fmc_state = FMC_BUSY;
fmc_state_enum fmc_ready_wait(uint32_t timeout) {
fmc_state_enum fmc_state = FMC_BUSY;
/* wait for FMC ready */
do{
/* get FMC state */
fmc_state = fmc_state_get();
timeout--;
}while((FMC_BUSY == fmc_state) && (0x00U != timeout));
/* wait for FMC ready */
do {
/* get FMC state */
fmc_state = fmc_state_get();
timeout--;
} while ((FMC_BUSY == fmc_state) && (0x00U != timeout));
if(FMC_BUSY == fmc_state){
fmc_state = FMC_TOERR;
}
/* return the FMC state */
return fmc_state;
if (FMC_BUSY == fmc_state) {
fmc_state = FMC_TOERR;
}
/* return the FMC state */
return fmc_state;
}

View File

@@ -1,43 +1,43 @@
/*!
\file gd32vf103_fwdgt.c
\brief FWDGT driver
\version 2019-6-5, V1.0.0, firmware for GD32VF103
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_fwdgt.h"
/* write value to FWDGT_CTL_CMD bit field */
#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0))
#define CTL_CMD(regval) (BITS(0, 15) & ((uint32_t)(regval) << 0))
/* write value to FWDGT_RLD_RLD bit field */
#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0))
#define RLD_RLD(regval) (BITS(0, 11) & ((uint32_t)(regval) << 0))
/*!
\brief enable write access to FWDGT_PSC and FWDGT_RLD
@@ -45,10 +45,7 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void fwdgt_write_enable(void)
{
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
}
void fwdgt_write_enable(void) { FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; }
/*!
\brief disable write access to FWDGT_PSC and FWDGT_RLD
@@ -56,10 +53,7 @@ void fwdgt_write_enable(void)
\param[out] none
\retval none
*/
void fwdgt_write_disable(void)
{
FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE;
}
void fwdgt_write_disable(void) { FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; }
/*!
\brief start the free watchdog timer counter
@@ -67,10 +61,7 @@ void fwdgt_write_disable(void)
\param[out] none
\retval none
*/
void fwdgt_enable(void)
{
FWDGT_CTL = FWDGT_KEY_ENABLE;
}
void fwdgt_enable(void) { FWDGT_CTL = FWDGT_KEY_ENABLE; }
/*!
\brief reload the counter of FWDGT
@@ -78,10 +69,7 @@ void fwdgt_enable(void)
\param[out] none
\retval none
*/
void fwdgt_counter_reload(void)
{
FWDGT_CTL = FWDGT_KEY_RELOAD;
}
void fwdgt_counter_reload(void) { FWDGT_CTL = FWDGT_KEY_RELOAD; }
/*!
\brief configure counter reload value, and prescaler divider value
@@ -98,54 +86,52 @@ void fwdgt_counter_reload(void)
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
{
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
/* enable write access to FWDGT_PSC,and FWDGT_RLD */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* wait until the PUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
}while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
if((uint32_t)RESET != flag_status){
return ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_div;
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) {
uint32_t timeout = FWDGT_PSC_TIMEOUT;
uint32_t flag_status = RESET;
timeout = FWDGT_RLD_TIMEOUT;
/* wait until the RUD flag to be reset */
do{
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
}while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
if((uint32_t)RESET != flag_status){
return ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
/* reload the counter */
FWDGT_CTL = FWDGT_KEY_RELOAD;
/* enable write access to FWDGT_PSC,and FWDGT_RLD */
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
/* wait until the PUD flag to be reset */
do {
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
} while ((--timeout > 0U) && ((uint32_t)RESET != flag_status));
return SUCCESS;
if ((uint32_t)RESET != flag_status) {
return ERROR;
}
/* configure FWDGT */
FWDGT_PSC = (uint32_t)prescaler_div;
timeout = FWDGT_RLD_TIMEOUT;
/* wait until the RUD flag to be reset */
do {
flag_status = FWDGT_STAT & FWDGT_STAT_RUD;
} while ((--timeout > 0U) && ((uint32_t)RESET != flag_status));
if ((uint32_t)RESET != flag_status) {
return ERROR;
}
FWDGT_RLD = RLD_RLD(reload_value);
/* reload the counter */
FWDGT_CTL = FWDGT_KEY_RELOAD;
return SUCCESS;
}
/*!
\brief get flag state of FWDGT
\param[in] flag: flag to get
\param[in] flag: flag to get
only one parameter can be selected which is shown as below:
\arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going
\arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus fwdgt_flag_get(uint16_t flag)
{
if(FWDGT_STAT & flag){
return SET;
}
return RESET;
FlagStatus fwdgt_flag_get(uint16_t flag) {
if (FWDGT_STAT & flag) {
return SET;
}
return RESET;
}

View File

@@ -8,41 +8,41 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_gpio.h"
#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
/*!
\brief reset GPIO port
@@ -50,37 +50,36 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void gpio_deinit(uint32_t gpio_periph)
{
switch (gpio_periph) {
case GPIOA:
/* reset GPIOA */
rcu_periph_reset_enable(RCU_GPIOARST);
rcu_periph_reset_disable(RCU_GPIOARST);
break;
case GPIOB:
/* reset GPIOB */
rcu_periph_reset_enable(RCU_GPIOBRST);
rcu_periph_reset_disable(RCU_GPIOBRST);
break;
case GPIOC:
/* reset GPIOC */
rcu_periph_reset_enable(RCU_GPIOCRST);
rcu_periph_reset_disable(RCU_GPIOCRST);
break;
case GPIOD:
/* reset GPIOD */
rcu_periph_reset_enable(RCU_GPIODRST);
rcu_periph_reset_disable(RCU_GPIODRST);
break;
case GPIOE:
/* reset GPIOE */
rcu_periph_reset_enable(RCU_GPIOERST);
rcu_periph_reset_disable(RCU_GPIOERST);
break;
default:
break;
}
void gpio_deinit(uint32_t gpio_periph) {
switch (gpio_periph) {
case GPIOA:
/* reset GPIOA */
rcu_periph_reset_enable(RCU_GPIOARST);
rcu_periph_reset_disable(RCU_GPIOARST);
break;
case GPIOB:
/* reset GPIOB */
rcu_periph_reset_enable(RCU_GPIOBRST);
rcu_periph_reset_disable(RCU_GPIOBRST);
break;
case GPIOC:
/* reset GPIOC */
rcu_periph_reset_enable(RCU_GPIOCRST);
rcu_periph_reset_disable(RCU_GPIOCRST);
break;
case GPIOD:
/* reset GPIOD */
rcu_periph_reset_enable(RCU_GPIODRST);
rcu_periph_reset_disable(RCU_GPIODRST);
break;
case GPIOE:
/* reset GPIOE */
rcu_periph_reset_enable(RCU_GPIOERST);
rcu_periph_reset_disable(RCU_GPIOERST);
break;
default:
break;
}
}
/*!
@@ -89,10 +88,9 @@ void gpio_deinit(uint32_t gpio_periph)
\param[out] none
\retval none
*/
void gpio_afio_deinit(void)
{
rcu_periph_reset_enable(RCU_AFRST);
rcu_periph_reset_disable(RCU_AFRST);
void gpio_afio_deinit(void) {
rcu_periph_reset_enable(RCU_AFRST);
rcu_periph_reset_disable(RCU_AFRST);
}
/*!
@@ -120,70 +118,68 @@ void gpio_afio_deinit(void)
\param[out] none
\retval none
*/
void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed,
uint32_t pin)
{
uint16_t i;
uint32_t temp_mode = 0U;
uint32_t reg = 0U;
void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin) {
uint16_t i;
uint32_t temp_mode = 0U;
uint32_t reg = 0U;
/* GPIO mode configuration */
temp_mode = (uint32_t) (mode & ((uint32_t) 0x0FU));
/* GPIO mode configuration */
temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
/* GPIO speed configuration */
if (((uint32_t) 0x00U) != ((uint32_t) mode & ((uint32_t) 0x10U))) {
/* output mode max speed:10MHz,2MHz,50MHz */
temp_mode |= (uint32_t) speed;
}
/* GPIO speed configuration */
if (((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))) {
/* output mode max speed:10MHz,2MHz,50MHz */
temp_mode |= (uint32_t)speed;
}
/* configure the eight low port pins with GPIO_CTL0 */
for (i = 0U; i < 8U; i++) {
if ((1U << i) & pin) {
reg = GPIO_CTL0(gpio_periph);
/* configure the eight low port pins with GPIO_CTL0 */
for (i = 0U; i < 8U; i++) {
if ((1U << i) & pin) {
reg = GPIO_CTL0(gpio_periph);
/* clear the specified pin mode bits */
reg &= ~GPIO_MODE_MASK(i);
/* set the specified pin mode bits */
reg |= GPIO_MODE_SET(i, temp_mode);
/* clear the specified pin mode bits */
reg &= ~GPIO_MODE_MASK(i);
/* set the specified pin mode bits */
reg |= GPIO_MODE_SET(i, temp_mode);
/* set IPD or IPU */
if (GPIO_MODE_IPD == mode) {
/* reset the corresponding OCTL bit */
GPIO_BC(gpio_periph) = (uint32_t) ((1U << i) & pin);
} else {
/* set the corresponding OCTL bit */
if (GPIO_MODE_IPU == mode) {
GPIO_BOP(gpio_periph) = (uint32_t) ((1U << i) & pin);
}
}
/* set GPIO_CTL0 register */
GPIO_CTL0(gpio_periph) = reg;
/* set IPD or IPU */
if (GPIO_MODE_IPD == mode) {
/* reset the corresponding OCTL bit */
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
} else {
/* set the corresponding OCTL bit */
if (GPIO_MODE_IPU == mode) {
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
}
}
/* set GPIO_CTL0 register */
GPIO_CTL0(gpio_periph) = reg;
}
/* configure the eight high port pins with GPIO_CTL1 */
for (i = 8U; i < 16U; i++) {
if ((1U << i) & pin) {
reg = GPIO_CTL1(gpio_periph);
}
/* configure the eight high port pins with GPIO_CTL1 */
for (i = 8U; i < 16U; i++) {
if ((1U << i) & pin) {
reg = GPIO_CTL1(gpio_periph);
/* clear the specified pin mode bits */
reg &= ~GPIO_MODE_MASK(i - 8U);
/* set the specified pin mode bits */
reg |= GPIO_MODE_SET(i - 8U, temp_mode);
/* clear the specified pin mode bits */
reg &= ~GPIO_MODE_MASK(i - 8U);
/* set the specified pin mode bits */
reg |= GPIO_MODE_SET(i - 8U, temp_mode);
/* set IPD or IPU */
if (GPIO_MODE_IPD == mode) {
/* reset the corresponding OCTL bit */
GPIO_BC(gpio_periph) = (uint32_t) ((1U << i) & pin);
} else {
/* set the corresponding OCTL bit */
if (GPIO_MODE_IPU == mode) {
GPIO_BOP(gpio_periph) = (uint32_t) ((1U << i) & pin);
}
}
/* set GPIO_CTL1 register */
GPIO_CTL1(gpio_periph) = reg;
/* set IPD or IPU */
if (GPIO_MODE_IPD == mode) {
/* reset the corresponding OCTL bit */
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
} else {
/* set the corresponding OCTL bit */
if (GPIO_MODE_IPU == mode) {
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
}
}
/* set GPIO_CTL1 register */
GPIO_CTL1(gpio_periph) = reg;
}
}
}
/*!
@@ -195,10 +191,7 @@ void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed,
\param[out] none
\retval none
*/
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
{
GPIO_BOP(gpio_periph) = (uint32_t) pin;
}
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) { GPIO_BOP(gpio_periph) = (uint32_t)pin; }
/*!
\brief reset GPIO pin
@@ -209,10 +202,7 @@ void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
\param[out] none
\retval none
*/
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
{
GPIO_BC(gpio_periph) = (uint32_t) pin;
}
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) { GPIO_BC(gpio_periph) = (uint32_t)pin; }
/*!
\brief write data to the specified GPIO pin
@@ -227,13 +217,12 @@ void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
\param[out] none
\retval none
*/
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
{
if (RESET != bit_value) {
GPIO_BOP(gpio_periph) = (uint32_t) pin;
} else {
GPIO_BC(gpio_periph) = (uint32_t) pin;
}
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) {
if (RESET != bit_value) {
GPIO_BOP(gpio_periph) = (uint32_t)pin;
} else {
GPIO_BC(gpio_periph) = (uint32_t)pin;
}
}
/*!
@@ -243,10 +232,7 @@ void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
\param[out] none
\retval none
*/
void gpio_port_write(uint32_t gpio_periph, uint16_t data)
{
GPIO_OCTL(gpio_periph) = (uint32_t) data;
}
void gpio_port_write(uint32_t gpio_periph, uint16_t data) { GPIO_OCTL(gpio_periph) = (uint32_t)data; }
/*!
\brief get GPIO pin input status
@@ -257,13 +243,12 @@ void gpio_port_write(uint32_t gpio_periph, uint16_t data)
\param[out] none
\retval input status of gpio pin: SET or RESET
*/
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
{
if ((uint32_t) RESET != (GPIO_ISTAT(gpio_periph) & (pin))) {
return SET;
} else {
return RESET;
}
FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin) {
if ((uint32_t)RESET != (GPIO_ISTAT(gpio_periph) & (pin))) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -272,10 +257,7 @@ FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
\param[out] none
\retval input status of gpio all pins
*/
uint16_t gpio_input_port_get(uint32_t gpio_periph)
{
return (uint16_t) (GPIO_ISTAT(gpio_periph));
}
uint16_t gpio_input_port_get(uint32_t gpio_periph) { return (uint16_t)(GPIO_ISTAT(gpio_periph)); }
/*!
\brief get GPIO pin output status
@@ -286,13 +268,12 @@ uint16_t gpio_input_port_get(uint32_t gpio_periph)
\param[out] none
\retval output status of gpio pin: SET or RESET
*/
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
{
if ((uint32_t) RESET != (GPIO_OCTL(gpio_periph) & (pin))) {
return SET;
} else {
return RESET;
}
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) {
if ((uint32_t)RESET != (GPIO_OCTL(gpio_periph) & (pin))) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -301,10 +282,7 @@ FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
\param[out] none
\retval output status of gpio all pins
*/
uint16_t gpio_output_port_get(uint32_t gpio_periph)
{
return ((uint16_t) GPIO_OCTL(gpio_periph));
}
uint16_t gpio_output_port_get(uint32_t gpio_periph) { return ((uint16_t)GPIO_OCTL(gpio_periph)); }
/*!
\brief configure GPIO pin remap
@@ -338,47 +316,45 @@ uint16_t gpio_output_port_get(uint32_t gpio_periph)
\param[out] none
\retval none
*/
void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
{
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) {
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) {
/* get AFIO_PCF1 regiter value */
temp_reg = AFIO_PCF1;
} else {
/* get AFIO_PCF0 regiter value */
temp_reg = AFIO_PCF0;
}
if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) {
/* get AFIO_PCF1 regiter value */
temp_reg = AFIO_PCF1;
} else {
/* get AFIO_PCF0 regiter value */
temp_reg = AFIO_PCF0;
}
temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
remap1 = remap & LSB_16BIT_MASK;
temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
remap1 = remap & LSB_16BIT_MASK;
/* judge pin remap type */
if ((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK)
== (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))) {
temp_reg &= PCF_SWJCFG_MASK;
AFIO_PCF0 &= PCF_SWJCFG_MASK;
} else if (PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)) {
remap2 = ((uint32_t) 0x03U) << temp_mask;
temp_reg &= ~remap2;
temp_reg |= ~PCF_SWJCFG_MASK;
} else {
temp_reg &= ~(remap1 << ((remap >> 0x15U) * 0x10U));
temp_reg |= ~PCF_SWJCFG_MASK;
}
/* judge pin remap type */
if ((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))) {
temp_reg &= PCF_SWJCFG_MASK;
AFIO_PCF0 &= PCF_SWJCFG_MASK;
} else if (PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)) {
remap2 = ((uint32_t)0x03U) << temp_mask;
temp_reg &= ~remap2;
temp_reg |= ~PCF_SWJCFG_MASK;
} else {
temp_reg &= ~(remap1 << ((remap >> 0x15U) * 0x10U));
temp_reg |= ~PCF_SWJCFG_MASK;
}
/* set pin remap value */
if (DISABLE != newvalue) {
temp_reg |= (remap1 << ((remap >> 0x15U) * 0x10U));
}
/* set pin remap value */
if (DISABLE != newvalue) {
temp_reg |= (remap1 << ((remap >> 0x15U) * 0x10U));
}
if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) {
/* set AFIO_PCF1 regiter value */
AFIO_PCF1 = temp_reg;
} else {
/* set AFIO_PCF0 regiter value */
AFIO_PCF0 = temp_reg;
}
if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) {
/* set AFIO_PCF1 regiter value */
AFIO_PCF1 = temp_reg;
} else {
/* set AFIO_PCF0 regiter value */
AFIO_PCF0 = temp_reg;
}
}
/*!
@@ -394,38 +370,28 @@ void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
\param[out] none
\retval none
*/
void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
{
uint32_t source = 0U;
source = ((uint32_t) 0x0FU)
<< (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) {
uint32_t source = 0U;
source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
/* select EXTI sources */
if (GPIO_PIN_SOURCE_4 > output_pin) {
/* select EXTI0/EXTI1/EXTI2/EXTI3 */
AFIO_EXTISS0 &= ~source;
AFIO_EXTISS0 |= (((uint32_t) output_port)
<< (AFIO_EXTI_SOURCE_FIELDS
* (output_pin & AFIO_EXTI_SOURCE_MASK)));
} else if (GPIO_PIN_SOURCE_8 > output_pin) {
/* select EXTI4/EXTI5/EXTI6/EXTI7 */
AFIO_EXTISS1 &= ~source;
AFIO_EXTISS1 |= (((uint32_t) output_port)
<< (AFIO_EXTI_SOURCE_FIELDS
* (output_pin & AFIO_EXTI_SOURCE_MASK)));
} else if (GPIO_PIN_SOURCE_12 > output_pin) {
/* select EXTI8/EXTI9/EXTI10/EXTI11 */
AFIO_EXTISS2 &= ~source;
AFIO_EXTISS2 |= (((uint32_t) output_port)
<< (AFIO_EXTI_SOURCE_FIELDS
* (output_pin & AFIO_EXTI_SOURCE_MASK)));
} else {
/* select EXTI12/EXTI13/EXTI14/EXTI15 */
AFIO_EXTISS3 &= ~source;
AFIO_EXTISS3 |= (((uint32_t) output_port)
<< (AFIO_EXTI_SOURCE_FIELDS
* (output_pin & AFIO_EXTI_SOURCE_MASK)));
}
/* select EXTI sources */
if (GPIO_PIN_SOURCE_4 > output_pin) {
/* select EXTI0/EXTI1/EXTI2/EXTI3 */
AFIO_EXTISS0 &= ~source;
AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
} else if (GPIO_PIN_SOURCE_8 > output_pin) {
/* select EXTI4/EXTI5/EXTI6/EXTI7 */
AFIO_EXTISS1 &= ~source;
AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
} else if (GPIO_PIN_SOURCE_12 > output_pin) {
/* select EXTI8/EXTI9/EXTI10/EXTI11 */
AFIO_EXTISS2 &= ~source;
AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
} else {
/* select EXTI12/EXTI13/EXTI14/EXTI15 */
AFIO_EXTISS3 &= ~source;
AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
}
}
/*!
@@ -443,18 +409,17 @@ void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
\param[out] none
\retval none
*/
void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
{
uint32_t reg = 0U;
reg = AFIO_EC;
void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) {
uint32_t reg = 0U;
reg = AFIO_EC;
/* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
reg &= (uint32_t) (~(AFIO_EC_PORT | AFIO_EC_PIN));
/* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
reg &= (uint32_t)(~(AFIO_EC_PORT | AFIO_EC_PIN));
reg |= (uint32_t) ((uint32_t) output_port << GPIO_OUTPUT_PORT_OFFSET);
reg |= (uint32_t) output_pin;
reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET);
reg |= (uint32_t)output_pin;
AFIO_EC = reg;
AFIO_EC = reg;
}
/*!
@@ -463,10 +428,7 @@ void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
\param[out] none
\retval none
*/
void gpio_event_output_enable(void)
{
AFIO_EC |= AFIO_EC_EOE;
}
void gpio_event_output_enable(void) { AFIO_EC |= AFIO_EC_EOE; }
/*!
\brief disable GPIO pin event output
@@ -474,10 +436,7 @@ void gpio_event_output_enable(void)
\param[out] none
\retval none
*/
void gpio_event_output_disable(void)
{
AFIO_EC &= (uint32_t) (~AFIO_EC_EOE);
}
void gpio_event_output_disable(void) { AFIO_EC &= (uint32_t)(~AFIO_EC_EOE); }
/*!
\brief lock GPIO pin
@@ -488,15 +447,14 @@ void gpio_event_output_disable(void)
\param[out] none
\retval none
*/
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
{
uint32_t lock = 0x00010000U;
lock |= pin;
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) {
uint32_t lock = 0x00010000U;
lock |= pin;
/* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */
GPIO_LOCK(gpio_periph) = (uint32_t) lock;
GPIO_LOCK(gpio_periph) = (uint32_t) pin;
GPIO_LOCK(gpio_periph) = (uint32_t) lock;
lock = GPIO_LOCK(gpio_periph);
lock = GPIO_LOCK(gpio_periph);
/* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
GPIO_LOCK(gpio_periph) = (uint32_t)pin;
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
lock = GPIO_LOCK(gpio_periph);
lock = GPIO_LOCK(gpio_periph);
}

View File

@@ -8,41 +8,41 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_i2c.h"
/* I2C register bit mask */
#define I2CCLK_MAX ((uint32_t)0x00000048U) /*!< i2cclk maximum value */
#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */
#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */
#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */
#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */
#define I2CCLK_MAX ((uint32_t)0x00000048U) /*!< i2cclk maximum value */
#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */
#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */
#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */
#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */
/* I2C register bit offset */
#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */
#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */
/*!
\brief reset I2C
@@ -50,22 +50,21 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void i2c_deinit(uint32_t i2c_periph)
{
switch (i2c_periph) {
case I2C0:
/* reset I2C0 */
rcu_periph_reset_enable(RCU_I2C0RST);
rcu_periph_reset_disable(RCU_I2C0RST);
break;
case I2C1:
/* reset I2C1 */
rcu_periph_reset_enable(RCU_I2C1RST);
rcu_periph_reset_disable(RCU_I2C1RST);
break;
default:
break;
}
void i2c_deinit(uint32_t i2c_periph) {
switch (i2c_periph) {
case I2C0:
/* reset I2C0 */
rcu_periph_reset_enable(RCU_I2C0RST);
rcu_periph_reset_disable(RCU_I2C0RST);
break;
case I2C1:
/* reset I2C1 */
rcu_periph_reset_enable(RCU_I2C1RST);
rcu_periph_reset_disable(RCU_I2C1RST);
break;
default:
break;
}
}
/*!
@@ -74,70 +73,68 @@ void i2c_deinit(uint32_t i2c_periph)
\param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
\param[in] dutycyc: duty cycle in fast mode
only one parameter can be selected which is shown as below:
\arg I2C_DTCY_2: T_low/T_high=2
\arg I2C_DTCY_2: T_low/T_high=2
\arg I2C_DTCY_16_9: T_low/T_high=16/9
\param[out] none
\retval none
*/
void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
{
uint32_t pclk1, clkc, freq, risetime;
uint32_t temp;
void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) {
uint32_t pclk1, clkc, freq, risetime;
uint32_t temp;
pclk1 = rcu_clock_freq_get(CK_APB1);
/* I2C peripheral clock frequency */
freq = (uint32_t) (pclk1 / 1000000U);
if (freq >= I2CCLK_MAX) {
freq = I2CCLK_MAX;
}
temp = I2C_CTL1(i2c_periph);
temp &= ~I2C_CTL1_I2CCLK;
temp |= freq;
pclk1 = rcu_clock_freq_get(CK_APB1);
/* I2C peripheral clock frequency */
freq = (uint32_t)(pclk1 / 1000000U);
if (freq >= I2CCLK_MAX) {
freq = I2CCLK_MAX;
}
temp = I2C_CTL1(i2c_periph);
temp &= ~I2C_CTL1_I2CCLK;
temp |= freq;
I2C_CTL1(i2c_periph) = temp;
I2C_CTL1(i2c_periph) = temp;
if (100000U >= clkspeed) {
/* the maximum SCL rise time is 1000ns in standard mode */
risetime = (uint32_t) ((pclk1 / 1000000U) + 1U);
if (risetime >= I2CCLK_MAX) {
I2C_RT(i2c_periph) = I2CCLK_MAX;
} else if (risetime <= I2CCLK_MIN) {
I2C_RT(i2c_periph) = I2CCLK_MIN;
} else {
I2C_RT(i2c_periph) = risetime;
}
clkc = (uint32_t) (pclk1 / (clkspeed * 2U));
if (clkc < 0x04U) {
/* the CLKC in standard mode minmum value is 4 */
clkc = 0x04U;
}
I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
} else if (400000U >= clkspeed) {
/* the maximum SCL rise time is 300ns in fast mode */
I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U)
/ (uint32_t) 1000U) + (uint32_t) 1U);
if (I2C_DTCY_2 == dutycyc) {
/* I2C duty cycle is 2 */
clkc = (uint32_t) (pclk1 / (clkspeed * 3U));
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
} else {
/* I2C duty cycle is 16/9 */
clkc = (uint32_t) (pclk1 / (clkspeed * 25U));
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
}
if (0U == (clkc & I2C_CKCFG_CLKC)) {
/* the CLKC in fast mode minmum value is 1 */
clkc |= 0x0001U;
}
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
I2C_CKCFG(i2c_periph) |= clkc;
if (100000U >= clkspeed) {
/* the maximum SCL rise time is 1000ns in standard mode */
risetime = (uint32_t)((pclk1 / 1000000U) + 1U);
if (risetime >= I2CCLK_MAX) {
I2C_RT(i2c_periph) = I2CCLK_MAX;
} else if (risetime <= I2CCLK_MIN) {
I2C_RT(i2c_periph) = I2CCLK_MIN;
} else {
I2C_RT(i2c_periph) = risetime;
}
clkc = (uint32_t)(pclk1 / (clkspeed * 2U));
if (clkc < 0x04U) {
/* the CLKC in standard mode minmum value is 4 */
clkc = 0x04U;
}
I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
} else if (400000U >= clkspeed) {
/* the maximum SCL rise time is 300ns in fast mode */
I2C_RT(i2c_periph) = (uint32_t)(((freq * (uint32_t)300U) / (uint32_t)1000U) + (uint32_t)1U);
if (I2C_DTCY_2 == dutycyc) {
/* I2C duty cycle is 2 */
clkc = (uint32_t)(pclk1 / (clkspeed * 3U));
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
} else {
/* I2C duty cycle is 16/9 */
clkc = (uint32_t)(pclk1 / (clkspeed * 25U));
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
}
if (0U == (clkc & I2C_CKCFG_CLKC)) {
/* the CLKC in fast mode minmum value is 1 */
clkc |= 0x0001U;
}
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
I2C_CKCFG(i2c_periph) |= clkc;
} else {
}
}
/*!
\brief configure I2C address
\brief configure I2C address
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] mode:
only one parameter can be selected which is shown as below:
@@ -151,18 +148,17 @@ void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
\param[out] none
\retval none
*/
void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode,uint32_t addformat, uint32_t addr)
{
/* SMBus/I2C mode selected */
uint32_t ctl = 0U;
void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) {
/* SMBus/I2C mode selected */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SMBEN);
ctl |= mode;
I2C_CTL0(i2c_periph) = ctl;
/* configure address */
addr = addr & I2C_ADDRESS_MASK;
I2C_SADDR0(i2c_periph) = (addformat | addr);
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SMBEN);
ctl |= mode;
I2C_CTL0(i2c_periph) = ctl;
/* configure address */
addr = addr & I2C_ADDRESS_MASK;
I2C_SADDR0(i2c_periph) = (addformat | addr);
}
/*!
@@ -175,13 +171,12 @@ void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode,uint32_t addformat,
\param[out] none
\retval none
*/
void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
{
if (I2C_SMBUS_HOST == type) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
}
void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) {
if (I2C_SMBUS_HOST == type) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
}
}
/*!
@@ -194,13 +189,12 @@ void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
\param[out] none
\retval none
*/
void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
{
if (I2C_ACK_ENABLE == ack) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN);
}
void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) {
if (I2C_ACK_ENABLE == ack) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN);
}
}
/*!
@@ -213,37 +207,35 @@ void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
\param[out] none
\retval none
*/
void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
{
/* configure I2C POAP position */
if (I2C_ACKPOS_NEXT == pos) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP);
}
void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) {
/* configure I2C POAP position */
if (I2C_ACKPOS_NEXT == pos) {
I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP;
} else {
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP);
}
}
/*!
\brief master sends slave address
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] addr: slave address
\param[in] addr: slave address
\param[in] trandirection: transmitter or receiver
only one parameter can be selected which is shown as below:
\arg I2C_TRANSMITTER: transmitter
\arg I2C_RECEIVER: receiver
\arg I2C_TRANSMITTER: transmitter
\arg I2C_RECEIVER: receiver
\param[out] none
\retval none
*/
void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr,uint32_t trandirection)
{
/* master is a transmitter or a receiver */
if (I2C_TRANSMITTER == trandirection) {
addr = addr & I2C_TRANSMITTER;
} else {
addr = addr | I2C_RECEIVER;
}
/* send slave address */
I2C_DATA(i2c_periph) = addr;
void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) {
/* master is a transmitter or a receiver */
if (I2C_TRANSMITTER == trandirection) {
addr = addr & I2C_TRANSMITTER;
} else {
addr = addr | I2C_RECEIVER;
}
/* send slave address */
I2C_DATA(i2c_periph) = addr;
}
/*!
@@ -253,10 +245,9 @@ void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr,uint32_t trandirec
\param[out] none
\retval none
*/
void i2c_saddr1_config(uint32_t i2c_periph,uint32_t addr)
{
/* configure saddress1 */
I2C_SADDR1(i2c_periph) = (0xFE & addr);
void i2c_saddr1_config(uint32_t i2c_periph, uint32_t addr) {
/* configure saddress1 */
I2C_SADDR1(i2c_periph) = (0xFE & addr);
}
/*!
@@ -266,45 +257,35 @@ void i2c_saddr1_config(uint32_t i2c_periph,uint32_t addr)
\param[out] none
\retval none
*/
void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr)
{
/* configure address */
addr = addr & I2C_ADDRESS2_MASK;
I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) {
/* configure address */
addr = addr & I2C_ADDRESS2_MASK;
I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
}
/*!
\brief disable dual-address mode
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[out] none
\retval none
*/
void i2c_dualaddr_disable(uint32_t i2c_periph)
{
I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
}
void i2c_dualaddr_disable(uint32_t i2c_periph) { I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); }
/*!
\brief enable I2C
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[out] none
\retval none
*/
void i2c_enable(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
}
void i2c_enable(uint32_t i2c_periph) { I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; }
/*!
\brief disable I2C
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[out] none
\retval none
*/
void i2c_disable(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
}
void i2c_disable(uint32_t i2c_periph) { I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); }
/*!
\brief generate a START condition on I2C bus
@@ -312,10 +293,7 @@ void i2c_disable(uint32_t i2c_periph)
\param[out] none
\retval none
*/
void i2c_start_on_bus(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
}
void i2c_start_on_bus(uint32_t i2c_periph) { I2C_CTL0(i2c_periph) |= I2C_CTL0_START; }
/*!
\brief generate a STOP condition on I2C bus
@@ -323,22 +301,16 @@ void i2c_start_on_bus(uint32_t i2c_periph)
\param[out] none
\retval none
*/
void i2c_stop_on_bus(uint32_t i2c_periph)
{
I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
}
void i2c_stop_on_bus(uint32_t i2c_periph) { I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; }
/*!
\brief I2C transmit data function
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] data: data of transmission
\param[in] data: data of transmission
\param[out] none
\retval none
*/
void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
{
I2C_DATA(i2c_periph) = DATA_TRANS(data);
}
void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) { I2C_DATA(i2c_periph) = DATA_TRANS(data); }
/*!
\brief I2C receive data function
@@ -346,13 +318,10 @@ void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
\param[out] none
\retval data of received
*/
uint8_t i2c_data_receive(uint32_t i2c_periph)
{
return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph));
}
uint8_t i2c_data_receive(uint32_t i2c_periph) { return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph)); }
/*!
\brief enable I2C DMA mode
\brief enable I2C DMA mode
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] dmastate:
only one parameter can be selected which is shown as below:
@@ -361,15 +330,14 @@ uint8_t i2c_data_receive(uint32_t i2c_periph)
\param[out] none
\retval none
*/
void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate)
{
/* configure I2C DMA function */
uint32_t ctl = 0U;
void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) {
/* configure I2C DMA function */
uint32_t ctl = 0U;
ctl = I2C_CTL1(i2c_periph);
ctl &= ~(I2C_CTL1_DMAON);
ctl |= dmastate;
I2C_CTL1(i2c_periph) = ctl;
ctl = I2C_CTL1(i2c_periph);
ctl &= ~(I2C_CTL1_DMAON);
ctl |= dmastate;
I2C_CTL1(i2c_periph) = ctl;
}
/*!
@@ -382,19 +350,18 @@ void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate)
\param[out] none
\retval none
*/
void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
{
/* configure DMA last transfer */
uint32_t ctl = 0U;
void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) {
/* configure DMA last transfer */
uint32_t ctl = 0U;
ctl = I2C_CTL1(i2c_periph);
ctl &= ~(I2C_CTL1_DMALST);
ctl |= dmalast;
I2C_CTL1(i2c_periph) = ctl;
ctl = I2C_CTL1(i2c_periph);
ctl &= ~(I2C_CTL1_DMALST);
ctl |= dmalast;
I2C_CTL1(i2c_periph) = ctl;
}
/*!
\brief whether to stretch SCL low when data is not ready in slave mode
\brief whether to stretch SCL low when data is not ready in slave mode
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] stretchpara:
only one parameter can be selected which is shown as below:
@@ -403,19 +370,18 @@ void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
\param[out] none
\retval none
*/
void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
{
/* configure I2C SCL strerching enable or disable */
uint32_t ctl = 0U;
void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) {
/* configure I2C SCL strerching enable or disable */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SS);
ctl |= stretchpara;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SS);
ctl |= stretchpara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief whether or not to response to a general call
\brief whether or not to response to a general call
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] gcallpara:
only one parameter can be selected which is shown as below:
@@ -424,19 +390,18 @@ void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
\param[out] none
\retval none
*/
void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
{
/* configure slave response to a general call enable or disable */
uint32_t ctl = 0U;
void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) {
/* configure slave response to a general call enable or disable */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_GCEN);
ctl |= gcallpara;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_GCEN);
ctl |= gcallpara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief software reset I2C
\brief software reset I2C
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] sreset:
only one parameter can be selected which is shown as below:
@@ -445,15 +410,14 @@ void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
\param[out] none
\retval none
*/
void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
{
/* modify CTL0 and configure software reset I2C state */
uint32_t ctl = 0U;
void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) {
/* modify CTL0 and configure software reset I2C state */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SRESET);
ctl |= sreset;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SRESET);
ctl |= sreset;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
@@ -461,20 +425,19 @@ void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] pecpara:
only one parameter can be selected which is shown as below:
\arg I2C_PEC_ENABLE: PEC calculation on
\arg I2C_PEC_DISABLE: PEC calculation off
\arg I2C_PEC_ENABLE: PEC calculation on
\arg I2C_PEC_DISABLE: PEC calculation off
\param[out] none
\retval none
*/
void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate)
{
/* on/off PEC calculation */
uint32_t ctl = 0U;
void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) {
/* on/off PEC calculation */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_PECEN);
ctl |= pecstate;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_PECEN);
ctl |= pecstate;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
@@ -482,52 +445,47 @@ void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] pecpara:
only one parameter can be selected which is shown as below:
\arg I2C_PECTRANS_ENABLE: transfer PEC
\arg I2C_PECTRANS_DISABLE: not transfer PEC
\arg I2C_PECTRANS_ENABLE: transfer PEC
\arg I2C_PECTRANS_DISABLE: not transfer PEC
\param[out] none
\retval none
*/
void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara)
{
/* whether to transfer PEC */
uint32_t ctl = 0U;
void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) {
/* whether to transfer PEC */
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_PECTRANS);
ctl |= pecpara;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_PECTRANS);
ctl |= pecpara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
\brief get packet error checking value
\brief get packet error checking value
\param[in] i2c_periph: I2Cx(x=0,1)
\param[out] none
\retval PEC value
*/
uint8_t i2c_pec_value_get(uint32_t i2c_periph)
{
return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>> STAT1_PECV_OFFSET);
}
uint8_t i2c_pec_value_get(uint32_t i2c_periph) { return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET); }
/*!
\brief I2C issue alert through SMBA pin
\brief I2C issue alert through SMBA pin
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] smbuspara:
only one parameter can be selected which is shown as below:
\arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin
\arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
\arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin
\arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
\param[out] none
\retval none
*/
void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara)
{
/* issue alert through SMBA pin configure*/
uint32_t ctl = 0U;
void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) {
/* issue alert through SMBA pin configure*/
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SALT);
ctl |= smbuspara;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_SALT);
ctl |= smbuspara;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
@@ -540,15 +498,14 @@ void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara)
\param[out] none
\retval none
*/
void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate)
{
/* enable or disable I2C ARP protocol*/
uint32_t ctl = 0U;
void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) {
/* enable or disable I2C ARP protocol*/
uint32_t ctl = 0U;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_ARPEN);
ctl |= arpstate;
I2C_CTL0(i2c_periph) = ctl;
ctl = I2C_CTL0(i2c_periph);
ctl &= ~(I2C_CTL0_ARPEN);
ctl |= arpstate;
I2C_CTL0(i2c_periph) = ctl;
}
/*!
@@ -556,7 +513,7 @@ void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] flag: I2C flags, refer to i2c_flag_enum
only one parameter can be selected which is shown as below:
\arg I2C_FLAG_SBSEND: start condition send out
\arg I2C_FLAG_SBSEND: start condition send out
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
\arg I2C_FLAG_BTC: byte transmission finishes
\arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
@@ -580,13 +537,12 @@ void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
{
if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) {
return SET;
} else {
return RESET;
}
FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) {
if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -597,24 +553,23 @@ FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
\arg I2C_FLAG_SMBALT: SMBus Alert status
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
\arg I2C_FLAG_PECERR: PEC error when receiving data
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
\arg I2C_FLAG_AERR: acknowledge error
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
\arg I2C_FLAG_BERR: a bus error
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
\arg I2C_FLAG_BERR: a bus error
\arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1
\param[out] none
\retval none
*/
void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
{
uint32_t temp;
if (I2C_FLAG_ADDSEND == flag) {
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
temp = I2C_STAT0(i2c_periph);
temp = I2C_STAT1(i2c_periph);
} else {
I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
}
void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) {
uint32_t temp;
if (I2C_FLAG_ADDSEND == flag) {
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
temp = I2C_STAT0(i2c_periph);
temp = I2C_STAT1(i2c_periph);
} else {
I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
}
}
/*!
@@ -622,32 +577,26 @@ void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
only one parameter can be selected which is shown as below:
\arg I2C_INT_ERR: error interrupt enable
\arg I2C_INT_EV: event interrupt enable
\arg I2C_INT_ERR: error interrupt enable
\arg I2C_INT_EV: event interrupt enable
\arg I2C_INT_BUF: buffer interrupt enable
\param[out] none
\retval none
*/
void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
{
I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
}
void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) { I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); }
/*!
\brief disable I2C interrupt
\param[in] i2c_periph: I2Cx(x=0,1)
\param[in] interrupt: I2C interrupts, refer to i2c_flag_enum
only one parameter can be selected which is shown as below:
\arg I2C_INT_ERR: error interrupt enable
\arg I2C_INT_EV: event interrupt enable
\arg I2C_INT_ERR: error interrupt enable
\arg I2C_INT_EV: event interrupt enable
\arg I2C_INT_BUF: buffer interrupt enable
\param[out] none
\retval none
*/
void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
{
I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
}
void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) { I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); }
/*!
\brief check I2C interrupt flag
@@ -671,30 +620,29 @@ void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U, bufie;
FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) {
uint32_t intenable = 0U, flagstatus = 0U, bufie;
/* check BUFIE */
bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE;
/* check BUFIE */
bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE;
/* get the interrupt enable bit status */
intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag)& BIT(I2C_BIT_POS2(int_flag)));
/* get the interrupt enable bit status */
intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag)));
if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) {
if (intenable && bufie) {
intenable = 1U;
} else {
intenable = 0U;
}
}
if ((0U != flagstatus) && (0U != intenable)) {
return SET;
if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) {
if (intenable && bufie) {
intenable = 1U;
} else {
return RESET;
intenable = 0U;
}
}
if ((0U != flagstatus) && (0U != intenable)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -713,14 +661,13 @@ FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum in
\param[out] none
\retval none
*/
void i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag)
{
uint32_t temp;
if (I2C_INT_FLAG_ADDSEND == int_flag) {
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
temp = I2C_STAT0(i2c_periph);
temp = I2C_STAT1(i2c_periph);
} else {
I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
}
void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) {
uint32_t temp;
if (I2C_INT_FLAG_ADDSEND == int_flag) {
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
temp = I2C_STAT0(i2c_periph);
temp = I2C_STAT1(i2c_periph);
} else {
I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
}
}

View File

@@ -40,11 +40,10 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void pmu_deinit(void)
{
/* reset PMU */
rcu_periph_reset_enable(RCU_PMURST);
rcu_periph_reset_disable(RCU_PMURST);
void pmu_deinit(void) {
/* reset PMU */
rcu_periph_reset_enable(RCU_PMURST);
rcu_periph_reset_disable(RCU_PMURST);
}
/*!
@@ -62,16 +61,15 @@ void pmu_deinit(void)
\param[out] none
\retval none
*/
void pmu_lvd_select(uint32_t lvdt_n)
{
/* disable LVD */
PMU_CTL &= ~PMU_CTL_LVDEN;
/* clear LVDT bits */
PMU_CTL &= ~PMU_CTL_LVDT;
/* set LVDT bits according to lvdt_n */
PMU_CTL |= lvdt_n;
/* enable LVD */
PMU_CTL |= PMU_CTL_LVDEN;
void pmu_lvd_select(uint32_t lvdt_n) {
/* disable LVD */
PMU_CTL &= ~PMU_CTL_LVDEN;
/* clear LVDT bits */
PMU_CTL &= ~PMU_CTL_LVDT;
/* set LVDT bits according to lvdt_n */
PMU_CTL |= lvdt_n;
/* enable LVD */
PMU_CTL |= PMU_CTL_LVDEN;
}
/*!
@@ -80,10 +78,9 @@ void pmu_lvd_select(uint32_t lvdt_n)
\param[out] none
\retval none
*/
void pmu_lvd_disable(void)
{
/* disable LVD */
PMU_CTL &= ~PMU_CTL_LVDEN;
void pmu_lvd_disable(void) {
/* disable LVD */
PMU_CTL &= ~PMU_CTL_LVDEN;
}
/*!
@@ -95,19 +92,18 @@ void pmu_lvd_disable(void)
\param[out] none
\retval none
*/
void pmu_to_sleepmode(uint8_t sleepmodecmd)
{
/* clear sleepdeep bit of RISC-V system control register */
__RV_CSR_CLEAR(CSR_WFE, WFE_WFE);
void pmu_to_sleepmode(uint8_t sleepmodecmd) {
/* clear sleepdeep bit of RISC-V system control register */
__RV_CSR_CLEAR(CSR_WFE, WFE_WFE);
/* select WFI or WFE command to enter sleep mode */
if(WFI_CMD == sleepmodecmd){
__WFI();
}else{
__disable_irq();
__WFE();
__enable_irq();
}
/* select WFI or WFE command to enter sleep mode */
if (WFI_CMD == sleepmodecmd) {
__WFI();
} else {
__disable_irq();
__WFE();
__enable_irq();
}
}
/*!
@@ -123,24 +119,23 @@ void pmu_to_sleepmode(uint8_t sleepmodecmd)
\param[out] none
\retval none
*/
void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd)
{
/* clear stbmod and ldolp bits */
PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP));
/* set ldolp bit according to pmu_ldo */
PMU_CTL |= ldo;
/* set CSR_SLEEPVALUE bit of RISC-V system control register */
__RV_CSR_SET(CSR_WFE, WFE_WFE);
/* select WFI or WFE command to enter deepsleep mode */
if(WFI_CMD == deepsleepmodecmd){
__WFI();
}else{
__disable_irq();
__WFE();
__enable_irq();
}
/* reset sleepdeep bit of RISC-V system control register */
__RV_CSR_CLEAR(CSR_WFE, WFE_WFE);
void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd) {
/* clear stbmod and ldolp bits */
PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP));
/* set ldolp bit according to pmu_ldo */
PMU_CTL |= ldo;
/* set CSR_SLEEPVALUE bit of RISC-V system control register */
__RV_CSR_SET(CSR_WFE, WFE_WFE);
/* select WFI or WFE command to enter deepsleep mode */
if (WFI_CMD == deepsleepmodecmd) {
__WFI();
} else {
__disable_irq();
__WFE();
__enable_irq();
}
/* reset sleepdeep bit of RISC-V system control register */
__RV_CSR_CLEAR(CSR_WFE, WFE_WFE);
}
/*!
@@ -152,26 +147,25 @@ void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd)
\param[out] none
\retval none
*/
void pmu_to_standbymode(uint8_t standbymodecmd)
{
/* set CSR_SLEEPVALUE bit of RISC-V system control register */
__RV_CSR_SET(CSR_WFE, WFE_WFE);
void pmu_to_standbymode(uint8_t standbymodecmd) {
/* set CSR_SLEEPVALUE bit of RISC-V system control register */
__RV_CSR_SET(CSR_WFE, WFE_WFE);
/* set stbmod bit */
PMU_CTL |= PMU_CTL_STBMOD;
/* set stbmod bit */
PMU_CTL |= PMU_CTL_STBMOD;
/* reset wakeup flag */
PMU_CTL |= PMU_CTL_WURST;
/* reset wakeup flag */
PMU_CTL |= PMU_CTL_WURST;
/* select WFI or WFE command to enter standby mode */
if(WFI_CMD == standbymodecmd){
__WFI();
}else{
__disable_irq();
__WFE();
__enable_irq();
}
__RV_CSR_CLEAR(CSR_WFE, WFE_WFE);
/* select WFI or WFE command to enter standby mode */
if (WFI_CMD == standbymodecmd) {
__WFI();
} else {
__disable_irq();
__WFE();
__enable_irq();
}
__RV_CSR_CLEAR(CSR_WFE, WFE_WFE);
}
/*!
@@ -180,10 +174,7 @@ void pmu_to_standbymode(uint8_t standbymodecmd)
\param[out] none
\retval none
*/
void pmu_wakeup_pin_enable(void)
{
PMU_CS |= PMU_CS_WUPEN;
}
void pmu_wakeup_pin_enable(void) { PMU_CS |= PMU_CS_WUPEN; }
/*!
\brief disable wakeup pin
@@ -191,10 +182,7 @@ void pmu_wakeup_pin_enable(void)
\param[out] none
\retval none
*/
void pmu_wakeup_pin_disable(void)
{
PMU_CS &= ~PMU_CS_WUPEN;
}
void pmu_wakeup_pin_disable(void) { PMU_CS &= ~PMU_CS_WUPEN; }
/*!
\brief enable write access to the registers in backup domain
@@ -202,10 +190,7 @@ void pmu_wakeup_pin_disable(void)
\param[out] none
\retval none
*/
void pmu_backup_write_enable(void)
{
PMU_CTL |= PMU_CTL_BKPWEN;
}
void pmu_backup_write_enable(void) { PMU_CTL |= PMU_CTL_BKPWEN; }
/*!
\brief disable write access to the registers in backup domain
@@ -213,10 +198,7 @@ void pmu_backup_write_enable(void)
\param[out] none
\retval none
*/
void pmu_backup_write_disable(void)
{
PMU_CTL &= ~PMU_CTL_BKPWEN;
}
void pmu_backup_write_disable(void) { PMU_CTL &= ~PMU_CTL_BKPWEN; }
/*!
\brief get flag state
@@ -228,13 +210,12 @@ void pmu_backup_write_disable(void)
\param[out] none
\retval FlagStatus SET or RESET
*/
FlagStatus pmu_flag_get(uint32_t flag)
{
if(PMU_CS & flag){
return SET;
}else{
return RESET;
}
FlagStatus pmu_flag_get(uint32_t flag) {
if (PMU_CS & flag) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -246,18 +227,17 @@ FlagStatus pmu_flag_get(uint32_t flag)
\param[out] none
\retval none
*/
void pmu_flag_clear(uint32_t flag_reset)
{
switch(flag_reset){
case PMU_FLAG_RESET_WAKEUP:
/* reset wakeup flag */
PMU_CTL |= PMU_CTL_WURST;
break;
case PMU_FLAG_RESET_STANDBY:
/* reset standby flag */
PMU_CTL |= PMU_CTL_STBRST;
break;
default :
break;
}
void pmu_flag_clear(uint32_t flag_reset) {
switch (flag_reset) {
case PMU_FLAG_RESET_WAKEUP:
/* reset wakeup flag */
PMU_CTL |= PMU_CTL_WURST;
break;
case PMU_FLAG_RESET_STANDBY:
/* reset standby flag */
PMU_CTL |= PMU_CTL_STBRST;
break;
default:
break;
}
}

View File

@@ -1,45 +1,45 @@
/*!
\file gd32vf103_rtc.c
\brief RTC driver
\version 2019-6-5, V1.0.0, firmware for GD32VF103
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_rtc.h"
/* RTC register high / low bits mask */
#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */
#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */
#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */
#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */
/* RTC register high bits offset */
#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U)
#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U)
/*!
\brief enter RTC configuration mode
@@ -47,10 +47,7 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void rtc_configuration_mode_enter(void)
{
RTC_CTL |= RTC_CTL_CMF;
}
void rtc_configuration_mode_enter(void) { RTC_CTL |= RTC_CTL_CMF; }
/*!
\brief exit RTC configuration mode
@@ -58,10 +55,7 @@ void rtc_configuration_mode_enter(void)
\param[out] none
\retval none
*/
void rtc_configuration_mode_exit(void)
{
RTC_CTL &= ~RTC_CTL_CMF;
}
void rtc_configuration_mode_exit(void) { RTC_CTL &= ~RTC_CTL_CMF; }
/*!
\brief set RTC counter value
@@ -69,14 +63,13 @@ void rtc_configuration_mode_exit(void)
\param[out] none
\retval none
*/
void rtc_counter_set(uint32_t cnt)
{
rtc_configuration_mode_enter();
/* set the RTC counter high bits */
RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
/* set the RTC counter low bits */
RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
rtc_configuration_mode_exit();
void rtc_counter_set(uint32_t cnt) {
rtc_configuration_mode_enter();
/* set the RTC counter high bits */
RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
/* set the RTC counter low bits */
RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
rtc_configuration_mode_exit();
}
/*!
@@ -85,14 +78,13 @@ void rtc_counter_set(uint32_t cnt)
\param[out] none
\retval none
*/
void rtc_prescaler_set(uint32_t psc)
{
rtc_configuration_mode_enter();
/* set the RTC prescaler high bits */
RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET);
/* set the RTC prescaler low bits */
RTC_PSCL = (psc & RTC_LOW_BITS_MASK);
rtc_configuration_mode_exit();
void rtc_prescaler_set(uint32_t psc) {
rtc_configuration_mode_enter();
/* set the RTC prescaler high bits */
RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET);
/* set the RTC prescaler low bits */
RTC_PSCL = (psc & RTC_LOW_BITS_MASK);
rtc_configuration_mode_exit();
}
/*!
@@ -101,11 +93,9 @@ void rtc_prescaler_set(uint32_t psc)
\param[out] none
\retval none
*/
void rtc_lwoff_wait(void)
{
/* loop until LWOFF flag is set */
while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){
}
void rtc_lwoff_wait(void) {
/* loop until LWOFF flag is set */
while (RESET == (RTC_CTL & RTC_CTL_LWOFF)) {}
}
/*!
@@ -114,13 +104,11 @@ void rtc_lwoff_wait(void)
\param[out] none
\retval none
*/
void rtc_register_sync_wait(void)
{
/* clear RSYNF flag */
RTC_CTL &= ~RTC_CTL_RSYNF;
/* loop until RSYNF flag is set */
while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){
}
void rtc_register_sync_wait(void) {
/* clear RSYNF flag */
RTC_CTL &= ~RTC_CTL_RSYNF;
/* loop until RSYNF flag is set */
while (RESET == (RTC_CTL & RTC_CTL_RSYNF)) {}
}
/*!
@@ -129,14 +117,13 @@ void rtc_register_sync_wait(void)
\param[out] none
\retval none
*/
void rtc_alarm_config(uint32_t alarm)
{
rtc_configuration_mode_enter();
/* set the alarm high bits */
RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET);
/* set the alarm low bits */
RTC_ALRML = (alarm & RTC_LOW_BITS_MASK);
rtc_configuration_mode_exit();
void rtc_alarm_config(uint32_t alarm) {
rtc_configuration_mode_enter();
/* set the alarm high bits */
RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET);
/* set the alarm low bits */
RTC_ALRML = (alarm & RTC_LOW_BITS_MASK);
rtc_configuration_mode_exit();
}
/*!
@@ -145,13 +132,12 @@ void rtc_alarm_config(uint32_t alarm)
\param[out] none
\retval RTC counter value
*/
uint32_t rtc_counter_get(void)
{
uint32_t temp = 0x0U;
temp = RTC_CNTL;
temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET);
return temp;
uint32_t rtc_counter_get(void) {
uint32_t temp = 0x0U;
temp = RTC_CNTL;
temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET);
return temp;
}
/*!
@@ -160,17 +146,16 @@ uint32_t rtc_counter_get(void)
\param[out] none
\retval RTC divider value
*/
uint32_t rtc_divider_get(void)
{
uint32_t temp = 0x00U;
temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET);
temp |= RTC_DIVL;
return temp;
uint32_t rtc_divider_get(void) {
uint32_t temp = 0x00U;
temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET);
temp |= RTC_DIVL;
return temp;
}
/*!
\brief get RTC flag status
\brief get RTC flag status
\param[in] flag: specify which flag status to get
only one parameter can be selected which is shown as below:
\arg RTC_FLAG_SECOND: second interrupt flag
@@ -181,13 +166,12 @@ uint32_t rtc_divider_get(void)
\param[out] none
\retval SET or RESET
*/
FlagStatus rtc_flag_get(uint32_t flag)
{
if(RESET != (RTC_CTL & flag)){
return SET;
}else{
return RESET;
}
FlagStatus rtc_flag_get(uint32_t flag) {
if (RESET != (RTC_CTL & flag)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -201,14 +185,13 @@ FlagStatus rtc_flag_get(uint32_t flag)
\param[out] none
\retval none
*/
void rtc_flag_clear(uint32_t flag)
{
/* clear RTC flag */
RTC_CTL &= ~flag;
void rtc_flag_clear(uint32_t flag) {
/* clear RTC flag */
RTC_CTL &= ~flag;
}
/*!
\brief get RTC interrupt flag status
\brief get RTC interrupt flag status
\param[in] flag: specify which flag status to get
only one parameter can be selected which is shown as below:
\arg RTC_INT_FLAG_SECOND: second interrupt flag
@@ -217,13 +200,12 @@ void rtc_flag_clear(uint32_t flag)
\param[out] none
\retval SET or RESET
*/
FlagStatus rtc_interrupt_flag_get(uint32_t flag)
{
if(RESET != (RTC_CTL & flag)){
return SET;
}else{
return RESET;
}
FlagStatus rtc_interrupt_flag_get(uint32_t flag) {
if (RESET != (RTC_CTL & flag)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -236,10 +218,9 @@ FlagStatus rtc_interrupt_flag_get(uint32_t flag)
\param[out] none
\retval none
*/
void rtc_interrupt_flag_clear(uint32_t flag)
{
/* clear RTC interrupt flag */
RTC_CTL &= ~flag;
void rtc_interrupt_flag_clear(uint32_t flag) {
/* clear RTC interrupt flag */
RTC_CTL &= ~flag;
}
/*!
@@ -252,10 +233,7 @@ void rtc_interrupt_flag_clear(uint32_t flag)
\param[out] none
\retval none
*/
void rtc_interrupt_enable(uint32_t interrupt)
{
RTC_INTEN |= interrupt;
}
void rtc_interrupt_enable(uint32_t interrupt) { RTC_INTEN |= interrupt; }
/*!
\brief disable RTC interrupt
@@ -267,7 +245,4 @@ void rtc_interrupt_enable(uint32_t interrupt)
\param[out] none
\retval none
*/
void rtc_interrupt_disable(uint32_t interrupt)
{
RTC_INTEN &= ~interrupt;
}
void rtc_interrupt_disable(uint32_t interrupt) { RTC_INTEN &= ~interrupt; }

View File

@@ -8,74 +8,73 @@
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_spi.h"
/* SPI/I2S parameter initialization mask */
#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */
#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */
#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */
#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */
/* I2S clock source selection, multiplication and division mask */
#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */
#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */
#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */
#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */
#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */
#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */
#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */
#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */
/* default value and offset */
#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */
#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */
#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */
#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */
#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */
#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */
/*!
\brief reset SPI and I2S
\brief reset SPI and I2S
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval none
*/
void spi_i2s_deinit(uint32_t spi_periph)
{
switch(spi_periph){
case SPI0:
/* reset SPI0 */
rcu_periph_reset_enable(RCU_SPI0RST);
rcu_periph_reset_disable(RCU_SPI0RST);
break;
case SPI1:
/* reset SPI1 and I2S1 */
rcu_periph_reset_enable(RCU_SPI1RST);
rcu_periph_reset_disable(RCU_SPI1RST);
break;
case SPI2:
/* reset SPI2 and I2S2 */
rcu_periph_reset_enable(RCU_SPI2RST);
rcu_periph_reset_disable(RCU_SPI2RST);
break;
default :
break;
}
void spi_i2s_deinit(uint32_t spi_periph) {
switch (spi_periph) {
case SPI0:
/* reset SPI0 */
rcu_periph_reset_enable(RCU_SPI0RST);
rcu_periph_reset_disable(RCU_SPI0RST);
break;
case SPI1:
/* reset SPI1 and I2S1 */
rcu_periph_reset_enable(RCU_SPI1RST);
rcu_periph_reset_disable(RCU_SPI1RST);
break;
case SPI2:
/* reset SPI2 and I2S2 */
rcu_periph_reset_enable(RCU_SPI2RST);
rcu_periph_reset_disable(RCU_SPI2RST);
break;
default:
break;
}
}
/*!
@@ -84,21 +83,20 @@ void spi_i2s_deinit(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_struct_para_init(spi_parameter_struct* spi_struct)
{
/* set the SPI struct with the default values */
spi_struct->device_mode = SPI_SLAVE;
spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
spi_struct->nss = SPI_NSS_HARD;
spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_struct->prescale = SPI_PSC_2;
void spi_struct_para_init(spi_parameter_struct *spi_struct) {
/* set the SPI struct with the default values */
spi_struct->device_mode = SPI_SLAVE;
spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
spi_struct->nss = SPI_NSS_HARD;
spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_struct->prescale = SPI_PSC_2;
}
/*!
\brief initialize SPI parameter
\param[in] spi_periph: SPIx(x=0,1,2)
\param[in] spi_struct: SPI parameter initialization stuct members of the structure
\param[in] spi_struct: SPI parameter initialization stuct members of the structure
and the member values are shown as below:
device_mode: SPI_MASTER, SPI_SLAVE
trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
@@ -112,31 +110,30 @@ void spi_struct_para_init(spi_parameter_struct* spi_struct)
\param[out] none
\retval none
*/
void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
{
uint32_t reg = 0U;
reg = SPI_CTL0(spi_periph);
reg &= SPI_INIT_MASK;
void spi_init(uint32_t spi_periph, spi_parameter_struct *spi_struct) {
uint32_t reg = 0U;
reg = SPI_CTL0(spi_periph);
reg &= SPI_INIT_MASK;
/* select SPI as master or slave */
reg |= spi_struct->device_mode;
/* select SPI transfer mode */
reg |= spi_struct->trans_mode;
/* select SPI frame size */
reg |= spi_struct->frame_size;
/* select SPI NSS use hardware or software */
reg |= spi_struct->nss;
/* select SPI LSB or MSB */
reg |= spi_struct->endian;
/* select SPI polarity and phase */
reg |= spi_struct->clock_polarity_phase;
/* select SPI prescale to adjust transmit speed */
reg |= spi_struct->prescale;
/* select SPI as master or slave */
reg |= spi_struct->device_mode;
/* select SPI transfer mode */
reg |= spi_struct->trans_mode;
/* select SPI frame size */
reg |= spi_struct->frame_size;
/* select SPI NSS use hardware or software */
reg |= spi_struct->nss;
/* select SPI LSB or MSB */
reg |= spi_struct->endian;
/* select SPI polarity and phase */
reg |= spi_struct->clock_polarity_phase;
/* select SPI prescale to adjust transmit speed */
reg |= spi_struct->prescale;
/* write to SPI_CTL0 register */
SPI_CTL0(spi_periph) = (uint32_t)reg;
/* write to SPI_CTL0 register */
SPI_CTL0(spi_periph) = (uint32_t)reg;
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
}
/*!
@@ -145,24 +142,18 @@ void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
\param[out] none
\retval none
*/
void spi_enable(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
}
void spi_enable(uint32_t spi_periph) { SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; }
/*!
\brief disable SPI
\brief disable SPI
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval none
*/
void spi_disable(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
}
void spi_disable(uint32_t spi_periph) { SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); }
/*!
\brief initialize I2S parameter
\brief initialize I2S parameter
\param[in] spi_periph: SPIx(x=1,2)
\param[in] mode: I2S operation mode
only one parameter can be selected which is shown as below:
@@ -184,27 +175,26 @@ void spi_disable(uint32_t spi_periph)
\param[out] none
\retval none
*/
void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl)
{
uint32_t reg = 0U;
reg = SPI_I2SCTL(spi_periph);
reg &= I2S_INIT_MASK;
void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl) {
uint32_t reg = 0U;
reg = SPI_I2SCTL(spi_periph);
reg &= I2S_INIT_MASK;
/* enable I2S mode */
reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
/* select I2S mode */
reg |= (uint32_t)mode;
/* select I2S standard */
reg |= (uint32_t)standard;
/* select I2S polarity */
reg |= (uint32_t)ckpl;
/* enable I2S mode */
reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
/* select I2S mode */
reg |= (uint32_t)mode;
/* select I2S standard */
reg |= (uint32_t)standard;
/* select I2S polarity */
reg |= (uint32_t)ckpl;
/* write to SPI_I2SCTL register */
SPI_I2SCTL(spi_periph) = (uint32_t)reg;
/* write to SPI_I2SCTL register */
SPI_I2SCTL(spi_periph) = (uint32_t)reg;
}
/*!
\brief configure I2S prescaler
\brief configure I2S prescaler
\param[in] spi_periph: SPIx(x=1,2)
\param[in] audiosample: I2S audio sample rate
only one parameter can be selected which is shown as below:
@@ -230,121 +220,108 @@ void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ck
\param[out] none
\retval none
*/
void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout)
{
uint32_t i2sdiv = 2U, i2sof = 0U;
uint32_t clks = 0U;
uint32_t i2sclock = 0U;
void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) {
uint32_t i2sdiv = 2U, i2sof = 0U;
uint32_t clks = 0U;
uint32_t i2sclock = 0U;
/* deinit SPI_I2SPSC register */
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
/* deinit SPI_I2SPSC register */
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
/* get the I2S clock source */
if(SPI1 == ((uint32_t)spi_periph)){
/* I2S1 clock source selection */
clks = I2S1_CLOCK_SEL;
}else{
/* I2S2 clock source selection */
clks = I2S2_CLOCK_SEL;
/* get the I2S clock source */
if (SPI1 == ((uint32_t)spi_periph)) {
/* I2S1 clock source selection */
clks = I2S1_CLOCK_SEL;
} else {
/* I2S2 clock source selection */
clks = I2S2_CLOCK_SEL;
}
if (0U != (RCU_CFG1 & clks)) {
/* get RCU PLL2 clock multiplication factor */
clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET);
if ((clks > 5U) && (clks < 15U)) {
/* multiplier is between 8 and 16 */
clks += 2U;
} else {
if (15U == clks) {
/* multiplier is 20 */
clks = 20U;
}
}
if(0U != (RCU_CFG1 & clks)){
/* get RCU PLL2 clock multiplication factor */
clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET);
if((clks > 5U) && (clks < 15U)){
/* multiplier is between 8 and 16 */
clks += 2U;
}else{
if(15U == clks){
/* multiplier is 20 */
clks = 20U;
}
}
/* get the PREDV1 value */
i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U);
/* calculate I2S clock based on PLL2 and PREDV1 */
i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
}else{
/* get system clock */
i2sclock = rcu_clock_freq_get(CK_SYS);
}
/* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
if(I2S_MCKOUT_ENABLE == mckout){
clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
}else{
if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){
clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample);
}else{
clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample);
}
}
/* remove the floating point */
clks = (clks + 5U) / 10U;
i2sof = (clks & 0x00000001U);
i2sdiv = ((clks - i2sof) / 2U);
i2sof = (i2sof << 8U);
/* get the PREDV1 value */
i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U);
/* calculate I2S clock based on PLL2 and PREDV1 */
i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
} else {
/* get system clock */
i2sclock = rcu_clock_freq_get(CK_SYS);
}
/* set the default values */
if((i2sdiv < 2U) || (i2sdiv > 255U)){
i2sdiv = 2U;
i2sof = 0U;
/* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
if (I2S_MCKOUT_ENABLE == mckout) {
clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
} else {
if (I2S_FRAMEFORMAT_DT16B_CH16B == frameformat) {
clks = (uint32_t)(((i2sclock / 32U) * 10U) / audiosample);
} else {
clks = (uint32_t)(((i2sclock / 64U) * 10U) / audiosample);
}
/* configure SPI_I2SPSC */
SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
}
/* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
/* configure data frame format */
SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
/* remove the floating point */
clks = (clks + 5U) / 10U;
i2sof = (clks & 0x00000001U);
i2sdiv = ((clks - i2sof) / 2U);
i2sof = (i2sof << 8U);
/* set the default values */
if ((i2sdiv < 2U) || (i2sdiv > 255U)) {
i2sdiv = 2U;
i2sof = 0U;
}
/* configure SPI_I2SPSC */
SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
/* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
/* configure data frame format */
SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
}
/*!
\brief enable I2S
\brief enable I2S
\param[in] spi_periph: SPIx(x=1,2)
\param[out] none
\retval none
*/
void i2s_enable(uint32_t spi_periph)
{
SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
}
void i2s_enable(uint32_t spi_periph) { SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; }
/*!
\brief disable I2S
\brief disable I2S
\param[in] spi_periph: SPIx(x=1,2)
\param[out] none
\retval none
*/
void i2s_disable(uint32_t spi_periph)
{
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
}
void i2s_disable(uint32_t spi_periph) { SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); }
/*!
\brief enable SPI NSS output
\brief enable SPI NSS output
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval none
*/
void spi_nss_output_enable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
}
void spi_nss_output_enable(uint32_t spi_periph) { SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; }
/*!
\brief disable SPI NSS output
\brief disable SPI NSS output
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval none
*/
void spi_nss_output_disable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
}
void spi_nss_output_disable(uint32_t spi_periph) { SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); }
/*!
\brief SPI NSS pin high level in software mode
@@ -352,10 +329,7 @@ void spi_nss_output_disable(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_nss_internal_high(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
}
void spi_nss_internal_high(uint32_t spi_periph) { SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; }
/*!
\brief SPI NSS pin low level in software mode
@@ -363,13 +337,10 @@ void spi_nss_internal_high(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_nss_internal_low(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
}
void spi_nss_internal_low(uint32_t spi_periph) { SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); }
/*!
\brief enable SPI DMA send or receive
\brief enable SPI DMA send or receive
\param[in] spi_periph: SPIx(x=0,1,2)
\param[in] dma: SPI DMA mode
only one parameter can be selected which is shown as below:
@@ -378,17 +349,16 @@ void spi_nss_internal_low(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
{
if(SPI_DMA_TRANSMIT == dma){
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
}else{
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
}
void spi_dma_enable(uint32_t spi_periph, uint8_t dma) {
if (SPI_DMA_TRANSMIT == dma) {
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
} else {
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
}
}
/*!
\brief disable SPI DMA send or receive
\brief disable SPI DMA send or receive
\param[in] spi_periph: SPIx(x=0,1,2)
\param[in] dma: SPI DMA mode
only one parameter can be selected which is shown as below:
@@ -397,13 +367,12 @@ void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
\param[out] none
\retval none
*/
void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
{
if(SPI_DMA_TRANSMIT == dma){
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
}else{
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
}
void spi_dma_disable(uint32_t spi_periph, uint8_t dma) {
if (SPI_DMA_TRANSMIT == dma) {
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
} else {
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
}
}
/*!
@@ -416,12 +385,11 @@ void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
\param[out] none
\retval none
*/
void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
{
/* clear SPI_CTL0_FF16 bit */
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
/* configure SPI_CTL0_FF16 bit */
SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) {
/* clear SPI_CTL0_FF16 bit */
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
/* configure SPI_CTL0_FF16 bit */
SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
}
/*!
@@ -431,10 +399,7 @@ void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format
\param[out] none
\retval none
*/
void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
{
SPI_DATA(spi_periph) = (uint32_t)data;
}
void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) { SPI_DATA(spi_periph) = (uint32_t)data; }
/*!
\brief SPI receive data
@@ -442,10 +407,7 @@ void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
\param[out] none
\retval 16-bit data
*/
uint16_t spi_i2s_data_receive(uint32_t spi_periph)
{
return ((uint16_t)SPI_DATA(spi_periph));
}
uint16_t spi_i2s_data_receive(uint32_t spi_periph) { return ((uint16_t)SPI_DATA(spi_periph)); }
/*!
\brief configure SPI bidirectional transfer direction
@@ -457,65 +419,54 @@ uint16_t spi_i2s_data_receive(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
{
if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){
/* set the transmit-only mode */
SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
}else{
/* set the receive-only mode */
SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
}
void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) {
if (SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction) {
/* set the transmit-only mode */
SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
} else {
/* set the receive-only mode */
SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
}
}
/*!
\brief set SPI CRC polynomial
\brief set SPI CRC polynomial
\param[in] spi_periph: SPIx(x=0,1,2)
\param[in] crc_poly: CRC polynomial value
\param[out] none
\retval none
*/
void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly)
{
/* enable SPI CRC */
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly) {
/* enable SPI CRC */
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
/* set SPI CRC polynomial */
SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
/* set SPI CRC polynomial */
SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
}
/*!
\brief get SPI CRC polynomial
\brief get SPI CRC polynomial
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval 16-bit CRC polynomial
*/
uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
{
return ((uint16_t)SPI_CRCPOLY(spi_periph));
}
uint16_t spi_crc_polynomial_get(uint32_t spi_periph) { return ((uint16_t)SPI_CRCPOLY(spi_periph)); }
/*!
\brief turn on CRC function
\brief turn on CRC function
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval none
*/
void spi_crc_on(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
}
void spi_crc_on(uint32_t spi_periph) { SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; }
/*!
\brief turn off CRC function
\brief turn off CRC function
\param[in] spi_periph: SPIx(x=0,1,2)
\param[out] none
\retval none
*/
void spi_crc_off(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
}
void spi_crc_off(uint32_t spi_periph) { SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); }
/*!
\brief SPI next data is CRC value
@@ -523,10 +474,7 @@ void spi_crc_off(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_crc_next(uint32_t spi_periph)
{
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
}
void spi_crc_next(uint32_t spi_periph) { SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; }
/*!
\brief get SPI CRC send value or receive value
@@ -538,13 +486,12 @@ void spi_crc_next(uint32_t spi_periph)
\param[out] none
\retval 16-bit CRC value
*/
uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc)
{
if(SPI_CRC_TX == crc){
return ((uint16_t)(SPI_TCRC(spi_periph)));
}else{
return ((uint16_t)(SPI_RCRC(spi_periph)));
}
uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc) {
if (SPI_CRC_TX == crc) {
return ((uint16_t)(SPI_TCRC(spi_periph)));
} else {
return ((uint16_t)(SPI_RCRC(spi_periph)));
}
}
/*!
@@ -553,10 +500,7 @@ uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc)
\param[out] none
\retval none
*/
void spi_ti_mode_enable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD;
}
void spi_ti_mode_enable(uint32_t spi_periph) { SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD; }
/*!
\brief disable SPI TI mode
@@ -564,10 +508,7 @@ void spi_ti_mode_enable(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_ti_mode_disable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD);
}
void spi_ti_mode_disable(uint32_t spi_periph) { SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD); }
/*!
\brief enable SPI NSS pulse mode
@@ -575,10 +516,7 @@ void spi_ti_mode_disable(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_nssp_mode_enable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
}
void spi_nssp_mode_enable(uint32_t spi_periph) { SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP; }
/*!
\brief disable SPI NSS pulse mode
@@ -586,14 +524,10 @@ void spi_nssp_mode_enable(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_nssp_mode_disable(uint32_t spi_periph)
{
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
}
void spi_nssp_mode_disable(uint32_t spi_periph) { SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP); }
/*!
\brief enable SPI and I2S interrupt
\brief enable SPI and I2S interrupt
\param[in] spi_periph: SPIx(x=0,1,2)
\param[in] interrupt: SPI/I2S interrupt
only one parameter can be selected which is shown as below:
@@ -604,28 +538,27 @@ void spi_nssp_mode_disable(uint32_t spi_periph)
\param[out] none
\retval none
*/
void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
{
switch(interrupt){
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_TBE:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_RBNE:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
break;
/* SPI/I2S error */
case SPI_I2S_INT_ERR:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
break;
default:
break;
}
void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) {
switch (interrupt) {
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_TBE:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_RBNE:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
break;
/* SPI/I2S error */
case SPI_I2S_INT_ERR:
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
break;
default:
break;
}
}
/*!
\brief disable SPI and I2S interrupt
\brief disable SPI and I2S interrupt
\param[in] spi_periph: SPIx(x=0,1,2)
\param[in] interrupt: SPI/I2S interrupt
only one parameter can be selected which is shown as below:
@@ -636,24 +569,23 @@ void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
\param[out] none
\retval none
*/
void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
{
switch(interrupt){
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_TBE:
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_RBNE:
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
break;
/* SPI/I2S error */
case SPI_I2S_INT_ERR:
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
break;
default:
break;
}
void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) {
switch (interrupt) {
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_TBE:
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_RBNE:
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
break;
/* SPI/I2S error */
case SPI_I2S_INT_ERR:
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
break;
default:
break;
}
}
/*!
@@ -671,56 +603,55 @@ void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
{
uint32_t reg1 = SPI_STAT(spi_periph);
uint32_t reg2 = SPI_CTL1(spi_periph);
FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) {
uint32_t reg1 = SPI_STAT(spi_periph);
uint32_t reg2 = SPI_CTL1(spi_periph);
switch(interrupt){
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_FLAG_TBE:
reg1 = reg1 & SPI_STAT_TBE;
reg2 = reg2 & SPI_CTL1_TBEIE;
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_FLAG_RBNE:
reg1 = reg1 & SPI_STAT_RBNE;
reg2 = reg2 & SPI_CTL1_RBNEIE;
break;
/* SPI/I2S overrun interrupt */
case SPI_I2S_INT_FLAG_RXORERR:
reg1 = reg1 & SPI_STAT_RXORERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI config error interrupt */
case SPI_INT_FLAG_CONFERR:
reg1 = reg1 & SPI_STAT_CONFERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI CRC error interrupt */
case SPI_INT_FLAG_CRCERR:
reg1 = reg1 & SPI_STAT_CRCERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* I2S underrun error interrupt */
case I2S_INT_FLAG_TXURERR:
reg1 = reg1 & SPI_STAT_TXURERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI/I2S format error interrupt */
case SPI_I2S_INT_FLAG_FERR:
reg1 = reg1 & SPI_STAT_FERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
default:
break;
}
/* get SPI/I2S interrupt flag status */
if((0U != reg1) && (0U != reg2)){
return SET;
}else{
return RESET;
}
switch (interrupt) {
/* SPI/I2S transmit buffer empty interrupt */
case SPI_I2S_INT_FLAG_TBE:
reg1 = reg1 & SPI_STAT_TBE;
reg2 = reg2 & SPI_CTL1_TBEIE;
break;
/* SPI/I2S receive buffer not empty interrupt */
case SPI_I2S_INT_FLAG_RBNE:
reg1 = reg1 & SPI_STAT_RBNE;
reg2 = reg2 & SPI_CTL1_RBNEIE;
break;
/* SPI/I2S overrun interrupt */
case SPI_I2S_INT_FLAG_RXORERR:
reg1 = reg1 & SPI_STAT_RXORERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI config error interrupt */
case SPI_INT_FLAG_CONFERR:
reg1 = reg1 & SPI_STAT_CONFERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI CRC error interrupt */
case SPI_INT_FLAG_CRCERR:
reg1 = reg1 & SPI_STAT_CRCERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* I2S underrun error interrupt */
case I2S_INT_FLAG_TXURERR:
reg1 = reg1 & SPI_STAT_TXURERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
/* SPI/I2S format error interrupt */
case SPI_I2S_INT_FLAG_FERR:
reg1 = reg1 & SPI_STAT_FERR;
reg2 = reg2 & SPI_CTL1_ERRIE;
break;
default:
break;
}
/* get SPI/I2S interrupt flag status */
if ((0U != reg1) && (0U != reg2)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -745,13 +676,12 @@ FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
{
if(RESET != (SPI_STAT(spi_periph) & flag)){
return SET;
}else{
return RESET;
}
FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) {
if (RESET != (SPI_STAT(spi_periph) & flag)) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -760,7 +690,4 @@ FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
\param[out] none
\retval none
*/
void spi_crc_error_clear(uint32_t spi_periph)
{
SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR);
}
void spi_crc_error_clear(uint32_t spi_periph) { SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); }

View File

@@ -35,42 +35,41 @@ OF SUCH DAMAGE.
#include "gd32vf103_usart.h"
/*!
\brief reset USART/UART
\brief reset USART/UART
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
\param[out] none
\retval none
*/
void usart_deinit(uint32_t usart_periph)
{
switch(usart_periph){
case USART0:
/* reset USART0 */
rcu_periph_reset_enable(RCU_USART0RST);
rcu_periph_reset_disable(RCU_USART0RST);
break;
case USART1:
/* reset USART1 */
rcu_periph_reset_enable(RCU_USART1RST);
rcu_periph_reset_disable(RCU_USART1RST);
break;
case USART2:
/* reset USART2 */
rcu_periph_reset_enable(RCU_USART2RST);
rcu_periph_reset_disable(RCU_USART2RST);
break;
case UART3:
/* reset UART3 */
rcu_periph_reset_enable(RCU_UART3RST);
rcu_periph_reset_disable(RCU_UART3RST);
break;
case UART4:
/* reset UART4 */
rcu_periph_reset_enable(RCU_UART4RST);
rcu_periph_reset_disable(RCU_UART4RST);
break;
default:
break;
}
void usart_deinit(uint32_t usart_periph) {
switch (usart_periph) {
case USART0:
/* reset USART0 */
rcu_periph_reset_enable(RCU_USART0RST);
rcu_periph_reset_disable(RCU_USART0RST);
break;
case USART1:
/* reset USART1 */
rcu_periph_reset_enable(RCU_USART1RST);
rcu_periph_reset_disable(RCU_USART1RST);
break;
case USART2:
/* reset USART2 */
rcu_periph_reset_enable(RCU_USART2RST);
rcu_periph_reset_disable(RCU_USART2RST);
break;
case UART3:
/* reset UART3 */
rcu_periph_reset_enable(RCU_UART3RST);
rcu_periph_reset_disable(RCU_UART3RST);
break;
case UART4:
/* reset UART4 */
rcu_periph_reset_enable(RCU_UART4RST);
rcu_periph_reset_disable(RCU_UART4RST);
break;
default:
break;
}
}
/*!
@@ -79,40 +78,39 @@ void usart_deinit(uint32_t usart_periph)
\param[in] baudval: baud rate value
\param[out] none
\retval none
*/
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
{
uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U;
switch(usart_periph){
/* get clock frequency */
case USART0:
/* get USART0 clock */
uclk=rcu_clock_freq_get(CK_APB2);
break;
case USART1:
/* get USART1 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
case USART2:
/* get USART2 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
case UART3:
/* get UART3 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
case UART4:
/* get UART4 clock */
uclk=rcu_clock_freq_get(CK_APB1);
break;
default:
break;
}
/* oversampling by 16, configure the value of USART_BAUD */
udiv = (uclk+baudval/2U)/baudval;
intdiv = udiv & (0x0000fff0U);
fradiv = udiv & (0x0000000fU);
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
*/
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) {
uint32_t uclk = 0U, intdiv = 0U, fradiv = 0U, udiv = 0U;
switch (usart_periph) {
/* get clock frequency */
case USART0:
/* get USART0 clock */
uclk = rcu_clock_freq_get(CK_APB2);
break;
case USART1:
/* get USART1 clock */
uclk = rcu_clock_freq_get(CK_APB1);
break;
case USART2:
/* get USART2 clock */
uclk = rcu_clock_freq_get(CK_APB1);
break;
case UART3:
/* get UART3 clock */
uclk = rcu_clock_freq_get(CK_APB1);
break;
case UART4:
/* get UART4 clock */
uclk = rcu_clock_freq_get(CK_APB1);
break;
default:
break;
}
/* oversampling by 16, configure the value of USART_BAUD */
udiv = (uclk + baudval / 2U) / baudval;
intdiv = udiv & (0x0000fff0U);
fradiv = udiv & (0x0000000fU);
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
}
/*!
@@ -122,16 +120,15 @@ void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
only one parameter can be selected which is shown as below:
\arg USART_PM_NONE: no parity
\arg USART_PM_ODD: odd parity
\arg USART_PM_EVEN: even parity
\arg USART_PM_EVEN: even parity
\param[out] none
\retval none
*/
void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
{
/* clear USART_CTL0 PM,PCEN bits */
USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN);
/* configure USART parity mode */
USART_CTL0(usart_periph) |= paritycfg ;
void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) {
/* clear USART_CTL0 PM,PCEN bits */
USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN);
/* configure USART parity mode */
USART_CTL0(usart_periph) |= paritycfg;
}
/*!
@@ -144,12 +141,11 @@ void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
\param[out] none
\retval none
*/
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
{
/* clear USART_CTL0 WL bit */
USART_CTL0(usart_periph) &= ~USART_CTL0_WL;
/* configure USART word length */
USART_CTL0(usart_periph) |= wlen;
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) {
/* clear USART_CTL0 WL bit */
USART_CTL0(usart_periph) &= ~USART_CTL0_WL;
/* configure USART word length */
USART_CTL0(usart_periph) |= wlen;
}
/*!
@@ -164,12 +160,11 @@ void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
\param[out] none
\retval none
*/
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
{
/* clear USART_CTL1 STB bits */
USART_CTL1(usart_periph) &= ~USART_CTL1_STB;
/* configure USART stop bits */
USART_CTL1(usart_periph) |= stblen;
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) {
/* clear USART_CTL1 STB bits */
USART_CTL1(usart_periph) &= ~USART_CTL1_STB;
/* configure USART stop bits */
USART_CTL1(usart_periph) |= stblen;
}
/*!
@@ -178,10 +173,7 @@ void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
\param[out] none
\retval none
*/
void usart_enable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) |= USART_CTL0_UEN;
}
void usart_enable(uint32_t usart_periph) { USART_CTL0(usart_periph) |= USART_CTL0_UEN; }
/*!
\brief disable USART
@@ -189,10 +181,7 @@ void usart_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_disable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN);
}
void usart_disable(uint32_t usart_periph) { USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); }
/*!
\brief configure USART transmitter
@@ -204,15 +193,14 @@ void usart_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
{
uint32_t ctl = 0U;
ctl = USART_CTL0(usart_periph);
ctl &= ~USART_CTL0_TEN;
ctl |= txconfig;
/* configure transfer mode */
USART_CTL0(usart_periph) = ctl;
void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) {
uint32_t ctl = 0U;
ctl = USART_CTL0(usart_periph);
ctl &= ~USART_CTL0_TEN;
ctl |= txconfig;
/* configure transfer mode */
USART_CTL0(usart_periph) = ctl;
}
/*!
@@ -225,28 +213,24 @@ void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
\param[out] none
\retval none
*/
void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig)
{
uint32_t ctl = 0U;
ctl = USART_CTL0(usart_periph);
ctl &= ~USART_CTL0_REN;
ctl |= rxconfig;
/* configure receiver mode */
USART_CTL0(usart_periph) = ctl;
void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) {
uint32_t ctl = 0U;
ctl = USART_CTL0(usart_periph);
ctl &= ~USART_CTL0_REN;
ctl |= rxconfig;
/* configure receiver mode */
USART_CTL0(usart_periph) = ctl;
}
/*!
\brief USART transmit data function
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
\param[in] data: data of transmission
\param[in] data: data of transmission
\param[out] none
\retval none
*/
void usart_data_transmit(uint32_t usart_periph, uint32_t data)
{
USART_DATA(usart_periph) = USART_DATA_DATA & data;
}
void usart_data_transmit(uint32_t usart_periph, uint32_t data) { USART_DATA(usart_periph) = USART_DATA_DATA & data; }
/*!
\brief USART receive data function
@@ -254,10 +238,7 @@ void usart_data_transmit(uint32_t usart_periph, uint32_t data)
\param[out] none
\retval data of received
*/
uint16_t usart_data_receive(uint32_t usart_periph)
{
return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U));
}
uint16_t usart_data_receive(uint32_t usart_periph) { return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); }
/*!
\brief configure the address of the USART in wake up by address match mode
@@ -266,10 +247,9 @@ uint16_t usart_data_receive(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_address_config(uint32_t usart_periph, uint8_t addr)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR);
USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr);
void usart_address_config(uint32_t usart_periph, uint8_t addr) {
USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR);
USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr);
}
/*!
@@ -278,10 +258,7 @@ void usart_address_config(uint32_t usart_periph, uint8_t addr)
\param[out] none
\retval none
*/
void usart_mute_mode_enable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) |= USART_CTL0_RWU;
}
void usart_mute_mode_enable(uint32_t usart_periph) { USART_CTL0(usart_periph) |= USART_CTL0_RWU; }
/*!
\brief receiver in active mode
@@ -289,10 +266,7 @@ void usart_mute_mode_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_mute_mode_disable(uint32_t usart_periph)
{
USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU);
}
void usart_mute_mode_disable(uint32_t usart_periph) { USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); }
/*!
\brief configure wakeup method in mute mode
@@ -304,10 +278,9 @@ void usart_mute_mode_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod)
{
USART_CTL0(usart_periph) &= ~(USART_CTL0_WM);
USART_CTL0(usart_periph) |= wmethod;
void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) {
USART_CTL0(usart_periph) &= ~(USART_CTL0_WM);
USART_CTL0(usart_periph) |= wmethod;
}
/*!
@@ -316,10 +289,7 @@ void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod)
\param[out] none
\retval none
*/
void usart_lin_mode_enable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) |= USART_CTL1_LMEN;
}
void usart_lin_mode_enable(uint32_t usart_periph) { USART_CTL1(usart_periph) |= USART_CTL1_LMEN; }
/*!
\brief disable LIN mode
@@ -327,10 +297,7 @@ void usart_lin_mode_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_lin_mode_disable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN);
}
void usart_lin_mode_disable(uint32_t usart_periph) { USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); }
/*!
\brief configure lin break frame length
@@ -342,10 +309,9 @@ void usart_lin_mode_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN);
USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen);
void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) {
USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN);
USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen);
}
/*!
@@ -354,10 +320,7 @@ void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lbl
\param[out] none
\retval none
*/
void usart_send_break(uint32_t usart_periph)
{
USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD;
}
void usart_send_break(uint32_t usart_periph) { USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; }
/*!
\brief enable half duplex mode
@@ -365,10 +328,7 @@ void usart_send_break(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_halfduplex_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_HDEN;
}
void usart_halfduplex_enable(uint32_t usart_periph) { USART_CTL2(usart_periph) |= USART_CTL2_HDEN; }
/*!
\brief disable half duplex mode
@@ -376,10 +336,7 @@ void usart_halfduplex_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_halfduplex_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN);
}
void usart_halfduplex_disable(uint32_t usart_periph) { USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); }
/*!
\brief enable CK pin in synchronous mode
@@ -387,10 +344,7 @@ void usart_halfduplex_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_synchronous_clock_enable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) |= USART_CTL1_CKEN;
}
void usart_synchronous_clock_enable(uint32_t usart_periph) { USART_CTL1(usart_periph) |= USART_CTL1_CKEN; }
/*!
\brief disable CK pin in synchronous mode
@@ -398,40 +352,36 @@ void usart_synchronous_clock_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_synchronous_clock_disable(uint32_t usart_periph)
{
USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN);
}
void usart_synchronous_clock_disable(uint32_t usart_periph) { USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); }
/*!
\brief configure USART synchronous mode parameters
\param[in] usart_periph: USARTx(x=0,1,2)
\param[in] clen: CK length
only one parameter can be selected which is shown as below:
\arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame
\arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame
\arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame
\param[in] cph: clock phase
only one parameter can be selected which is shown as below:
\arg USART_CPH_1CK: first clock transition is the first data capture edge
\arg USART_CPH_1CK: first clock transition is the first data capture edge
\arg USART_CPH_2CK: second clock transition is the first data capture edge
\param[in] cpl: clock polarity
only one parameter can be selected which is shown as below:
\arg USART_CPL_LOW: steady low value on CK pin
\arg USART_CPL_LOW: steady low value on CK pin
\arg USART_CPL_HIGH: steady high value on CK pin
\param[out] none
\retval none
*/
void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl)
{
uint32_t ctl = 0U;
/* read USART_CTL1 register */
ctl = USART_CTL1(usart_periph);
ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL);
/* set CK length, CK phase, CK polarity */
ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl);
void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) {
uint32_t ctl = 0U;
USART_CTL1(usart_periph) = ctl;
/* read USART_CTL1 register */
ctl = USART_CTL1(usart_periph);
ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL);
/* set CK length, CK phase, CK polarity */
ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl);
USART_CTL1(usart_periph) = ctl;
}
/*!
@@ -441,10 +391,9 @@ void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32
\param[out] none
\retval none
*/
void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut)
{
USART_GP(usart_periph) &= ~(USART_GP_GUAT);
USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut)<<8));
void usart_guard_time_config(uint32_t usart_periph, uint32_t gaut) {
USART_GP(usart_periph) &= ~(USART_GP_GUAT);
USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut) << 8));
}
/*!
@@ -453,10 +402,7 @@ void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut)
\param[out] none
\retval none
*/
void usart_smartcard_mode_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_SCEN;
}
void usart_smartcard_mode_enable(uint32_t usart_periph) { USART_CTL2(usart_periph) |= USART_CTL2_SCEN; }
/*!
\brief disable smartcard mode
@@ -464,10 +410,7 @@ void usart_smartcard_mode_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_smartcard_mode_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN);
}
void usart_smartcard_mode_disable(uint32_t usart_periph) { USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); }
/*!
\brief enable NACK in smartcard mode
@@ -475,10 +418,7 @@ void usart_smartcard_mode_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_smartcard_mode_nack_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_NKEN;
}
void usart_smartcard_mode_nack_enable(uint32_t usart_periph) { USART_CTL2(usart_periph) |= USART_CTL2_NKEN; }
/*!
\brief disable NACK in smartcard mode
@@ -486,10 +426,7 @@ void usart_smartcard_mode_nack_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_smartcard_mode_nack_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN);
}
void usart_smartcard_mode_nack_disable(uint32_t usart_periph) { USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); }
/*!
\brief enable IrDA mode
@@ -497,10 +434,7 @@ void usart_smartcard_mode_nack_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_irda_mode_enable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) |= USART_CTL2_IREN;
}
void usart_irda_mode_enable(uint32_t usart_periph) { USART_CTL2(usart_periph) |= USART_CTL2_IREN; }
/*!
\brief disable IrDA mode
@@ -508,10 +442,7 @@ void usart_irda_mode_enable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_irda_mode_disable(uint32_t usart_periph)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN);
}
void usart_irda_mode_disable(uint32_t usart_periph) { USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); }
/*!
\brief configure the peripheral clock prescaler in USART IrDA low-power mode
@@ -520,10 +451,9 @@ void usart_irda_mode_disable(uint32_t usart_periph)
\param[out] none
\retval none
*/
void usart_prescaler_config(uint32_t usart_periph, uint8_t psc)
{
USART_GP(usart_periph) &= ~(USART_GP_PSC);
USART_GP(usart_periph) |= psc;
void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) {
USART_GP(usart_periph) &= ~(USART_GP_PSC);
USART_GP(usart_periph) |= psc;
}
/*!
@@ -536,10 +466,9 @@ void usart_prescaler_config(uint32_t usart_periph, uint8_t psc)
\param[out] none
\retval none
*/
void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp)
{
USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP);
USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp);
void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) {
USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP);
USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp);
}
/*!
@@ -552,15 +481,14 @@ void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp)
\param[out] none
\retval none
*/
void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
{
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_RTSEN;
ctl |= rtsconfig;
/* configure RTS */
USART_CTL2(usart_periph) = ctl;
void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) {
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_RTSEN;
ctl |= rtsconfig;
/* configure RTS */
USART_CTL2(usart_periph) = ctl;
}
/*!
@@ -573,15 +501,14 @@ void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
\param[out] none
\retval none
*/
void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
{
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_CTSEN;
ctl |= ctsconfig;
/* configure CTS */
USART_CTL2(usart_periph) = ctl;
void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) {
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_CTSEN;
ctl |= ctsconfig;
/* configure CTS */
USART_CTL2(usart_periph) = ctl;
}
/*!
@@ -594,15 +521,14 @@ void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
\param[out] none
\retval none
*/
void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd)
{
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_DENR;
ctl |= dmacmd;
/* configure DMA reception */
USART_CTL2(usart_periph) = ctl;
void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) {
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_DENR;
ctl |= dmacmd;
/* configure DMA reception */
USART_CTL2(usart_periph) = ctl;
}
/*!
@@ -615,15 +541,14 @@ void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd)
\param[out] none
\retval none
*/
void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd)
{
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_DENT;
ctl |= dmacmd;
/* configure DMA transmission */
USART_CTL2(usart_periph) = ctl;
void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) {
uint32_t ctl = 0U;
ctl = USART_CTL2(usart_periph);
ctl &= ~USART_CTL2_DENT;
ctl |= dmacmd;
/* configure DMA transmission */
USART_CTL2(usart_periph) = ctl;
}
/*!
@@ -632,25 +557,24 @@ void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd)
\param[in] flag: USART flags, refer to usart_flag_enum
only one parameter can be selected which is shown as below:
\arg USART_FLAG_CTSF: CTS change flag
\arg USART_FLAG_LBDF: LIN break detected flag
\arg USART_FLAG_TBE: transmit data buffer empty
\arg USART_FLAG_TC: transmission complete
\arg USART_FLAG_RBNE: read data buffer not empty
\arg USART_FLAG_IDLEF: IDLE frame detected flag
\arg USART_FLAG_ORERR: overrun error
\arg USART_FLAG_NERR: noise error flag
\arg USART_FLAG_FERR: frame error flag
\arg USART_FLAG_PERR: parity error flag
\arg USART_FLAG_LBDF: LIN break detected flag
\arg USART_FLAG_TBE: transmit data buffer empty
\arg USART_FLAG_TC: transmission complete
\arg USART_FLAG_RBNE: read data buffer not empty
\arg USART_FLAG_IDLEF: IDLE frame detected flag
\arg USART_FLAG_ORERR: overrun error
\arg USART_FLAG_NERR: noise error flag
\arg USART_FLAG_FERR: frame error flag
\arg USART_FLAG_PERR: parity error flag
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
{
if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){
return SET;
}else{
return RESET;
}
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) {
if (RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -665,10 +589,7 @@ FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
\param[out] none
\retval none
*/
void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag)
{
USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag));
}
void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) { USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); }
/*!
\brief enable USART interrupt
@@ -686,10 +607,7 @@ void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag)
\param[out] none
\retval none
*/
void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag)
{
USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag));
}
void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) { USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag)); }
/*!
\brief disable USART interrupt
@@ -707,10 +625,7 @@ void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag)
\param[out] none
\retval none
*/
void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag)
{
USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag));
}
void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) { USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag)); }
/*!
\brief get USART interrupt and flag status
@@ -731,19 +646,18 @@ void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag)
{
uint32_t intenable = 0U, flagstatus = 0U;
/* get the interrupt enable bit status */
intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag)));
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) {
uint32_t intenable = 0U, flagstatus = 0U;
/* get the interrupt enable bit status */
intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag)));
/* get the corresponding flag bit status */
flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag)));
if(flagstatus && intenable){
return SET;
}else{
return RESET;
}
if (flagstatus && intenable) {
return SET;
} else {
return RESET;
}
}
/*!
@@ -758,24 +672,18 @@ FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag)
\param[out] none
\retval none
*/
void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag)
{
USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag));
void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag) { USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); }
int usart_write(uint32_t usart_periph, int ch) {
usart_data_transmit(usart_periph, (uint8_t)ch);
while (usart_flag_get(usart_periph, USART_FLAG_TBE) == RESET) {}
return ch;
}
int usart_write(uint32_t usart_periph,int ch)
{
usart_data_transmit(usart_periph, (uint8_t) ch );
while (usart_flag_get(usart_periph, USART_FLAG_TBE)== RESET){
}
return ch;
}
uint8_t usart_read(uint32_t usart_periph)
{
/* loop until RBNE = 1 */
while (usart_flag_get(usart_periph, USART_FLAG_RBNE) == RESET);
return(usart_data_receive(usart_periph));
uint8_t usart_read(uint32_t usart_periph) {
/* loop until RBNE = 1 */
while (usart_flag_get(usart_periph, USART_FLAG_RBNE) == RESET)
;
return (usart_data_receive(usart_periph));
}

View File

@@ -1,43 +1,43 @@
/*!
\file gd32vf103_wwdgt.c
\brief WWDGT driver
\version 2019-6-5, V1.0.0, firmware for GD32VF103
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32vf103_wwdgt.h"
/* write value to WWDGT_CTL_CNT bit field */
#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0))
#define CTL_CNT(regval) (BITS(0, 6) & ((uint32_t)(regval) << 0))
/* write value to WWDGT_CFG_WIN bit field */
#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0))
#define CFG_WIN(regval) (BITS(0, 6) & ((uint32_t)(regval) << 0))
/*!
\brief reset the window watchdog timer configuration
@@ -45,10 +45,9 @@ OF SUCH DAMAGE.
\param[out] none
\retval none
*/
void wwdgt_deinit(void)
{
rcu_periph_reset_enable(RCU_WWDGTRST);
rcu_periph_reset_disable(RCU_WWDGTRST);
void wwdgt_deinit(void) {
rcu_periph_reset_enable(RCU_WWDGTRST);
rcu_periph_reset_disable(RCU_WWDGTRST);
}
/*!
@@ -57,10 +56,7 @@ void wwdgt_deinit(void)
\param[out] none
\retval none
*/
void wwdgt_enable(void)
{
WWDGT_CTL |= WWDGT_CTL_WDGTEN;
}
void wwdgt_enable(void) { WWDGT_CTL |= WWDGT_CTL_WDGTEN; }
/*!
\brief configure the window watchdog timer counter value
@@ -68,19 +64,18 @@ void wwdgt_enable(void)
\param[out] none
\retval none
*/
void wwdgt_counter_update(uint16_t counter_value)
{
uint32_t reg = 0U;
reg = (WWDGT_CTL & (~WWDGT_CTL_CNT));
reg |= CTL_CNT(counter_value);
WWDGT_CTL = reg;
void wwdgt_counter_update(uint16_t counter_value) {
uint32_t reg = 0U;
reg = (WWDGT_CTL & (~WWDGT_CTL_CNT));
reg |= CTL_CNT(counter_value);
WWDGT_CTL = reg;
}
/*!
\brief configure counter value, window value, and prescaler divider value
\param[in] counter: 0x00 - 0x7F
\brief configure counter value, window value, and prescaler divider value
\param[in] counter: 0x00 - 0x7F
\param[in] window: 0x00 - 0x7F
\param[in] prescaler: wwdgt prescaler value
only one parameter can be selected which is shown as below:
@@ -91,21 +86,20 @@ void wwdgt_counter_update(uint16_t counter_value)
\param[out] none
\retval none
*/
void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
{
uint32_t reg_cfg = 0U, reg_ctl = 0U;
void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) {
uint32_t reg_cfg = 0U, reg_ctl = 0U;
/* clear WIN and PSC bits, clear CNT bit */
reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC)));
reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT));
/* configure WIN and PSC bits, configure CNT bit */
reg_cfg |= CFG_WIN(window);
reg_cfg |= prescaler;
reg_ctl |= CTL_CNT(counter);
WWDGT_CTL = reg_ctl;
WWDGT_CFG = reg_cfg;
/* clear WIN and PSC bits, clear CNT bit */
reg_cfg = (WWDGT_CFG & (~(WWDGT_CFG_WIN | WWDGT_CFG_PSC)));
reg_ctl = (WWDGT_CTL & (~WWDGT_CTL_CNT));
/* configure WIN and PSC bits, configure CNT bit */
reg_cfg |= CFG_WIN(window);
reg_cfg |= prescaler;
reg_ctl |= CTL_CNT(counter);
WWDGT_CTL = reg_ctl;
WWDGT_CFG = reg_cfg;
}
/*!
@@ -114,10 +108,7 @@ void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
\param[out] none
\retval none
*/
void wwdgt_interrupt_enable(void)
{
WWDGT_CFG |= WWDGT_CFG_EWIE;
}
void wwdgt_interrupt_enable(void) { WWDGT_CFG |= WWDGT_CFG_EWIE; }
/*!
\brief check early wakeup interrupt state of WWDGT
@@ -125,13 +116,12 @@ void wwdgt_interrupt_enable(void)
\param[out] none
\retval FlagStatus: SET or RESET
*/
FlagStatus wwdgt_flag_get(void)
{
if(WWDGT_STAT & WWDGT_STAT_EWIF){
return SET;
}
FlagStatus wwdgt_flag_get(void) {
if (WWDGT_STAT & WWDGT_STAT_EWIF) {
return SET;
}
return RESET;
return RESET;
}
/*!
@@ -140,7 +130,4 @@ FlagStatus wwdgt_flag_get(void)
\param[out] none
\retval none
*/
void wwdgt_flag_clear(void)
{
WWDGT_STAT &= (~WWDGT_STAT_EWIF);
}
void wwdgt_flag_clear(void) { WWDGT_STAT &= (~WWDGT_STAT_EWIF); }

View File

@@ -1,7 +1,4 @@
#include <errno.h>
#include "stub.h"
#include <errno.h>
int _close(int fd)
{
return _stub(EBADF);
}
int _close(int fd) { return _stub(EBADF); }

View File

@@ -1,9 +1,6 @@
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include "stub.h"
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
int _fstat(int fd, struct stat* st)
{
return _stub(EBADF);
}
int _fstat(int fd, struct stat *st) { return _stub(EBADF); }

View File

@@ -1,14 +1,13 @@
#include "nuclei_sdk_soc.h"
#include <errno.h>
#include <sys/time.h>
#include "nuclei_sdk_soc.h"
int _gettimeofday(struct timeval *tp, void *tzp)
{
uint64_t cycles;
int _gettimeofday(struct timeval *tp, void *tzp) {
uint64_t cycles;
cycles = __get_rv_cycle();
cycles = __get_rv_cycle();
tp->tv_sec = cycles / SystemCoreClock;
tp->tv_usec = (cycles % SystemCoreClock) * 1000000 / SystemCoreClock;
return 0;
tp->tv_sec = cycles / SystemCoreClock;
tp->tv_usec = (cycles % SystemCoreClock) * 1000000 / SystemCoreClock;
return 0;
}

View File

@@ -2,11 +2,10 @@
#include <unistd.h>
int _isatty(int fd)
{
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
return 1;
}
return 0;
int _isatty(int fd) {
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
return 1;
}
return 0;
}

View File

@@ -1,9 +1,6 @@
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "stub.h"
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
off_t _lseek(int fd, off_t ptr, int dir)
{
return _stub(EBADF);
}
off_t _lseek(int fd, off_t ptr, int dir) { return _stub(EBADF); }

View File

@@ -1,12 +1,10 @@
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "nuclei_sdk_hal.h"
#include "gd32vf103_usart.h"
#include "nuclei_sdk_hal.h"
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
// #define UART_AUTO_ECHO
ssize_t _read(int fd, void* ptr, size_t len) {
return -1;
}
ssize_t _read(int fd, void *ptr, size_t len) { return -1; }

View File

@@ -1,19 +1,18 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
void *_sbrk(ptrdiff_t incr)
{
extern char _end[];
extern char _heap_end[];
static char *curbrk = _end;
void *_sbrk(ptrdiff_t incr) {
extern char _end[];
extern char _heap_end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) {
return NULL - 1;
}
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) {
return NULL - 1;
}
curbrk += incr;
return curbrk - incr;
curbrk += incr;
return curbrk - incr;
}

View File

@@ -1,12 +1,10 @@
/* See LICENSE of license details. */
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <nuclei_sdk_hal.h>
#include "gd32vf103_usart.h"
#include <errno.h>
#include <nuclei_sdk_hal.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
ssize_t _write(int fd, const void* ptr, size_t len) {
return -1;
}
ssize_t _write(int fd, const void *ptr, size_t len) { return -1; }

View File

@@ -1,42 +1,36 @@
#include "nuclei_sdk_soc.h"
static uint32_t get_timer_freq()
{
return SOC_TIMER_FREQ;
static uint32_t get_timer_freq() { return SOC_TIMER_FREQ; }
uint32_t measure_cpu_freq(uint32_t n) {
uint32_t start_mcycle, delta_mcycle;
uint32_t start_mtime, delta_mtime;
uint32_t mtime_freq = get_timer_freq();
// Don't start measuruing until we see an mtime tick
uint32_t tmp = (uint32_t)SysTimer_GetLoadValue();
do {
start_mtime = (uint32_t)SysTimer_GetLoadValue();
start_mcycle = __RV_CSR_READ(CSR_MCYCLE);
} while (start_mtime == tmp);
do {
delta_mtime = (uint32_t)SysTimer_GetLoadValue() - start_mtime;
delta_mcycle = __RV_CSR_READ(CSR_MCYCLE) - start_mcycle;
} while (delta_mtime < n);
return (delta_mcycle / delta_mtime) * mtime_freq + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
}
uint32_t measure_cpu_freq(uint32_t n)
{
uint32_t start_mcycle, delta_mcycle;
uint32_t start_mtime, delta_mtime;
uint32_t mtime_freq = get_timer_freq();
uint32_t get_cpu_freq() {
uint32_t cpu_freq;
// Don't start measuruing until we see an mtime tick
uint32_t tmp = (uint32_t)SysTimer_GetLoadValue();
do {
start_mtime = (uint32_t)SysTimer_GetLoadValue();
start_mcycle = __RV_CSR_READ(CSR_MCYCLE);
} while (start_mtime == tmp);
// warm up
measure_cpu_freq(1);
// measure for real
cpu_freq = measure_cpu_freq(100);
do {
delta_mtime = (uint32_t)SysTimer_GetLoadValue() - start_mtime;
delta_mcycle = __RV_CSR_READ(CSR_MCYCLE) - start_mcycle;
} while (delta_mtime < n);
return (delta_mcycle / delta_mtime) * mtime_freq
+ ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
}
uint32_t get_cpu_freq()
{
uint32_t cpu_freq;
// warm up
measure_cpu_freq(1);
// measure for real
cpu_freq = measure_cpu_freq(100);
return cpu_freq;
return cpu_freq;
}
/**
@@ -46,14 +40,13 @@ uint32_t get_cpu_freq()
* \param[in] count: count in milliseconds
* \remarks
*/
void delay_1ms(uint32_t count)
{
uint64_t start_mtime, delta_mtime;
uint64_t delay_ticks = (SOC_TIMER_FREQ * (uint64_t)count) / 1000;
void delay_1ms(uint32_t count) {
uint64_t start_mtime, delta_mtime;
uint64_t delay_ticks = (SOC_TIMER_FREQ * (uint64_t)count) / 1000;
start_mtime = SysTimer_GetLoadValue();
start_mtime = SysTimer_GetLoadValue();
do {
delta_mtime = SysTimer_GetLoadValue() - start_mtime;
} while (delta_mtime < delay_ticks);
do {
delta_mtime = SysTimer_GetLoadValue() - start_mtime;
} while (delta_mtime < delay_ticks);
}

View File

@@ -23,9 +23,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nuclei_sdk_hal.h"
#include <stdint.h>
#include <stdio.h>
#include "nuclei_sdk_hal.h"
/*----------------------------------------------------------------------------
Define clocks
@@ -33,7 +33,7 @@
/* ToDo: add here your necessary defines for device initialization
following is an example for different system frequencies */
#ifndef SYSTEM_CLOCK
#define SYSTEM_CLOCK __SYSTEM_CLOCK_108M_PLL_HXTAL
#define SYSTEM_CLOCK __SYSTEM_CLOCK_108M_PLL_HXTAL
#endif
/**
@@ -94,87 +94,76 @@ uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; /* System Clock Freque
*/
static void system_clock_108m_hxtal(void) {
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
/* wait until HXTAL is stable or the startup time is longer than
* HXTAL_STARTUP_TIMEOUT */
do {
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
} while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
/* wait until HXTAL is stable or the startup time is longer than
* HXTAL_STARTUP_TIMEOUT */
do {
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
} while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
/* if fail */
if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
while (1) {
}
}
/* if fail */
if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
while (1) {}
}
/* HXTAL is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* HXTAL is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27);
/* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27);
if (HXTAL_VALUE == 25000000) {
/* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF |
RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PREDV1_DIV5 | RCU_PLL1_MUL8 |
RCU_PREDV0_DIV10);
if (HXTAL_VALUE == 25000000) {
/* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */
RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PREDV1_DIV5 | RCU_PLL1_MUL8 | RCU_PREDV0_DIV10);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL1STB)) {
}
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL1STB)) {}
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL2EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL2STB)) {
}
} else if (HXTAL_VALUE == 8000000) {
RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF |
RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 | RCU_PREDV1_DIV2 |
RCU_PLL1_MUL20 | RCU_PLL2_MUL20);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL2EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL2STB)) {}
} else if (HXTAL_VALUE == 8000000) {
RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV0);
RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 | RCU_PREDV1_DIV2 | RCU_PLL1_MUL20 | RCU_PLL2_MUL20);
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL1STB)) {
}
/* enable PLL1 */
RCU_CTL |= RCU_CTL_PLL1EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL1STB)) {}
/* enable PLL2 */
RCU_CTL |= RCU_CTL_PLL2EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL2STB)) {
}
}
/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;
/* enable PLL2 */
RCU_CTL |= RCU_CTL_PLL2EN;
/* wait till PLL1 is ready */
while (0U == (RCU_CTL & RCU_CTL_PLL2STB)) {}
}
/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;
/* wait until PLL is stable */
while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
}
/* wait until PLL is stable */
while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) {}
/* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL;
/* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL;
/* wait until PLL is selected as system clock */
while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) {
}
/* wait until PLL is selected as system clock */
while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) {}
}
/*!
@@ -183,9 +172,7 @@ static void system_clock_108m_hxtal(void) {
\param[out] none
\retval none
*/
static void system_clock_config(void) {
system_clock_108m_hxtal();
}
static void system_clock_config(void) { system_clock_108m_hxtal(); }
/**
* \brief Function to update the variable \ref SystemCoreClock
@@ -196,82 +183,82 @@ static void system_clock_config(void) {
*/
void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
{
/* ToDo: add code to calculate the system frequency based upon the current
* register settings.
* Note: This function can be used to retrieve the system core clock
* frequeny after user changed register settings.
*/
uint32_t scss;
uint32_t pllsel, predv0sel, pllmf, ck_src;
uint32_t predv0, predv1, pll1mf;
/* ToDo: add code to calculate the system frequency based upon the current
* register settings.
* Note: This function can be used to retrieve the system core clock
* frequeny after user changed register settings.
*/
uint32_t scss;
uint32_t pllsel, predv0sel, pllmf, ck_src;
uint32_t predv0, predv1, pll1mf;
scss = GET_BITS(RCU_CFG0, 2, 3);
scss = GET_BITS(RCU_CFG0, 2, 3);
switch (scss) {
/* IRC8M is selected as CK_SYS */
case SEL_IRC8M:
SystemCoreClock = IRC8M_VALUE;
break;
switch (scss) {
/* IRC8M is selected as CK_SYS */
case SEL_IRC8M:
SystemCoreClock = IRC8M_VALUE;
break;
/* HXTAL is selected as CK_SYS */
case SEL_HXTAL:
SystemCoreClock = HXTAL_VALUE;
break;
/* HXTAL is selected as CK_SYS */
case SEL_HXTAL:
SystemCoreClock = HXTAL_VALUE;
break;
/* PLL is selected as CK_SYS */
case SEL_PLL:
/* PLL clock source selection, HXTAL or IRC8M/2 */
pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
/* PLL is selected as CK_SYS */
case SEL_PLL:
/* PLL clock source selection, HXTAL or IRC8M/2 */
pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
if (RCU_PLLSRC_IRC8M_DIV2 == pllsel) {
/* PLL clock source is IRC8M/2 */
ck_src = IRC8M_VALUE / 2U;
} else {
/* PLL clock source is HXTAL */
ck_src = HXTAL_VALUE;
if (RCU_PLLSRC_IRC8M_DIV2 == pllsel) {
/* PLL clock source is IRC8M/2 */
ck_src = IRC8M_VALUE / 2U;
} else {
/* PLL clock source is HXTAL */
ck_src = HXTAL_VALUE;
predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
/* source clock use PLL1 */
if (RCU_PREDV0SRC_CKPLL1 == predv0sel) {
predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
if (17U == pll1mf) {
pll1mf = 20U;
}
ck_src = (ck_src / predv1) * pll1mf;
}
predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
ck_src /= predv0;
}
/* source clock use PLL1 */
if (RCU_PREDV0SRC_CKPLL1 == predv0sel) {
predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
if (17U == pll1mf) {
pll1mf = 20U;
}
ck_src = (ck_src / predv1) * pll1mf;
}
predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
ck_src /= predv0;
}
/* PLL multiplication factor */
pllmf = GET_BITS(RCU_CFG0, 18, 21);
/* PLL multiplication factor */
pllmf = GET_BITS(RCU_CFG0, 18, 21);
if ((RCU_CFG0 & RCU_CFG0_PLLMF_4)) {
pllmf |= 0x10U;
}
if ((RCU_CFG0 & RCU_CFG0_PLLMF_4)) {
pllmf |= 0x10U;
}
if (pllmf >= 15U) {
pllmf += 1U;
} else {
pllmf += 2U;
}
if (pllmf >= 15U) {
pllmf += 1U;
} else {
pllmf += 2U;
}
SystemCoreClock = ck_src * pllmf;
SystemCoreClock = ck_src * pllmf;
if (15U == pllmf) {
/* PLL source clock multiply by 6.5 */
SystemCoreClock = ck_src * 6U + ck_src / 2U;
}
if (15U == pllmf) {
/* PLL source clock multiply by 6.5 */
SystemCoreClock = ck_src * 6U + ck_src / 2U;
}
break;
break;
/* IRC8M is selected as CK_SYS */
default:
SystemCoreClock = IRC8M_VALUE;
break;
}
/* IRC8M is selected as CK_SYS */
default:
SystemCoreClock = IRC8M_VALUE;
break;
}
}
/**
@@ -283,39 +270,35 @@ void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
* SystemInit is called from the file <b>startup<i>_device</i></b>.
*/
void SystemInit(void) {
/* ToDo: add code to initialize the system
* Warn: do not use global variables because this function is called before
* reaching pre-main. RW section maybe overwritten afterwards.
*/
/* reset the RCC clock configuration to the default reset state */
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* ToDo: add code to initialize the system
* Warn: do not use global variables because this function is called before
* reaching pre-main. RW section maybe overwritten afterwards.
*/
/* reset the RCC clock configuration to the default reset state */
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */
RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC
| RCU_CFG0_APB2PSC |
RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL);
/* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */
RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL);
/* reset HXTALEN, CKMEN, PLLEN bits */
RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
/* reset HXTALEN, CKMEN, PLLEN bits */
RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
/* Reset HXTALBPS bit */
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
/* Reset HXTALBPS bit */
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
/* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */
/* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4);
RCU_CFG1 = 0x00000000U;
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4);
RCU_CFG1 = 0x00000000U;
/* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN
| RCU_CTL_HXTALEN);
/* disable all interrupts */
RCU_INT = 0x00FF0000U;
/* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
/* disable all interrupts */
RCU_INT = 0x00FF0000U;
/* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
system_clock_config();
/* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
system_clock_config();
}
/**
@@ -329,7 +312,7 @@ void SystemInit(void) {
* @{
*/
/** \brief Max exception handler number, don't include the NMI(0xFFF) one */
#define MAX_SYSTEM_EXCEPTION_NUM 12
#define MAX_SYSTEM_EXCEPTION_NUM 12
/**
* \brief Store the exception handlers for each exception ID
* \note
@@ -354,14 +337,13 @@ typedef void (*EXC_HANDLER)(unsigned long mcause, unsigned long sp);
* This function provided a default exception and NMI handling code for all exception ids.
* By default, It will just print some information for debug, Vendor can customize it according to its requirements.
*/
static void system_default_exception_handler(unsigned long mcause,
unsigned long sp) {
/* TODO: Uncomment this if you have implement printf function */
printf("MCAUSE: 0x%lx\r\n", mcause);
printf("MEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_MEPC));
printf("MTVAL : 0x%lx\r\n", __RV_CSR_READ(CSR_MBADADDR));
while (1)
;
static void system_default_exception_handler(unsigned long mcause, unsigned long sp) {
/* TODO: Uncomment this if you have implement printf function */
printf("MCAUSE: 0x%lx\r\n", mcause);
printf("MEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_MEPC));
printf("MTVAL : 0x%lx\r\n", __RV_CSR_READ(CSR_MBADADDR));
while (1)
;
}
/**
@@ -372,10 +354,9 @@ static void system_default_exception_handler(unsigned long mcause,
* Called in \ref _init function, used to initialize default exception handlers for all exception IDs
*/
static void Exception_Init(void) {
for (int i = 0; i < MAX_SYSTEM_EXCEPTION_NUM + 1; i++) {
SystemExceptionHandlers[i] =
(unsigned long) system_default_exception_handler;
}
for (int i = 0; i < MAX_SYSTEM_EXCEPTION_NUM + 1; i++) {
SystemExceptionHandlers[i] = (unsigned long)system_default_exception_handler;
}
}
/**
@@ -387,11 +368,11 @@ static void Exception_Init(void) {
* \param exc_handler The exception handler for this exception code EXCn
*/
void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler) {
if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM)) {
SystemExceptionHandlers[EXCn] = exc_handler;
} else if (EXCn == NMI_EXCn) {
SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = exc_handler;
}
if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM)) {
SystemExceptionHandlers[EXCn] = exc_handler;
} else if (EXCn == NMI_EXCn) {
SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = exc_handler;
}
}
/**
@@ -403,13 +384,13 @@ void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler) {
* \return Current exception handler for exception code EXCn, if not found, return 0.
*/
unsigned long Exception_Get_EXC(uint32_t EXCn) {
if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM)) {
return SystemExceptionHandlers[EXCn];
} else if (EXCn == NMI_EXCn) {
return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
} else {
return 0;
}
if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM)) {
return SystemExceptionHandlers[EXCn];
} else if (EXCn == NMI_EXCn) {
return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
} else {
return 0;
}
}
/**
@@ -424,33 +405,32 @@ unsigned long Exception_Get_EXC(uint32_t EXCn) {
* which can help developer to register your exception handler for specific exception number.
*/
uint32_t core_exception_handler(unsigned long mcause, unsigned long sp) {
uint32_t EXCn = (uint32_t) (mcause & 0X00000fff);
EXC_HANDLER exc_handler;
uint32_t EXCn = (uint32_t)(mcause & 0X00000fff);
EXC_HANDLER exc_handler;
if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM)) {
exc_handler = (EXC_HANDLER) SystemExceptionHandlers[EXCn];
} else if (EXCn == NMI_EXCn) {
exc_handler =
(EXC_HANDLER) SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
} else {
exc_handler = (EXC_HANDLER) system_default_exception_handler;
}
if (exc_handler != NULL) {
exc_handler(mcause, sp);
}
return 0;
if ((EXCn < MAX_SYSTEM_EXCEPTION_NUM)) {
exc_handler = (EXC_HANDLER)SystemExceptionHandlers[EXCn];
} else if (EXCn == NMI_EXCn) {
exc_handler = (EXC_HANDLER)SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
} else {
exc_handler = (EXC_HANDLER)system_default_exception_handler;
}
if (exc_handler != NULL) {
exc_handler(mcause, sp);
}
return 0;
}
/** @} *//* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */
/** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */
void SystemBannerPrint(void) {
#if defined(NUCLEI_BANNER) && (NUCLEI_BANNER == 1)
#ifndef DOWNLOAD_MODE
#error DOWNLOAD_MODE is not defined via build system, please check!
#endif
const char* download_modes[] = {"FLASHXIP", "FLASH", "ILM", "DDR"};
printf("Nuclei SDK Build Time: %s, %s\r\n", __DATE__, __TIME__);
printf("Download Mode: %s\r\n", download_modes[DOWNLOAD_MODE]);
printf("CPU Frequency %d Hz\r\n", SystemCoreClock);
const char *download_modes[] = {"FLASHXIP", "FLASH", "ILM", "DDR"};
printf("Nuclei SDK Build Time: %s, %s\r\n", __DATE__, __TIME__);
printf("Download Mode: %s\r\n", download_modes[DOWNLOAD_MODE]);
printf("CPU Frequency %d Hz\r\n", SystemCoreClock);
#endif
}
@@ -461,9 +441,9 @@ void SystemBannerPrint(void) {
* configuration.
*/
void ECLIC_Init(void) {
/* TODO: Add your own initialization code here. This function will be called by main */
ECLIC_SetMth(0);
ECLIC_SetCfgNlbits(__ECLIC_INTCTLBITS);
/* TODO: Add your own initialization code here. This function will be called by main */
ECLIC_SetMth(0);
ECLIC_SetCfgNlbits(__ECLIC_INTCTLBITS);
}
/**
@@ -482,31 +462,28 @@ void ECLIC_Init(void) {
* - This function use to configure specific eclic interrupt and register its interrupt handler and enable its interrupt.
* - If the vector table is placed in read-only section(FLASHXIP mode), handler could not be installed
*/
int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv,
ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority,
void *handler) {
if ((IRQn > SOC_INT_MAX) || (shv > ECLIC_VECTOR_INTERRUPT)
|| (trig_mode > ECLIC_NEGTIVE_EDGE_TRIGGER)) {
return -1;
}
int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv, ECLIC_TRIGGER_Type trig_mode, uint8_t lvl, uint8_t priority, void *handler) {
if ((IRQn > SOC_INT_MAX) || (shv > ECLIC_VECTOR_INTERRUPT) || (trig_mode > ECLIC_NEGTIVE_EDGE_TRIGGER)) {
return -1;
}
/* set interrupt vector mode */
ECLIC_SetShvIRQ(IRQn, shv);
/* set interrupt trigger mode and polarity */
ECLIC_SetTrigIRQ(IRQn, trig_mode);
/* set interrupt level */
ECLIC_SetLevelIRQ(IRQn, lvl);
/* set interrupt priority */
ECLIC_SetPriorityIRQ(IRQn, priority);
if (handler != NULL) {
/* set interrupt handler entry to vector table */
ECLIC_SetVector(IRQn, (rv_csr_t) handler);
}
/* enable interrupt */
ECLIC_EnableIRQ(IRQn);
return 0;
/* set interrupt vector mode */
ECLIC_SetShvIRQ(IRQn, shv);
/* set interrupt trigger mode and polarity */
ECLIC_SetTrigIRQ(IRQn, trig_mode);
/* set interrupt level */
ECLIC_SetLevelIRQ(IRQn, lvl);
/* set interrupt priority */
ECLIC_SetPriorityIRQ(IRQn, priority);
if (handler != NULL) {
/* set interrupt handler entry to vector table */
ECLIC_SetVector(IRQn, (rv_csr_t)handler);
}
/* enable interrupt */
ECLIC_EnableIRQ(IRQn);
return 0;
}
/** @} *//* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */
/** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */
/**
* \brief early init function before main
@@ -517,12 +494,12 @@ int32_t ECLIC_Register_IRQ(IRQn_Type IRQn, uint8_t shv,
* to do initialization
*/
void _premain_init(void) {
/* TODO: Add your own initialization code here, called before main */
SystemCoreClock = get_cpu_freq();
/* Initialize exception default handlers */
Exception_Init();
/* ECLIC initialization, mainly MTH and NLBIT */
ECLIC_Init();
/* TODO: Add your own initialization code here, called before main */
SystemCoreClock = get_cpu_freq();
/* Initialize exception default handlers */
Exception_Init();
/* ECLIC initialization, mainly MTH and NLBIT */
ECLIC_Init();
}
/**
@@ -534,9 +511,7 @@ void _premain_init(void) {
* by __libc_fini_array function, so we defined a new function
* to do initialization
*/
void _postmain_fini(int status) {
/* TODO: Add your own finishing code here, called after main */
}
void _postmain_fini(int status) { /* TODO: Add your own finishing code here, called after main */ }
/**
* \brief _init function called in __libc_init_array()
@@ -547,9 +522,7 @@ void _postmain_fini(int status) {
* \note
* Please use \ref _premain_init function now
*/
void _init(void) {
/* Don't put any code here, please use _premain_init now */
}
void _init(void) { /* Don't put any code here, please use _premain_init now */ }
/**
* \brief _fini function called in __libc_fini_array()
@@ -560,8 +533,6 @@ void _init(void) {
* \note
* Please use \ref _postmain_fini function now
*/
void _fini(void) {
/* Don't put any code here, please use _postmain_fini now */
}
void _fini(void) { /* Don't put any code here, please use _postmain_fini now */ }
/** @} *//* End of Doxygen Group NMSIS_Core_SystemAndClock */
/** @} */ /* End of Doxygen Group NMSIS_Core_SystemAndClock */

View File

@@ -9,39 +9,38 @@
#include "BSP_Flash.h"
#include "gd32vf103_libopt.h"
#include "string.h"
#define FMC_PAGE_SIZE ((uint16_t)0x400U)
//static uint16_t settings_page[FMC_PAGE_SIZE] __attribute__ ((section (".settings_page")));
//Linker script doesnt want to play, so for now its hard coded
#define SETTINGS_START_PAGE (0x08000000 +(127*1024))
#define FMC_PAGE_SIZE ((uint16_t)0x400U)
// static uint16_t settings_page[FMC_PAGE_SIZE] __attribute__ ((section (".settings_page")));
// Linker script doesnt want to play, so for now its hard coded
#define SETTINGS_START_PAGE (0x08000000 + (127 * 1024))
uint8_t flash_save_buffer(const uint8_t *buffer, const uint16_t length) {
/* unlock the flash program/erase controller */
fmc_unlock();
/* unlock the flash program/erase controller */
fmc_unlock();
/* clear all pending flags */
fmc_flag_clear(FMC_FLAG_END);
fmc_flag_clear(FMC_FLAG_WPERR);
fmc_flag_clear(FMC_FLAG_PGERR);
resetWatchdog();
fmc_page_erase((uint32_t) SETTINGS_START_PAGE);
resetWatchdog();
uint16_t *data = (uint16_t*) buffer;
for (uint8_t i = 0; i < (length / 2); i++) {
fmc_halfword_program((uint32_t) SETTINGS_START_PAGE + (i * 2), data[i]);
fmc_flag_clear(FMC_FLAG_END);
fmc_flag_clear(FMC_FLAG_WPERR);
fmc_flag_clear(FMC_FLAG_PGERR);
resetWatchdog();
}
fmc_lock();
return 1;
/* clear all pending flags */
fmc_flag_clear(FMC_FLAG_END);
fmc_flag_clear(FMC_FLAG_WPERR);
fmc_flag_clear(FMC_FLAG_PGERR);
resetWatchdog();
fmc_page_erase((uint32_t)SETTINGS_START_PAGE);
resetWatchdog();
uint16_t *data = (uint16_t *)buffer;
for (uint8_t i = 0; i < (length / 2); i++) {
fmc_halfword_program((uint32_t)SETTINGS_START_PAGE + (i * 2), data[i]);
fmc_flag_clear(FMC_FLAG_END);
fmc_flag_clear(FMC_FLAG_WPERR);
fmc_flag_clear(FMC_FLAG_PGERR);
resetWatchdog();
}
fmc_lock();
return 1;
}
void flash_read_buffer(uint8_t *buffer, const uint16_t length) {
uint32_t* b = (uint32_t*) buffer;
uint32_t* b2 = (uint32_t*) SETTINGS_START_PAGE;
for (int i = 0; i < length / 4; i++) {
b[i] = b2[i];
}
uint32_t *b = (uint32_t *)buffer;
uint32_t *b2 = (uint32_t *)SETTINGS_START_PAGE;
for (int i = 0; i < length / 4; i++) {
b[i] = b2[i];
}
}

View File

@@ -16,12 +16,12 @@
*/
#include "Model_Config.h"
#ifdef POW_PD
#include "Setup.h"
#include "BSP.h"
#include "fusb302b.h"
#include "I2C_Wrapper.hpp"
#include <pd.h>
#include "Setup.h"
#include "fusb302b.h"
#include "int_n.h"
#include <pd.h>
/*
* Read a single byte from the FUSB302B
*
@@ -31,11 +31,11 @@
* Returns the value read from addr.
*/
static uint8_t fusb_read_byte(uint8_t addr) {
uint8_t data[1];
if (!FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1)) {
return 0;
}
return data[0];
uint8_t data[1];
if (!FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, (uint8_t *)data, 1)) {
return 0;
}
return data[0];
}
/*
@@ -46,9 +46,7 @@ static uint8_t fusb_read_byte(uint8_t addr) {
* size: The number of bytes to read
* buf: The buffer into which data will be read
*/
static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) {
return FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, buf, size);
}
static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { return FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, buf, size); }
/*
* Write a single byte to the FUSB302B
@@ -58,8 +56,8 @@ static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) {
* byte: The value to write
*/
static bool fusb_write_byte(uint8_t addr, uint8_t byte) {
FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1);
return true;
FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t *)&byte, 1);
return true;
}
/*
@@ -71,164 +69,150 @@ static bool fusb_write_byte(uint8_t addr, uint8_t byte) {
* buf: The buffer to write
*/
static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) {
FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) buf, size);
return true; //TODO
FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t *)buf, size);
return true; // TODO
}
void fusb_send_message(const union pd_msg *msg) {
/* Token sequences for the FUSB302B */
static uint8_t sop_seq[5] = {
FUSB_FIFO_TX_SOP1,
FUSB_FIFO_TX_SOP1,
FUSB_FIFO_TX_SOP1,
FUSB_FIFO_TX_SOP2,
FUSB_FIFO_TX_PACKSYM };
static const uint8_t eop_seq[4] = {
FUSB_FIFO_TX_JAM_CRC,
FUSB_FIFO_TX_EOP,
FUSB_FIFO_TX_TXOFF,
FUSB_FIFO_TX_TXON };
/* Token sequences for the FUSB302B */
static uint8_t sop_seq[5] = {FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP2, FUSB_FIFO_TX_PACKSYM};
static const uint8_t eop_seq[4] = {FUSB_FIFO_TX_JAM_CRC, FUSB_FIFO_TX_EOP, FUSB_FIFO_TX_TXOFF, FUSB_FIFO_TX_TXON};
/* Take the I2C2 mutex now so there can't be a race condition on sop_seq */
/* Get the length of the message: a two-octet header plus NUMOBJ four-octet
* data objects */
uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg);
/* Take the I2C2 mutex now so there can't be a race condition on sop_seq */
/* Get the length of the message: a two-octet header plus NUMOBJ four-octet
* data objects */
uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg);
/* Set the number of bytes to be transmitted in the packet */
sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len;
/* Write all three parts of the message to the TX FIFO */
fusb_write_buf( FUSB_FIFOS, 5, sop_seq);
fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes);
fusb_write_buf( FUSB_FIFOS, 4, eop_seq);
/* Set the number of bytes to be transmitted in the packet */
sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len;
/* Write all three parts of the message to the TX FIFO */
fusb_write_buf(FUSB_FIFOS, 5, sop_seq);
fusb_write_buf(FUSB_FIFOS, msg_len, msg->bytes);
fusb_write_buf(FUSB_FIFOS, 4, eop_seq);
}
uint8_t fusb_read_message(union pd_msg *msg) {
static uint8_t garbage[4];
uint8_t numobj;
static uint8_t garbage[4];
uint8_t numobj;
// Read the header. If its not a SOP we dont actually want it at all
// But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck
fusb_read_byte( FUSB_FIFOS);
/* Read the message header into msg */
fusb_read_buf( FUSB_FIFOS, 2, msg->bytes);
/* Get the number of data objects */
numobj = PD_NUMOBJ_GET(msg);
/* If there is at least one data object, read the data objects */
if (numobj > 0) {
fusb_read_buf( FUSB_FIFOS, numobj * 4, msg->bytes + 2);
}
/* Throw the CRC32 in the garbage, since the PHY already checked it. */
fusb_read_buf( FUSB_FIFOS, 4, garbage);
// Read the header. If its not a SOP we dont actually want it at all
// But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck
fusb_read_byte(FUSB_FIFOS);
/* Read the message header into msg */
fusb_read_buf(FUSB_FIFOS, 2, msg->bytes);
/* Get the number of data objects */
numobj = PD_NUMOBJ_GET(msg);
/* If there is at least one data object, read the data objects */
if (numobj > 0) {
fusb_read_buf(FUSB_FIFOS, numobj * 4, msg->bytes + 2);
}
/* Throw the CRC32 in the garbage, since the PHY already checked it. */
fusb_read_buf(FUSB_FIFOS, 4, garbage);
return 0;
return 0;
}
void fusb_send_hardrst() {
/* Send a hard reset */
fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET);
/* Send a hard reset */
fusb_write_byte(FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET);
}
bool fusb_setup() {
if (!FRToSI2C::probe(FUSB302B_ADDR)) {
return false;
}
/* Fully reset the FUSB302B */
fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES);
osDelay(2);
uint8_t tries = 0;
while (!fusb_read_id()) {
osDelay(10);
tries++;
if (tries > 5) {
return false; //Welp :(
}
}
if (!FRToSI2C::probe(FUSB302B_ADDR)) {
return false;
}
/* Fully reset the FUSB302B */
fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES);
osDelay(2);
uint8_t tries = 0;
while (!fusb_read_id()) {
osDelay(10);
tries++;
if (tries > 5) {
return false; // Welp :(
}
}
/* Turn on all power */
fusb_write_byte( FUSB_POWER, 0x0F);
/* Turn on all power */
fusb_write_byte(FUSB_POWER, 0x0F);
/* Set interrupt masks */
//Setting to 0 so interrupts are allowed
fusb_write_byte( FUSB_MASK1, 0x00);
fusb_write_byte( FUSB_MASKA, 0x00);
fusb_write_byte( FUSB_MASKB, 0x00);
fusb_write_byte( FUSB_CONTROL0, 0b11 << 2);
/* Set interrupt masks */
// Setting to 0 so interrupts are allowed
fusb_write_byte(FUSB_MASK1, 0x00);
fusb_write_byte(FUSB_MASKA, 0x00);
fusb_write_byte(FUSB_MASKB, 0x00);
fusb_write_byte(FUSB_CONTROL0, 0b11 << 2);
/* Enable automatic retransmission */
fusb_write_byte( FUSB_CONTROL3, 0x07);
//set defaults
fusb_write_byte( FUSB_CONTROL2, 0x00);
/* Flush the RX buffer */
fusb_write_byte( FUSB_CONTROL1,
FUSB_CONTROL1_RX_FLUSH);
/* Enable automatic retransmission */
fusb_write_byte(FUSB_CONTROL3, 0x07);
// set defaults
fusb_write_byte(FUSB_CONTROL2, 0x00);
/* Flush the RX buffer */
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
/* Measure CC1 */
fusb_write_byte( FUSB_SWITCHES0, 0x07);
osDelay(10);
uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
/* Measure CC1 */
fusb_write_byte(FUSB_SWITCHES0, 0x07);
osDelay(10);
uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
/* Measure CC2 */
fusb_write_byte( FUSB_SWITCHES0, 0x0B);
osDelay(10);
uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
/* Measure CC2 */
fusb_write_byte(FUSB_SWITCHES0, 0x0B);
osDelay(10);
uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL;
/* Select the correct CC line for BMC signaling; also enable AUTO_CRC */
if (cc1 > cc2) {
fusb_write_byte( FUSB_SWITCHES1, 0x25);
fusb_write_byte( FUSB_SWITCHES0, 0x07);
} else {
fusb_write_byte( FUSB_SWITCHES1, 0x26);
fusb_write_byte( FUSB_SWITCHES0, 0x0B);
}
/* Select the correct CC line for BMC signaling; also enable AUTO_CRC */
if (cc1 > cc2) {
fusb_write_byte(FUSB_SWITCHES1, 0x25);
fusb_write_byte(FUSB_SWITCHES0, 0x07);
} else {
fusb_write_byte(FUSB_SWITCHES1, 0x26);
fusb_write_byte(FUSB_SWITCHES0, 0x0B);
}
fusb_reset();
setupFUSBIRQ();
return true;
fusb_reset();
setupFUSBIRQ();
return true;
}
void fusb_get_status(union fusb_status *status) {
/* Read the interrupt and status flags into status */
fusb_read_buf( FUSB_STATUS0A, 7, status->bytes);
/* Read the interrupt and status flags into status */
fusb_read_buf(FUSB_STATUS0A, 7, status->bytes);
}
enum fusb_typec_current fusb_get_typec_current() {
/* Read the BC_LVL into a variable */
enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte(
FUSB_STATUS0) & FUSB_STATUS0_BC_LVL);
/* Read the BC_LVL into a variable */
enum fusb_typec_current bc_lvl = (enum fusb_typec_current)(fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL);
return bc_lvl;
return bc_lvl;
}
void fusb_reset() {
/* Flush the TX buffer */
fusb_write_byte( FUSB_CONTROL0, 0x44);
/* Flush the RX buffer */
fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
/* Reset the PD logic */
// fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET);
/* Flush the TX buffer */
fusb_write_byte(FUSB_CONTROL0, 0x44);
/* Flush the RX buffer */
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
/* Reset the PD logic */
// fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET);
}
bool fusb_read_id() {
//Return true if read of the revision ID is sane
uint8_t version = 0;
fusb_read_buf(FUSB_DEVICE_ID, 1, &version);
if (version == 0 || version == 0xFF)
return false;
return true;
// Return true if read of the revision ID is sane
uint8_t version = 0;
fusb_read_buf(FUSB_DEVICE_ID, 1, &version);
if (version == 0 || version == 0xFF)
return false;
return true;
}
uint8_t fusb302_detect() {
//Probe the I2C bus for its address
return FRToSI2C::probe(FUSB302B_ADDR);
// Probe the I2C bus for its address
return FRToSI2C::probe(FUSB302B_ADDR);
}
#endif

View File

@@ -13,13 +13,12 @@
#define LOGO_HEADER_VALUE 0xF00DAA55
uint8_t showBootLogoIfavailable() {
// Do not show logo data if signature is not found.
if (LOGO_HEADER_VALUE != *(reinterpret_cast<const uint32_t*>(FLASH_LOGOADDR))) {
return 0;
}
// Do not show logo data if signature is not found.
if (LOGO_HEADER_VALUE != *(reinterpret_cast<const uint32_t *>(FLASH_LOGOADDR))) {
return 0;
}
OLED::drawAreaSwapped(0, 0, 96, 16, (uint8_t*) (FLASH_LOGOADDR + 4));
OLED::refresh();
return 1;
OLED::drawAreaSwapped(0, 0, 96, 16, (uint8_t *)(FLASH_LOGOADDR + 4));
OLED::refresh();
return 1;
}

View File

@@ -1,38 +1,34 @@
#include "BSP.h"
#include "FreeRTOS.h"
#include "I2C_Wrapper.hpp"
#include "QC3.h"
#include "Settings.h"
#include "Si7210.h"
#include "cmsis_os.h"
#include "fusbpd.h"
#include "main.hpp"
#include "power.hpp"
#include "stdlib.h"
#include "task.h"
#include "I2C_Wrapper.hpp"
#include "fusbpd.h"
#include "Si7210.h"
bool hall_effect_present = false;
void postRToSInit() {
// Any after RTos setup
// Any after RTos setup
#ifdef HALL_SI7210
if (Si7210::detect()) {
hall_effect_present = Si7210::init();
}
if (Si7210::detect()) {
hall_effect_present = Si7210::init();
}
#endif
#ifdef POW_PD
//Spawn all of the USB-C processors
fusb302_start_processing();
// Spawn all of the USB-C processors
fusb302_start_processing();
#endif
}
int16_t getRawHallEffect() {
if (hall_effect_present) {
return Si7210::read();
}
return 0;
if (hall_effect_present) {
return Si7210::read();
}
return 0;
}
bool getHallSensorFitted() {
return hall_effect_present;
}
bool getHallSensorFitted() { return hall_effect_present; }

View File

@@ -5,18 +5,18 @@
* Author: Ralim
*/
#include "gd32vf103_libopt.h"
#include "BSP.h"
#include "Pins.h"
#include "Setup.h"
#include "gd32vf103_libopt.h"
#include <I2C_Wrapper.hpp>
void preRToSInit() {
//Normal system bringup -- GPIO etc
// Normal system bringup -- GPIO etc
hardware_init();
delay_ms(5);
gpio_bit_reset(OLED_RESET_GPIO_Port, OLED_RESET_Pin);
delay_ms(50);
gpio_bit_set(OLED_RESET_GPIO_Port, OLED_RESET_Pin);
FRToSI2C::FRToSInit();
hardware_init();
delay_ms(5);
gpio_bit_reset(OLED_RESET_GPIO_Port, OLED_RESET_Pin);
delay_ms(50);
gpio_bit_set(OLED_RESET_GPIO_Port, OLED_RESET_Pin);
FRToSI2C::FRToSInit();
}