mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
Merge branch 'pinecil' of https://github.com/Ralim/ts100 into pinecil
This commit is contained in:
@@ -4,110 +4,96 @@
|
||||
* Created on: 14Apr.,2018
|
||||
* Author: Ralim
|
||||
*/
|
||||
#include <I2C_Wrapper.hpp>
|
||||
#include "BSP.h"
|
||||
#include "Setup.h"
|
||||
#include <I2C_Wrapper.hpp>
|
||||
SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
|
||||
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
|
||||
SemaphoreHandle_t FRToSI2C::I2CSemaphore2 = nullptr;
|
||||
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer2;
|
||||
|
||||
void FRToSI2C::CpltCallback() {
|
||||
hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error)
|
||||
if (I2CSemaphore) {
|
||||
xSemaphoreGiveFromISR(I2CSemaphore, NULL);
|
||||
}
|
||||
hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error)
|
||||
if (I2CSemaphore) {
|
||||
xSemaphoreGiveFromISR(I2CSemaphore, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
|
||||
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
|
||||
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) {
|
||||
return Mem_Write(address, reg, &data, 1);
|
||||
return Mem_Write(address, reg, &data, 1);
|
||||
}
|
||||
|
||||
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
|
||||
uint8_t tx_data[1];
|
||||
Mem_Read(add, reg, tx_data, 1);
|
||||
return tx_data[0];
|
||||
uint8_t tx_data[1];
|
||||
Mem_Read(add, reg, tx_data, 1);
|
||||
return tx_data[0];
|
||||
}
|
||||
bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
|
||||
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
|
||||
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) != HAL_OK) {
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) != HAL_OK) {
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FRToSI2C::probe(uint16_t DevAddress) {
|
||||
if (!lock())
|
||||
return false;
|
||||
uint8_t buffer[1];
|
||||
bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK;
|
||||
unlock();
|
||||
return worked;
|
||||
if (!lock())
|
||||
return false;
|
||||
uint8_t buffer[1];
|
||||
bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK;
|
||||
unlock();
|
||||
return worked;
|
||||
}
|
||||
|
||||
void FRToSI2C::I2C_Unstick() {
|
||||
unstick_I2C();
|
||||
unstick_I2C();
|
||||
}
|
||||
|
||||
void FRToSI2C::unlock() {
|
||||
xSemaphoreGive(I2CSemaphore);
|
||||
xSemaphoreGive(I2CSemaphore);
|
||||
}
|
||||
|
||||
bool FRToSI2C::lock() {
|
||||
return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE;
|
||||
}
|
||||
bool FRToSI2C::lock2() {
|
||||
if (I2CSemaphore2 == nullptr)
|
||||
return true;
|
||||
return xSemaphoreTake(I2CSemaphore2,1000) == pdTRUE;
|
||||
return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE;
|
||||
}
|
||||
|
||||
void FRToSI2C::unlock2() {
|
||||
if (I2CSemaphore2 == nullptr)
|
||||
return;
|
||||
xSemaphoreGive(I2CSemaphore2);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
extern uint32_t SystemCoreClock;
|
||||
#endif
|
||||
//RISC-V configuration
|
||||
|
||||
#include "n200_timer.h"
|
||||
#define USER_MODE_TASKS 0
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
@@ -69,30 +69,30 @@ extern uint32_t SystemCoreClock;
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
|
||||
|
||||
/* Define to trap errors during development. */
|
||||
#define configASSERT(x) \
|
||||
if ((x) == 0) { \
|
||||
taskDISABLE_INTERRUPTS(); \
|
||||
for (;;) \
|
||||
; \
|
||||
}
|
||||
#define configASSERT(x) \
|
||||
if ((x) == 0) { \
|
||||
taskDISABLE_INTERRUPTS(); \
|
||||
for (;;) \
|
||||
; \
|
||||
}
|
||||
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_xResumeFromISR 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||
#define INCLUDE_eTaskGetState 0
|
||||
#define INCLUDE_xEventGroupSetBitFromISR 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 0
|
||||
#define INCLUDE_xTaskAbortDelay 0
|
||||
#define INCLUDE_xTaskGetHandle 1
|
||||
#define INCLUDE_xTaskResumeFromISR 1
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_xResumeFromISR 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||
#define INCLUDE_eTaskGetState 0
|
||||
#define INCLUDE_xEventGroupSetBitFromISR 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 0
|
||||
#define INCLUDE_xTaskAbortDelay 0
|
||||
#define INCLUDE_xTaskGetHandle 1
|
||||
#define INCLUDE_xTaskResumeFromISR 1
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
|
||||
@@ -5,403 +5,399 @@
|
||||
* Author: Ralim
|
||||
*/
|
||||
#include "BSP.h"
|
||||
#include "Setup.h"
|
||||
#include "IRQ.h"
|
||||
#include "Setup.h"
|
||||
#include <I2C_Wrapper.hpp>
|
||||
SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
|
||||
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
|
||||
#define I2C_TIME_OUT (uint16_t)(5000)
|
||||
#define I2C_TIME_OUT (uint16_t)(5000)
|
||||
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);
|
||||
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 i2c_timeout_flag = 0;
|
||||
while (!(i2c_timeout_flag)) {
|
||||
switch (state) {
|
||||
case I2C_START:
|
||||
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 i2c_timeout_flag = 0;
|
||||
while (!(i2c_timeout_flag)) {
|
||||
switch (state) {
|
||||
case I2C_START:
|
||||
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)) {
|
||||
osDelay(1);
|
||||
}
|
||||
/* 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)) {
|
||||
osDelay(1);
|
||||
}
|
||||
/* 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;
|
||||
uint8_t i2c_timeout_flag = 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_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)) {
|
||||
osDelay(1);
|
||||
}
|
||||
/* 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;
|
||||
i2c_timeout_flag = I2C_OK;
|
||||
done = true;
|
||||
} else {
|
||||
timedout = true;
|
||||
done = true;
|
||||
timeout = 0;
|
||||
state = I2C_START;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
state = I2C_START;
|
||||
i2c_timeout_flag = I2C_OK;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (timeout < I2C_TIME_OUT) {
|
||||
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||
timeout = 0;
|
||||
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)) {
|
||||
osDelay(1);
|
||||
}
|
||||
/* 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);
|
||||
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();
|
||||
unstick_I2C();
|
||||
}
|
||||
|
||||
bool FRToSI2C::lock() {
|
||||
if (I2CSemaphore == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE;
|
||||
if (I2CSemaphore == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE;
|
||||
}
|
||||
|
||||
void FRToSI2C::unlock() {
|
||||
xSemaphoreGive(I2CSemaphore);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,41 +1,39 @@
|
||||
#include "FreeRTOSConfig.h"
|
||||
//
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "portmacro.h"
|
||||
#include "gd32vf103.h"
|
||||
#include "n200_func.h"
|
||||
#include "riscv_encoding.h"
|
||||
#include "n200_timer.h"
|
||||
#include "n200_eclic.h"
|
||||
|
||||
#include "n200_func.h"
|
||||
#include "n200_timer.h"
|
||||
#include "portmacro.h"
|
||||
#include "riscv_encoding.h"
|
||||
#include "task.h"
|
||||
/* Standard Includes */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting variable. */
|
||||
UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
#if USER_MODE_TASKS
|
||||
#ifdef __riscv_flen
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13));
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13));
|
||||
#else
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPIE);
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPIE);
|
||||
#endif
|
||||
#else
|
||||
#ifdef __riscv_flen
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13));
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13));
|
||||
#else
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE);
|
||||
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
static void prvTaskExitError(void);
|
||||
|
||||
/**
|
||||
* @brief System Call Trap
|
||||
@@ -45,79 +43,63 @@ static void prvTaskExitError( void );
|
||||
* @param arg1 ECALL macro stores argument in a2
|
||||
* @return unsigned long 传入的sp
|
||||
*/
|
||||
unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1)
|
||||
{
|
||||
switch(mcause&0X00000fff)
|
||||
{
|
||||
//on User and Machine ECALL, handler the request
|
||||
case 8:
|
||||
case 11:
|
||||
{
|
||||
if(arg1==IRQ_DISABLE)
|
||||
{
|
||||
//zero out mstatus.mpie
|
||||
clear_csr(mstatus,MSTATUS_MPIE);
|
||||
}
|
||||
else if(arg1==IRQ_ENABLE)
|
||||
{
|
||||
//set mstatus.mpie
|
||||
set_csr(mstatus,MSTATUS_MPIE);
|
||||
}
|
||||
else if(arg1==PORT_YIELD)
|
||||
{
|
||||
//always yield from machine mode
|
||||
//fix up mepc on sync trap
|
||||
unsigned long epc = read_csr(mepc);
|
||||
vPortYield_from_ulSynchTrap(sp,epc+4);
|
||||
}
|
||||
else if(arg1==PORT_YIELD_TO_RA)
|
||||
{
|
||||
vPortYield_from_ulSynchTrap(sp,(*(unsigned long*)(sp+1*sizeof(sp))));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* 异常处理 */
|
||||
extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp);
|
||||
handle_trap(mcause,sp);
|
||||
}
|
||||
}
|
||||
unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1) {
|
||||
switch (mcause & 0X00000fff) {
|
||||
//on User and Machine ECALL, handler the request
|
||||
case 8:
|
||||
case 11: {
|
||||
if (arg1 == IRQ_DISABLE) {
|
||||
//zero out mstatus.mpie
|
||||
clear_csr(mstatus, MSTATUS_MPIE);
|
||||
} else if (arg1 == IRQ_ENABLE) {
|
||||
//set mstatus.mpie
|
||||
set_csr(mstatus, MSTATUS_MPIE);
|
||||
} else if (arg1 == PORT_YIELD) {
|
||||
//always yield from machine mode
|
||||
//fix up mepc on sync trap
|
||||
unsigned long epc = read_csr(mepc);
|
||||
vPortYield_from_ulSynchTrap(sp, epc + 4);
|
||||
} else if (arg1 == PORT_YIELD_TO_RA) {
|
||||
vPortYield_from_ulSynchTrap(sp, (*(unsigned long *)(sp + 1 * sizeof(sp))));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* 异常处理 */
|
||||
extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp);
|
||||
handle_trap(mcause, sp);
|
||||
}
|
||||
}
|
||||
|
||||
//fix mepc and return
|
||||
unsigned long epc = read_csr(mepc);
|
||||
//fix mepc and return
|
||||
unsigned long epc = read_csr(mepc);
|
||||
|
||||
write_csr(mepc,epc+4);
|
||||
return sp;
|
||||
write_csr(mepc, epc + 4);
|
||||
return sp;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 设置触发软中断
|
||||
* @note 目的是在软中断内进行任务上下文切换
|
||||
*
|
||||
*/
|
||||
void vPortSetMSIPInt(void)
|
||||
{
|
||||
*(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) |=0x01;
|
||||
__asm volatile("fence");
|
||||
__asm volatile("fence.i");
|
||||
void vPortSetMSIPInt(void) {
|
||||
*(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) |= 0x01;
|
||||
__asm volatile("fence");
|
||||
__asm volatile("fence.i");
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 清除软中断
|
||||
*
|
||||
*/
|
||||
void vPortClearMSIPInt(void)
|
||||
{
|
||||
*(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01;
|
||||
void vPortClearMSIPInt(void) {
|
||||
*(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 执行任务上下文切换,在portasm.S中被调用
|
||||
*
|
||||
@@ -125,97 +107,84 @@ void vPortClearMSIPInt(void)
|
||||
* @param arg1
|
||||
* @return unsigned long sp地址
|
||||
*/
|
||||
unsigned long taskswitch( unsigned long sp, unsigned long arg1)
|
||||
{
|
||||
//always yield from machine mode
|
||||
//fix up mepc on
|
||||
unsigned long epc = read_csr(mepc);
|
||||
vPortYield(sp,epc); //never returns
|
||||
unsigned long taskswitch(unsigned long sp, unsigned long arg1) {
|
||||
//always yield from machine mode
|
||||
//fix up mepc on
|
||||
unsigned long epc = read_csr(mepc);
|
||||
vPortYield(sp, epc); //never returns
|
||||
|
||||
return sp;
|
||||
return sp;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 调研freertos内建函数vTaskSwitchContext,在portasm.S中被调用
|
||||
*
|
||||
*/
|
||||
void vDoTaskSwitchContext( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
vTaskSwitchContext();
|
||||
portENABLE_INTERRUPTS();
|
||||
void vDoTaskSwitchContext(void) {
|
||||
portDISABLE_INTERRUPTS();
|
||||
vTaskSwitchContext();
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 进入临界段
|
||||
*
|
||||
*/
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
#if USER_MODE_TASKS
|
||||
ECALL(IRQ_DISABLE);
|
||||
#else
|
||||
portDISABLE_INTERRUPTS();
|
||||
#endif
|
||||
void vPortEnterCritical(void) {
|
||||
#if USER_MODE_TASKS
|
||||
ECALL(IRQ_DISABLE);
|
||||
#else
|
||||
portDISABLE_INTERRUPTS();
|
||||
#endif
|
||||
|
||||
uxCriticalNesting++;
|
||||
uxCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 退出临界段
|
||||
*
|
||||
*/
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
#if USER_MODE_TASKS
|
||||
ECALL(IRQ_ENABLE);
|
||||
#else
|
||||
portENABLE_INTERRUPTS();
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
void vPortExitCritical(void) {
|
||||
configASSERT(uxCriticalNesting);
|
||||
uxCriticalNesting--;
|
||||
if (uxCriticalNesting == 0) {
|
||||
#if USER_MODE_TASKS
|
||||
ECALL(IRQ_ENABLE);
|
||||
#else
|
||||
portENABLE_INTERRUPTS();
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear current interrupt mask and set given mask
|
||||
*
|
||||
* @param int_mask mth值
|
||||
*/
|
||||
void vPortClearInterruptMask(int int_mask)
|
||||
{
|
||||
eclic_set_mth (int_mask);
|
||||
void vPortClearInterruptMask(int int_mask) {
|
||||
eclic_set_mth(int_mask);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set interrupt mask and return current interrupt enable register
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int xPortSetInterruptMask(void)
|
||||
{
|
||||
int int_mask=0;
|
||||
int_mask=eclic_get_mth();
|
||||
int xPortSetInterruptMask(void) {
|
||||
int int_mask = 0;
|
||||
int_mask = eclic_get_mth();
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
return int_mask;
|
||||
portDISABLE_INTERRUPTS();
|
||||
return int_mask;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化任务栈帧
|
||||
*
|
||||
@@ -224,138 +193,126 @@ int xPortSetInterruptMask(void)
|
||||
* @param pvParameters 任务参数
|
||||
* @return StackType_t* 完成初始化后的栈顶
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
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. */
|
||||
#ifdef __riscv_flen
|
||||
pxTopOfStack -= 32; /* 浮点寄存器 */
|
||||
pxTopOfStack -= 32; /* 浮点寄存器 */
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x40; /* CSR_SUBM */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x40; /* CSR_SUBM */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */
|
||||
|
||||
pxTopOfStack -= 22;
|
||||
*pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */
|
||||
pxTopOfStack -= 22;
|
||||
*pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */
|
||||
|
||||
pxTopOfStack -=9;
|
||||
*pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */
|
||||
pxTopOfStack--;
|
||||
pxTopOfStack -= 9;
|
||||
*pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */
|
||||
pxTopOfStack--;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 任务退出函数
|
||||
*
|
||||
*/
|
||||
void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
void prvTaskExitError(void) {
|
||||
/* 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();
|
||||
for( ;; );
|
||||
configASSERT(uxCriticalNesting == ~0UL);
|
||||
portDISABLE_INTERRUPTS();
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief tick中断
|
||||
* @note 由于该中断配置为向量模式,则中断到来会调用portasm.S的MTIME_HANDLER,进行栈帧保存之后该函数会调用vPortSysTickHandler
|
||||
*
|
||||
*/
|
||||
void vPortSysTickHandler(void)
|
||||
{
|
||||
volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME);
|
||||
volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP);
|
||||
void vPortSysTickHandler(void) {
|
||||
volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
|
||||
volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP);
|
||||
|
||||
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
traceISR_ENTER();
|
||||
#endif
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
traceISR_ENTER();
|
||||
#endif
|
||||
|
||||
uint64_t now = *mtime;
|
||||
now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);
|
||||
*mtimecmp = now;
|
||||
uint64_t now = *mtime;
|
||||
now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);
|
||||
*mtimecmp = now;
|
||||
|
||||
/* 调用freertos的tick增加接口 */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
traceISR_EXIT_TO_SCHEDULER();
|
||||
#endif
|
||||
portYIELD();
|
||||
}
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
else
|
||||
{
|
||||
traceISR_EXIT();
|
||||
}
|
||||
#endif
|
||||
/* 调用freertos的tick增加接口 */
|
||||
if (xTaskIncrementTick() != pdFALSE) {
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
traceISR_EXIT_TO_SCHEDULER();
|
||||
#endif
|
||||
portYIELD();
|
||||
}
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
else {
|
||||
traceISR_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化tick
|
||||
*
|
||||
*/
|
||||
void vPortSetupTimer(void)
|
||||
{
|
||||
/* 内核timer定时器使用64位的计数器来实现 */
|
||||
volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME);
|
||||
volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP);
|
||||
void vPortSetupTimer(void) {
|
||||
/* 内核timer定时器使用64位的计数器来实现 */
|
||||
volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
|
||||
volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP);
|
||||
|
||||
portENTER_CRITICAL();
|
||||
portENTER_CRITICAL();
|
||||
uint64_t now = *mtime;
|
||||
now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);
|
||||
*mtimecmp = now;
|
||||
portEXIT_CRITICAL();
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
eclic_set_vmode(CLIC_INT_TMR);
|
||||
eclic_irq_enable(CLIC_INT_TMR,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0);
|
||||
eclic_set_vmode(CLIC_INT_TMR);
|
||||
eclic_irq_enable(CLIC_INT_TMR, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化软中断
|
||||
*
|
||||
*/
|
||||
void vPortSetupMSIP(void)
|
||||
{
|
||||
eclic_set_vmode(CLIC_INT_SFT);
|
||||
eclic_irq_enable(CLIC_INT_SFT,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0);
|
||||
void vPortSetupMSIP(void) {
|
||||
eclic_set_vmode(CLIC_INT_SFT);
|
||||
eclic_irq_enable(CLIC_INT_SFT, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief 调度启动前的初始化准备
|
||||
*
|
||||
*/
|
||||
void vPortSetup(void)
|
||||
{
|
||||
vPortSetupTimer();
|
||||
vPortSetupMSIP();
|
||||
uxCriticalNesting = 0;
|
||||
void vPortSetup(void) {
|
||||
vPortSetupTimer();
|
||||
vPortSetupMSIP();
|
||||
uxCriticalNesting = 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "riscv_encoding.h"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
@@ -20,123 +18,125 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#if (configUSE_16_BIT_TICKS == 1)
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t)0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t)0xffffffffUL
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portSTACK_GROWTH (-1)
|
||||
#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ)
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
extern void vPortYield(unsigned long,unsigned long);
|
||||
extern void vPortYield_from_ulSynchTrap(unsigned long,unsigned long);
|
||||
extern void vPortYield(unsigned long, unsigned long);
|
||||
extern void vPortYield_from_ulSynchTrap(unsigned long, unsigned long);
|
||||
extern int xPortSetInterruptMask(void);
|
||||
extern void vPortClearInterruptMask( int uxSavedStatusValue );
|
||||
|
||||
extern void vPortClearInterruptMask(int uxSavedStatusValue);
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*System Calls */
|
||||
/*-----------------------------------------------------------*/
|
||||
//ecall macro used to store argument in a3
|
||||
#define ECALL(arg) ({ \
|
||||
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg); \
|
||||
asm volatile ("ecall" \
|
||||
: "+r" (a2) \
|
||||
: \
|
||||
: "memory"); \
|
||||
a2; \
|
||||
#define ECALL(arg) ({ \
|
||||
register uintptr_t a2 asm("a2") = (uintptr_t)(arg); \
|
||||
asm volatile("ecall" \
|
||||
: "+r"(a2) \
|
||||
: \
|
||||
: "memory"); \
|
||||
a2; \
|
||||
})
|
||||
|
||||
|
||||
extern void vPortSetMSIPInt(void);
|
||||
#define port_MSIPSET_BIT vPortSetMSIPInt()
|
||||
|
||||
#define IRQ_DISABLE 20
|
||||
#define IRQ_ENABLE 30
|
||||
#define PORT_YIELD 40
|
||||
#define PORT_YIELD_TO_RA 50
|
||||
#define IRQ_DISABLE 20
|
||||
#define IRQ_ENABLE 30
|
||||
#define PORT_YIELD 40
|
||||
#define PORT_YIELD_TO_RA 50
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
/* the return after the ECALL is VERY important */
|
||||
|
||||
//#define portYIELD() ECALL(PORT_YIELD);
|
||||
#define portYIELD() port_MSIPSET_BIT;
|
||||
|
||||
#if CONFIG_SYSTEMVIEW_EN
|
||||
#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } }
|
||||
#ifdef CONFIG_SYSTEMVIEW_EN
|
||||
#define portEND_SWITCHING_ISR(xSwitchRequired) \
|
||||
{ \
|
||||
if (xSwitchRequired != pdFALSE) { \
|
||||
traceISR_EXIT_TO_SCHEDULER(); \
|
||||
portYIELD(); \
|
||||
} else { \
|
||||
traceISR_EXIT(); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD()
|
||||
#define portEND_SWITCHING_ISR(xSwitchRequired) \
|
||||
if (xSwitchRequired != pdFALSE) \
|
||||
portYIELD()
|
||||
#endif
|
||||
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
|
||||
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern void eclic_set_mth (uint8_t mth);
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY)|0x1f); \
|
||||
__asm volatile("fence"); \
|
||||
__asm volatile("fence.i"); \
|
||||
}
|
||||
#define portENABLE_INTERRUPTS() eclic_set_mth(0)
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
extern void vPortEnterCritical(void);
|
||||
extern void vPortExitCritical(void);
|
||||
extern void eclic_set_mth(uint8_t mth);
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY) | 0x1f); \
|
||||
__asm volatile("fence"); \
|
||||
__asm volatile("fence.i"); \
|
||||
}
|
||||
#define portENABLE_INTERRUPTS() eclic_set_mth(0)
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) vPortClearInterruptMask(uxSavedStatusValue)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not necessary for to use this port. They are defined so the common demo files
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime);
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime)
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#define portINLINE __inline
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#define portFORCE_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* Section where include file can be added */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Ensure stdint is only used by the compiler, and not the assembler. */
|
||||
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
extern uint32_t SystemCoreClock;
|
||||
#endif
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configSUPPORT_STATIC_ALLOCATION 1
|
||||
#define configSUPPORT_DYNAMIC_ALLOCATION 0
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ ( SystemCoreClock )
|
||||
#define configTICK_RATE_HZ ((TickType_t)1000)
|
||||
#define configMAX_PRIORITIES ( 6 )
|
||||
#define configMINIMAL_STACK_SIZE ((uint16_t)256)
|
||||
#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/
|
||||
#define configMAX_TASK_NAME_LEN ( 32 )
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 8
|
||||
#define configUSE_TIMERS 0
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 0
|
||||
#define INCLUDE_vTaskDelete 0
|
||||
#define INCLUDE_vTaskCleanUpResources 0
|
||||
#define INCLUDE_vTaskSuspend 0
|
||||
#define INCLUDE_vTaskDelayUntil 0
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
|
||||
/* Cortex-M specific definitions. */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
#else
|
||||
#define configPRIO_BITS 4
|
||||
#endif
|
||||
|
||||
/* The lowest interrupt priority that can be used in a call to a "set priority"
|
||||
function. */
|
||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
|
||||
|
||||
/* The highest interrupt priority that can be used by any interrupt service
|
||||
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
|
||||
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
|
||||
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
|
||||
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
|
||||
|
||||
/* Interrupt priorities used by the kernel port layer itself. These are generic
|
||||
to all Cortex-M ports, and do not rely on any particular library functions. */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h
|
||||
header file. */
|
||||
/* USER CODE BEGIN 1 */
|
||||
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
|
||||
/* USER CODE END 1 */
|
||||
|
||||
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
|
||||
standard names. */
|
||||
#define vPortSVCHandler SVC_Handler
|
||||
#define xPortPendSVHandler PendSV_Handler
|
||||
|
||||
#if configUSE_TIMERS
|
||||
#define configTIMER_TASK_PRIORITY 2
|
||||
#define configTIMER_QUEUE_LENGTH 8
|
||||
#define configTIMER_TASK_STACK_DEPTH (512/4)
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
Reference in New Issue
Block a user