Format Pine code
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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); }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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; }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user