hpw421初始版本

This commit is contained in:
xushaoxiang
2026-06-06 16:49:48 +08:00
commit 2339bbfd1f
3283 changed files with 860261 additions and 0 deletions
@@ -0,0 +1,97 @@
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "ringbuffer.h"
/**
* @file
* Implementation of ring buffer functions.
*/
void ring_buffer_create(ring_buffer_t *rb, uint8_t *buffer, uint32_t size)
{
if ((rb == NULL) || (buffer == NULL) || (size == 0)) {
return;
}
rb->buffer = buffer;
rb->size = size;
rb->tail_index = 0;
rb->head_index = 0;
rb->rx_lock = false;
}
void ring_buffer_queue(ring_buffer_t *rb, uint8_t data)
{
/* Is buffer full? */
if (ring_buffer_is_full(rb)) {
/* Is going to overwrite the oldest byte */
/* Increase tail index */
rb->tail_index = ((rb->tail_index + 1) & (rb->size - 1));
}
/* Place data in buffer */
rb->buffer[rb->head_index] = data;
rb->head_index = ((rb->head_index + 1) & (rb->size - 1));
}
void ring_buffer_queue_arr(ring_buffer_t *rb, uint8_t *data,
ring_buffer_size_t size)
{
/* Add bytes; one by one */
ring_buffer_size_t i;
for (i = 0; i < size; i++) {
ring_buffer_queue(rb, data[i]);
}
}
ring_buffer_size_t ring_buffer_dequeue(ring_buffer_t *rb, uint8_t *data)
{
if (ring_buffer_is_empty(rb)) {
/* No items */
return 0;
}
*data = rb->buffer[rb->tail_index];
rb->tail_index = ((rb->tail_index + 1) & (rb->size - 1));
return 1;
}
ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *rb, uint8_t *data,
ring_buffer_size_t len)
{
if (ring_buffer_is_empty(rb)) {
/* No items */
return 0;
}
unsigned char *data_ptr = data;
ring_buffer_size_t cnt = 0;
while ((cnt < len) && ring_buffer_dequeue(rb, data_ptr)) {
cnt++;
data_ptr++;
}
return cnt;
}
ring_buffer_size_t ring_buffer_peek(ring_buffer_t *rb, uint8_t *data,
ring_buffer_size_t index)
{
if (index >= ring_buffer_num_items(rb)) {
/* No items at index */
return 0;
}
/* Add index to pointer */
ring_buffer_size_t data_index = ((rb->tail_index + index) & (rb->size - 1));
*data = rb->buffer[data_index];
return 1;
}
extern inline ring_buffer_size_t ring_buffer_is_empty(ring_buffer_t *rb);
extern inline ring_buffer_size_t ring_buffer_is_full(ring_buffer_t *rb);
extern inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *rb);
@@ -0,0 +1,165 @@
/**
* @file
* Prototypes and structures for the ring buffer module.
*/
#ifndef __RINGBUFFER_H__
#define __RINGBUFFER_H__
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
/**
* The size of a ring buffer.
* Due to the design only <tt> RING_BUFFER_SIZE-1 </tt> items
* can be contained in the buffer.
* The buffer size must be a power of two.
*/
// #define RING_BUFFER_SIZE 256U//512
//
// #if (RING_BUFFER_SIZE & (RING_BUFFER_SIZE - 1)) != 0
// #error "RING_BUFFER_SIZE must be a power of two"
// #endif
/**
* The type which is used to hold the size
* and the indicies of the buffer.
* Must be able to fit \c RING_BUFFER_SIZE .
*/
typedef uint32_t ring_buffer_size_t;
/**
* Used as a modulo operator
* as <tt> a % b = (a & (b 1)) </tt>
* where \c a is a positive index in the buffer and
* \c b is the (power of two) size of the buffer.
*/
// #define RING_BUFFER_MASK (RING_BUFFER_SIZE-1)
/**
* Structure which holds a ring buffer.
* The buffer contains a buffer array
* as well as metadata for the ring buffer.
*/
typedef struct ring_buffer
{
/** Buffer memory. */
uint8_t *buffer;
/** Buffer size. */
ring_buffer_size_t size;
/** Index of tail. */
ring_buffer_size_t tail_index;
/** Index of head. */
ring_buffer_size_t head_index;
/** Rx Locker. */
bool rx_lock;
} ring_buffer_t;
// typedef struct ring_buffer {
// /** Buffer memory. */
//// uint8_t *buffer;
// unsigned char buffer[RING_BUFFER_SIZE];
// /** Index of tail. */
// ring_buffer_size_t tail_index;
// /** Index of head. */
// ring_buffer_size_t head_index;
// /** Rx Locker. */
// bool rx_lock;
//}ring_buffer_t;
// typedef struct ring_buffer {
// /** Buffer memory. */
//// uint8_t *buffer;
// unsigned char buffer[RING_BUFFER_SIZE];
// /** Index of tail. */
// ring_buffer_size_t tail_index;
// /** Index of head. */
// ring_buffer_size_t head_index;
// /** Rx Locker. */
// bool rx_lock;
//}ring_buffer_t;
/**
* Initializes the ring buffer pointed to by <em>buffer</em>.
* This function can also be used to empty/reset the buffer.
* @param buffer The ring buffer to initialize.
*/
// void ring_buffer_init(ring_buffer_t *buffer);
void ring_buffer_create(ring_buffer_t *rb, uint8_t *buffer, uint32_t size);
/**
* Adds a byte to a ring buffer.
* @param buffer The buffer in which the data should be placed.
* @param data The byte to place.
*/
void ring_buffer_queue(ring_buffer_t *rb, uint8_t data);
/**
* Adds an array of bytes to a ring buffer.
* @param buffer The buffer in which the data should be placed.
* @param data A pointer to the array of bytes to place in the queue.
* @param size The size of the array.
*/
void ring_buffer_queue_arr(ring_buffer_t *rb, uint8_t *data,
ring_buffer_size_t size);
/**
* Returns the oldest byte in a ring buffer.
* @param buffer The buffer from which the data should be returned.
* @param data A pointer to the location at which the data should be placed.
* @return 1 if data was returned; 0 otherwise.
*/
ring_buffer_size_t ring_buffer_dequeue(ring_buffer_t *rb, uint8_t *data);
/**
* Returns the <em>len</em> oldest bytes in a ring buffer.
* @param buffer The buffer from which the data should be returned.
* @param data A pointer to the array at which the data should be placed.
* @param len The maximum number of bytes to return.
* @return The number of bytes returned.
*/
ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *rb, uint8_t *data,
ring_buffer_size_t len);
/**
* Peeks a ring buffer, i.e. returns an element without removing it.
* @param buffer The buffer from which the data should be returned.
* @param data A pointer to the location at which the data should be placed.
* @param index The index to peek.
* @return 1 if data was returned; 0 otherwise.
*/
ring_buffer_size_t ring_buffer_peek(ring_buffer_t *rb, uint8_t *data,
ring_buffer_size_t index);
/**
* Returns whether a ring buffer is empty.
* @param buffer The buffer for which it should be returned whether it is empty.
* @return 1 if empty; 0 otherwise.
*/
inline ring_buffer_size_t ring_buffer_is_empty(ring_buffer_t *rb)
{
return (rb->head_index == rb->tail_index);
}
/**
* Returns whether a ring buffer is full.
* @param buffer The buffer for which it should be returned whether it is full.
* @return 1 if full; 0 otherwise.
*/
inline ring_buffer_size_t ring_buffer_is_full(ring_buffer_t *rb)
{
return ((rb->head_index - rb->tail_index) & (rb->size - 1)) ==
(rb->size - 1);
}
/**
* Returns the number of items in a ring buffer.
* @param buffer The buffer for which the number of items should be returned.
* @return The number of items in the ring buffer.
*/
inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *rb)
{
return ((rb->head_index - rb->tail_index) & (rb->size - 1));
}
#endif /* __RINGBUFFER_H__ */
@@ -0,0 +1,622 @@
/*!
* \file xc_drv_adc.c
*
* \brief Target xc adc driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static uint16_t adc_value[2 * ADC_FIFO_DOUT_LEN] = {0};
static uint16_t adc_it_val;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
**************************************************************************************
* @brief xc_adc_init
* @details ADC initialization
* @param[in] adc_cfg £ºThis is the structure parameter that the ADC initializes
* @param[out] void
* @retval void
* @other
adc_cfg.Freq = ADC_FREQ_2M;
adc_cfg.RefVol = ADC_REF_VOL_3_3V;
adc_cfg.SampEdge = ADC_SAMPEDGE_RISE;
adc_cfg.ExtDataMode = ADC_EXT_DATA_MODE_32BIT;
adc_cfg.ExtEdgeSel = ADC_EXT_EDGE_SEL_INTER;
adc_cfg.ExtSampleNum = ADC_EXT_SAMPLE_NUM_8;
adc_cfg.ExtTriggerSel = ADC_EXT_TRIGGER_SEL_PWM0;
adc_init(&adc_cfg);
***************************************************************************************
*/
void xc_adc_init(ADC_InitCfg_t *adc_cfg)
{
cpr_rstctl_ctlapb_sw__gpadc_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_ctlapb_sw__gpadc_rstn__setf(RSTCTL_DISABLE);
cpr_ctlapbclken_grctl__gpadc_pclk_en__setf(ENABLE);
cpr_opa_ctrl_reg__bg_5v_ctrl__setf(ENABLE);
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE);
xc_adc_fifo_flush();
adc_timer0_set(ADC_TIMER);
adc_main_ctl__edge_sel__setf(adc_cfg->SampEdge);
xc_adc_freq_set(adc_cfg->Freq);
xc_adc_refvol_set(adc_cfg->RefVol);
adc_main_ctl__ext_edge_sel__setf(adc_cfg->ExtEdgeSel);
adc_main_ctl__ext_sample_num__setf(adc_cfg->ExtSampleNum);
adc_main_ctl__ext_trigger_sel__setf(adc_cfg->ExtTriggerSel);
adc_main_ctl__ext_data_mode__setf(adc_cfg->ExtDataMode);
}
/**
**************************************************************************************
* @brief xc_adc_data_average
* @details Calculate the average of a set of data
* @param[in] data : The data to be averaged len : Take the number of averages
* @param[out] void
* @retval average
***************************************************************************************
*/
uint16_t xc_adc_data_average(uint16_t *data, uint16_t len)
{
uint16_t add_cnt = 0;
uint32_t sum_data = 0;
uint8_t filter_cnt = 0;
filter_cnt = len / 4;
for(int i = 0; i < len - 1; i++)
{
for(int j = 0; j < len - i - 1; j++)
{
if(data[j] > data[j + 1])
{
uint16_t temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
for(int i = filter_cnt; i < len - filter_cnt; i++)
{
sum_data += data[i];
add_cnt++;
}
if(0 == add_cnt)
{
return 0xffff;
}
else
{
return sum_data / add_cnt;
}
}
/**
**************************************************************************************
* @brief xc_adc_data_average
* @details Select and initialize the GPIO port based on the channel
* @param[in] Channel : adc Channel
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_channel_gpio_config(ADC_ChannelTypeDef_t Channel)
{
GPIO_InitCfg_t GPIO_InitCfg;
GPIO_InitCfg.Mux = GPIO_Mux0;
GPIO_InitCfg.FunSel = GPIO_Dx;
GPIO_InitCfg.Dir = GPIO_DIR_INPUT;
GPIO_InitCfg.Pull = GPIO_NOPULL;
GPIO_InitCfg.Int = NOT_INT;
switch(Channel)
{
case 0:
case 1:
case 2:
case 3:
{
GPIO_InitCfg.Pin = GPIO_21 - Channel;
}
break;
case 4:
{
GPIO_InitCfg.Pin = GPIO_0;
}
break;
case 5:
{
GPIO_InitCfg.Pin = GPIO_1;
}
break;
case 6:
{
GPIO_InitCfg.Pin = GPIO_4;
}
break;
case 7:
{
GPIO_InitCfg.Pin = GPIO_5;
}
break;
case 10:
{
GPIO_InitCfg.Pin = GPIO_2;
}
break;
case 11:
{
GPIO_InitCfg.Pin = GPIO_3;
}
break;
default:
break;
}
xc_gpio_init(&GPIO_InitCfg);
}
/**
**************************************************************************************
* @brief xc_adc_startgetvalue
* @details The corresponding ADC sampling value is obtained according to the channel
* @param[in] Channel : The ADC sampling channel to be obtained
* @param[in] *adc_val: ADC sample storage area
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_start_get_value(ADC_ChannelTypeDef_t Channel, uint16_t *adc_val)
{
uint32_t val;
ADC_FIFO_TypeDef_t *fifo_val = NULL;
uint32_t time_out = 100000;
uint8_t adc_count = 0;
uint16_t vvol;
*adc_val = 0;
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE);
adc_chan_ctl__select_chan__setf(Channel);
adc_fifo_ctl__read_req_thresh__setf(ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8);
xc_adc_fifo_flush();
adc_int_set(adc_int_get());
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_ENABLE);
val = adc_int_raw_get();
while(((val & ADC_INT_READ_REQ_INT_SET) != ADC_INT_READ_REQ_INT_SET) &&
time_out)
{
__nop();
val = adc_int_raw_get();
time_out--;
}
if(time_out == 0)
{
DEBUG("adc time_out\n");
return;
}
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE);
fifo_val = (ADC_FIFO_TypeDef_t *)&val;
for(int t = 0; t < ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8; t++)
{
val = adc_fifo_get();
if(fifo_val->chanel_1 != fifo_val->chanel_2)
{
//DEBUG("channel error :%d\n", t);
return;
}
if(fifo_val->chanel_1 != Channel)
{
//DEBUG("channel error :%d\n", t);
return;
}
adc_value[adc_count++] = fifo_val->value_1;
adc_value[adc_count++] = fifo_val->value_2;
// DEBUG("adc_value :%d\n", fifo_val->value_1);
// DEBUG("adc_value :%d\n", fifo_val->value_2);
}
vvol = xc_adc_data_average(adc_value, adc_count);
*adc_val = vvol;
if(vvol == 0)
{
*adc_val = vvol + 1;
}
}
/**
**************************************************************************************
* @brief xc_adc_enable
* @details Start adc sampling
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_enable(void)
{
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_ENABLE) ;
}
/**
**************************************************************************************
* @brief xc_adc_disable
* @details Stop adc sampling
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_disable(void)
{
adc_main_ctl__adc_en__setf(ADC_MAIN_CTL_ADC_EN_DISABLE) ;
}
/**
**************************************************************************************
* @brief xc_adc_enable_it
* @details Enable adc interrupt
* @param[in] it
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_enable_it(uint8_t it)
{
adc_int_en_set(it) ;
}
void xc_adc_disable_it(uint8_t it)
{
adc_int_en_set(it) ;
}
/**
**************************************************************************************
* @brief xc_adc_fifo_req_len_set
* @details fifo receive length Settings for adc
* @param[in] len : fifo length
(ADC_FIFO_CTL_READ_REQ_THRESH_LEN_1 ~ ADC_FIFO_CTL_READ_REQ_THRESH_LEN_15)
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_fifo_req_len_set(uint8_t len)
{
adc_fifo_ctl__read_req_thresh__setf(len);
}
/**
**************************************************************************************
* @brief xc_adc_wait_time_set
* @details ADC sampling wait time and interval Settings
* @param[in] timer0: Sampling wait time
* @param[in] timer1: Sampling interval time
ADC switches automatically when activated:
sampling time(sampling frequency) = timer0 + timer1;
(1M sampling(1US) = 0X1 + 31)
timer0 < timer1
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_wait_time_set(uint8_t timer0, uint16_t timer1)
{
adc_timer1_set(timer1);
adc_timer0_set(timer0);
}
/**
**************************************************************************************
* @brief xc_adc_ch_auto_enable
* @details The ADC automatic switchover was enabled
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_ch_auto_enable(void)
{
adc_main_ctl__auto_sw__setf(ADC_MAIN_CTL_AUTO_SW_ENABLE);
}
/**
**************************************************************************************
* @brief xc_adc_ch_auto_enable
* @details Disable the ADC automatic switching function
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_ch_auto_disable(void)
{
adc_main_ctl__auto_sw__setf(ADC_MAIN_CTL_AUTO_SW_DISABLE);
}
/**
**************************************************************************************
* @brief xc_adc_ch_auto_set
* @details Set the channel to be switched automatically
* @param[in] ch : Automatic switching channel ( 1-->4 channel ¡ê?A bit represents a channel )
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_ch_auto_set(uint8_t ch)
{
adc_chan_ctl__chan_auto__setf(ch);
}
/**
**************************************************************************************
* @brief xc_adc_ch_auto_set
* @details ADC channel selection for non-automatic switching channels
* @param[in] ch : 0 - 13(ADC_CH0_PIN21 - ADC_CH13_PIN6)
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_ch_not_auto_set(uint8_t ch)
{
adc_chan_ctl__select_chan__setf(ch);
}
/**
**************************************************************************************
* @brief xc_adc_it_set
* @details ADC Interrupt setting
* @param[in] it :
* Bits Field Name Reset Value
* ----- ------------------ -----------
* 1 FIFO_ERROR_INT 0
* 0 READ_REQ_INT 0
*
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_it_set(uint8_t it)
{
adc_int_set(it);
}
/**
**************************************************************************************
* @brief xc_adc_it_get
* @details Gets the ADC interrupt enable
* @param[in] void
* @param[out] void
* @retval nterrupt enable register
***************************************************************************************
*/
uint8_t xc_adc_it_get(void)
{
return adc_int_get();
}
/**
**************************************************************************************
* @brief xc_adc_data_get
* @details Get ADC sampling data
* @param[in] void
* @param[out] void
* @retval adc fifo data
***************************************************************************************
*/
uint32_t xc_adc_data_get(void)
{
return adc_fifo__fifo_dout__getf();
}
/**
**************************************************************************************
* @brief xc_adc_it_collectval_set
* @details ADC interrupts to save data
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_adc_it_collectval_set(uint16_t val)
{
adc_it_val = val;
}
/**
**************************************************************************************
* @brief xc_adc_it_collectval_get
* @details Gets the data saved by the ADC interrupt
* @param[in] void
* @param[out] void
* @retval adc_it_val
***************************************************************************************
*/
uint16_t xc_adc_it_collectval_get(void)
{
return adc_it_val;
}
/**
**************************************************************************************
* @brief GADC_Handler
* @details ADC interrupts the callback function
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void GADC_Handler(void)
{
adc_intr_callback();
adc_int_set(adc_int_get());
}
/**
**************************************************************************************
* @brief adc_intr_callback
* @details ADC interrupts the callback function that gets ADC sampled data
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
__WEAK void adc_intr_callback(void)
{
uint32_t adc_int;
uint32_t val;
uint8_t adc_count = 0;
ADC_FIFO_TypeDef_t *fifo_val = NULL;
uint8_t channel = adc_chan_ctl__select_chan__getf();
adc_int = adc_int_get();
if(!(adc_int & (ADC_INT_READ_REQ_INT_SET | ADC_INT_FIFO_ERROR_INT_SET)))
{
// DEBUG("adc error\n");
return;
}
fifo_val = (ADC_FIFO_TypeDef_t *)&val;
for(int t = 0; t < adc_fifo_ctl__read_req_thresh__getf(); t++)
{
val = adc_fifo_get();
if(fifo_val->chanel_1 != fifo_val->chanel_2)
{
DEBUG("channel error :%d\n", t);
break;
}
if(fifo_val->chanel_1 != channel)
{
DEBUG("channel error :%d\n", t);
break;
}
adc_value[adc_count++] = fifo_val->value_1;
adc_value[adc_count++] = fifo_val->value_2;
}
val = xc_adc_data_average(adc_value, adc_count);
xc_adc_it_collectval_set(val);
adc_chan_ctl__select_chan__setf(channel);
}
@@ -0,0 +1,250 @@
/*!
* \file xc_drv_adc.h
*
* \brief The header of xc_drv_adc.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_ADC_H_
#define _XC_DRV_ADC_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define ADC_FIFO_DOUT_LEN 0x10UL
#define ADC_TIMER 4
#define ADC_MAIN_CTL_AUTO_SW_ENABLE (0x01UL)
#define ADC_MAIN_CTL_AUTO_SW_DISABLE (0x00UL)
#define ADC_MAIN_CTL_ADC_EN_ENABLE (0x01UL)
#define ADC_MAIN_CTL_ADC_EN_DISABLE (0x00UL)
#define ADC_CHAN_CTL_CHAN_1_SET (0x01UL)
#define ADC_CHAN_CTL_CHAN_2_SET (0x02UL)
#define ADC_CHAN_CTL_CHAN_3_SET (0x04UL)
#define ADC_CHAN_CTL_CHAN_4_SET (0x08UL)
#define ADC_FIFO_CTL_FIFO_FLUSH_SET (0x01UL)
#define ADC_FIFO_CTL_FIFO_FLUSH_RESET (0x00UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_1 (0x01UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_2 (0x02UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_3 (0x03UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_4 (0x04UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_5 (0x05UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_6 (0x06UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_7 (0x07UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_8 (0x08UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_9 (0x09UL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_10 (0x0AUL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_11 (0x0BUL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_12 (0x0CUL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_13 (0x0DUL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_14 (0x0EUL)
#define ADC_FIFO_CTL_READ_REQ_THRESH_LEN_15 (0x0FUL)
#define ADC_INT_FIFO_ERROR_INT_SET (0x01UL<<0x01UL)
#define ADC_INT_READ_REQ_INT_SET (0x01UL<<0x00UL)
#define ADC_EXT_EDGE_SEL_INTER (0x00UL)
#define ADC_EXT_EDGE_SEL_EXTERN_RISE (0x01UL)
#define ADC_EXT_EDGE_SEL_EXTERN_FALL (0x02UL)
#define ADC_EXT_EDGE_SEL_EXTERN_BOTH (0x03UL)
#define ADC_EXT_TRIGGER_SEL_PWM0 (0x00UL)
#define ADC_EXT_TRIGGER_SEL_PWM1 (0x01UL)
#define ADC_EXT_TRIGGER_SEL_PWM2 (0x02UL)
#define ADC_EXT_TRIGGER_SEL_PWM3 (0x03UL)
#define ADC_EXT_TRIGGER_SEL_PWM4 (0x04UL)
#define ADC_EXT_TRIGGER_SEL_PWM5 (0x05UL)
#define ADC_EXT_TRIGGER_SEL_PWM_BRK1 (0x06UL)
#define ADC_EXT_TRIGGER_SEL_PWM_BRK2 (0x07UL)
#define ADC_EXT_DATA_MODE_32BIT (0x00UL)
#define ADC_EXT_DATA_MODE_LOW16BIT (0x01UL)
#define ADC_EXT_SAMPLE_NUM_1 (0x00UL)
#define ADC_EXT_SAMPLE_NUM_2 (0x01UL)
#define ADC_EXT_SAMPLE_NUM_3 (0x02UL)
#define ADC_EXT_SAMPLE_NUM_4 (0x03UL)
#define ADC_EXT_SAMPLE_NUM_5 (0x04UL)
#define ADC_EXT_SAMPLE_NUM_6 (0x05UL)
#define ADC_EXT_SAMPLE_NUM_7 (0x06UL)
#define ADC_EXT_SAMPLE_NUM_8 (0x07UL)
#define ADC_EXT_SAMPLE_NUM_9 (0x08UL)
#define ADC_EXT_SAMPLE_NUM_10 (0x09UL)
#define ADC_EXT_SAMPLE_NUM_11 (0x0AUL)
#define ADC_EXT_SAMPLE_NUM_12 (0x0BUL)
#define ADC_EXT_SAMPLE_NUM_13 (0x0CUL)
#define ADC_EXT_SAMPLE_NUM_14 (0x0DUL)
#define ADC_EXT_SAMPLE_NUM_15 (0x0EUL)
#define ADC_EXT_SAMPLE_NUM_16 (0x0FUL)
#define ADC_RF_CTL_PD_GADC_POWERDOWN (0x01UL)
#define ADC_RF_CTL_PD_GADC_WAKWUP (0x00UL)
#define ADC_RF_CTL_REFSEL_AVDD (0x01UL)
#define ADC_RF_CTL_REFSEL_2_4 (0x00UL)
#define ADC_RF_CTL_ADC_CTL_MUX_DIGITAL (0x01UL)
#define ADC_RF_CTL_ADC_CTL_MUX_SPI (0x00UL)
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef struct
{
unsigned int value_2 : 12;
unsigned int chanel_2 : 4;
unsigned int value_1 : 12;
unsigned int chanel_1 : 4;
} ADC_FIFO_TypeDef_t;
typedef enum
{
ADC_CH0_PIN21 = 0,
ADC_CH1_PIN20 = 1,
ADC_CH2_PIN19 = 2,
ADC_CH3_PIN18 = 3,
ADC_CH4_PIN0 = 4,
ADC_CH5_PIN1 = 5,
ADC_CH6_PIN4 = 6,
ADC_CH7_PIN5 = 7,
ADC_CH8_NOPIN = 8, // cmp0
ADC_CH9_NOPIN = 9, // cmp1
ADC_CH10_NOPIN = 10, // cmp2
ADC_CH11_NOPIN = 11, // pga
ADC_CH12_PIN2 = 12,
ADC_CH13_PIN3 = 13,
ADC_CH14_PIN6 = 14,
ADC_CH15_PIN7 = 15,
} ADC_ChannelTypeDef_t;
typedef enum
{
ADC_REF_VOL_2_48V = 0,
ADC_REF_VOL_3_3V = 1,
} ADC_RefVolTypeDef_t;
typedef enum
{
ADC_FREQ_8M = 0x00,
ADC_FREQ_4M = 0x01,
ADC_FREQ_2M = 0x03,
ADC_FREQ_1M = 0x07,
ADC_FREQ_500K = 0x0f,
} ADC_FreqTypeDef_t;
typedef enum
{
// Single-ended mode. PSELN will be ignored, negative input to ADC shorted
// to GND.
ADC_SAMPMODE_SINGLE_ENDED = 0x00UL,
ADC_SAMPMODE_DIFFERENTIAL = 0x01UL // Differential mode.
} ADC_SampModeTypeDef_t;
typedef enum
{
ADC_SAMPEDGE_FALL = 0x00UL, ///< Single-ended mode. PSELN will be ignored,
///< negative input to ADC shorted to GND.
ADC_SAMPEDGE_RISE = 0x01UL ///< Differential mode.
} ADC_SampEdgeTypeDef_t;
typedef struct
{
ADC_RefVolTypeDef_t RefVol;
ADC_FreqTypeDef_t Freq;
ADC_SampEdgeTypeDef_t SampEdge;
uint32_t ExtSampleNum;
uint32_t ExtDataMode;
uint32_t ExtTriggerSel;
uint32_t ExtEdgeSel;
} ADC_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
static __inline void xc_adc_fifo_flush(void)
{
adc_fifo_ctl__fifo_flush__setf(ADC_FIFO_CTL_FIFO_FLUSH_SET);
adc_fifo_ctl__fifo_flush__setf(ADC_FIFO_CTL_FIFO_FLUSH_RESET);
}
static __inline void xc_adc_refvol_set(uint8_t ref_vol)
{
adc_rf_ctl__pd_adc__setf(DISABLE);
if (ref_vol == ADC_REF_VOL_2_48V) {
adc_rf_ctl__gadc_vref_sel__setf(ADC_RF_CTL_REFSEL_2_4);
} else {
adc_rf_ctl__gadc_vref_sel__setf(ADC_RF_CTL_REFSEL_AVDD);
}
}
static __inline void xc_adc_freq_set(uint8_t freq)
{
adc_rf_ctl__adc_clkdiv__setf(freq);
adc_rf_ctl__adc_ctl_mux__setf(ADC_RF_CTL_ADC_CTL_MUX_DIGITAL);
}
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_adc_init(ADC_InitCfg_t *adc_cfg);
void xc_adc_start_get_value(ADC_ChannelTypeDef_t Channel, uint16_t *adc_val);
void xc_adc_enable_it(uint8_t it);
void xc_adc_disable_it(uint8_t it);
void xc_adc_fifo_req_len_set(uint8_t len);
void xc_adc_wait_time_set(uint8_t timer0, uint16_t timer1);
void xc_adc_ch_auto_enable(void);
void xc_adc_ch_auto_disable(void);
void xc_adc_ch_auto_set(uint8_t ch);
void xc_adc_ch_not_auto_set(uint8_t ch);
void xc_adc_it_set(uint8_t it);
uint8_t xc_adc_it_get(void);
void xc_adc_ch_not_auto_set(uint8_t ch);
uint32_t xc_adc_data_get(void);
void xc_adc_enable(void);
void xc_adc_disable(void);
uint16_t xc_adc_it_collectval_get(void);
void xc_adc_channel_gpio_config(ADC_ChannelTypeDef_t Channel);
void adc_intr_callback(void);
#endif
@@ -0,0 +1,219 @@
/*!
* \file xc_drv_aotimer.c
*
* \brief Target xinchip aotimer driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_aotimer.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static bool aotimer_rst_flag = false;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
aotimer_handler_callback aotimer_n_callback[2] = {aotimer0_callback,
aotimer1_callback};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
**************************************************************************************
* @brief xc_aotimer_init
* @details Example Initialize the aotimer according to its number
* @param[in] reg_idx : aotimer number idx; AOTIMER0_IDX or AOTIMER1_IDX
* @param[in] *init_cfg : This is the structure parameter that the AOTimer initializes
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_aotimer_init(uint8_t reg_idx, AOTimer_InitCfg_t *init_cfg)
{
if (aotimer_rst_flag == false) {
cprao_aon_clken_grctl__timer_ao_pclk_en__setf(ENABLE);
aotimer_rst_flag = true;
}
//The clocks for ao timer0 and ao timer1 need to be turned on at the same time.
if (AOTIMER0_IDX == reg_idx) {
cprao_aon_clken_grctl__timer0_ao_pclk_en__setf(ENABLE);
cprao_aon_clken_grctl__timer1_ao_pclk_en__setf(ENABLE);
} else if (AOTIMER1_IDX == reg_idx) {
cprao_aon_clken_grctl__timer0_ao_pclk_en__setf(ENABLE);
cprao_aon_clken_grctl__timer1_ao_pclk_en__setf(ENABLE);
}
cpr_lp_ctl__timer_sysclk_sel__setf(ENABLE);
aotimer_tcr__tes__setf(reg_idx, DISABLE);
aotimer_tcr__tms__setf(reg_idx, (uint8_t)init_cfg->aotimer_mode);
(void)aotimer_tic__tic__getf(reg_idx);
}
/**
**************************************************************************************
* @brief xc_aotimer_us_to_ticks
* @details Returns the number of ticks according to the time to be set by the aotimer
* @param[in] us : Time set by the timer (Microsecond is the smallest unit)
* @param[out] void
* @retval ticks ( Tick count )
***************************************************************************************
*/
static uint32_t xc_aotimer_us_to_ticks(uint32_t us)
{
uint32_t ticks = AOTIMER_TICK_CAL(us);
if (ticks < AOTIMER_MIN_TLC_VAL)
ticks = AOTIMER_MIN_TLC_VAL;
return ticks;
}
/**
**************************************************************************************
* @brief xc_aotimer_set_value
* @details Set the timing time according to the aotimer number
* @param[in] reg_idx : aotimer number idx; AOTIMER0_IDX or AOTIMER1_IDX
* @param[in] us : Time set by the timer (Microsecond is the smallest unit)
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_aotimer_set_value(uint8_t reg_idx, uint32_t us)
{
uint32_t ticks = xc_aotimer_us_to_ticks(us);
aotimer_tcr__tes__setf(reg_idx, AOTIMER_TCR_TES_DISABLE);
aotimer_tlc_set(reg_idx, ticks);
}
/**
**************************************************************************************
* @brief xc_aotimer_start
* @details Start the timer according to the aotimer number
* @param[in] reg_idx : aotimer number idx; AOTIMER0_IDX or AOTIMER1_IDX
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_aotimer_start(uint8_t reg_idx)
{
NVIC_EnableIRQ( (IRQn_Type)(TIMER_AO0_IRQn+reg_idx) );
aotimer_tcr__tim__setf(reg_idx, 0);
aotimer_tcr__tes__setf(reg_idx, ENABLE);
// Wait for timer enable
while(aotimer_tcr__tes__getf(reg_idx) != ENABLE)
{
__nop();
}
}
/**
**************************************************************************************
* @brief xc_aotimer_stop
* @details Stop the timer according to the aotimer number
* @param[in] reg_idx : aotimer number idx; AOTIMER0_IDX or AOTIMER1_IDX
* @param[out] void
* @retval void
***************************************************************************************
*/
void xc_aotimer_stop(uint8_t reg_idx)
{
aotimer_tcr__tes__setf(reg_idx, DISABLE);
}
/**
**************************************************************************************
* @brief AOTIMER0_Handler
* @details AOTIMER0 Interrupt function
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void AOTIMER0_Handler(void)
{
cprao_aon_reg1__timer_ao_sleep_clksw__setf(0);
(void)aotimer_tic__tic__getf(AOTIMER0_IDX);
if (aotimer_n_callback[0] != NULL)
aotimer_n_callback[0](NULL);
}
/**
**************************************************************************************
* @brief AOTIMER1_Handler
* @details AOTIMER1 Interrupt function
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
void AOTIMER1_Handler(void)
{
cprao_aon_reg1__timer_ao_sleep_clksw__setf(0);
(void)aotimer_tic__tic__getf(AOTIMER1_IDX);
if (aotimer_n_callback[1] != NULL)
aotimer_n_callback[1](NULL);
}
/**
**************************************************************************************
* @brief aotimer0_callback
* @details AOTIMER0 Interrupt the callback function
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
__WEAK void aotimer0_callback(void *context)
{ /* AOTimer0 中断回调处理事件 */
}
/**
**************************************************************************************
* @brief aotimer1_callback
* @details AOTIMER1 Interrupt the callback function
* @param[in] void
* @param[out] void
* @retval void
***************************************************************************************
*/
__WEAK void aotimer1_callback(void *context)
{ /* AOTimer1 中断回调处理事件 */
}
@@ -0,0 +1,78 @@
/*!
* \file xc_drv_aotimer.h
*
* \brief The header of xc_drv_aotimer.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_AOTIMER_H_
#define _XC_DRV_AOTIMER_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define AOTIMER_MIN_TLC_VAL 0x04
#define AOTIMER_TCR_TIM_DISABLE (0x00UL)
#define AOTIMER_TCR_TIM_ENABLE (0x01UL)
#define AOTIMER_TCR_TES_ENABLE (0x01UL)
#define AOTIMER_TCR_TES_DISABLE (0x00UL)
#define AOTIMER_TICK_CAL(us) ((CLOCK_RC_LFCLK_IN_32K / 1000) * us / 1000)
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
AOTIMER_MODE_SINGLE = 0,
AOTIMER_MODE_CYCLE = 1,
} AOTimer_ModeTypeDef;
typedef struct
{
AOTimer_ModeTypeDef aotimer_mode;
} AOTimer_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
typedef void (*aotimer_handler_callback)(void *context);
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_aotimer_init(uint8_t reg_idx, AOTimer_InitCfg_t *init_cfg);
void xc_aotimer_set_value(uint8_t reg_idx, uint32_t us);
void xc_aotimer_start(uint8_t reg_idx);
void xc_aotimer_stop(uint8_t reg_idx);
void aotimer0_callback(void *context);
void aotimer1_callback(void *context);
#endif
@@ -0,0 +1,318 @@
/*!
* \file xc_drv_calib.c
*
* \brief Target xc calib driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_calib.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define RC_ADJ_VAL_MIN 0x0
#define RC_ADJ_VAL_MID 0x1fff
#define RC_ADJ_VAL_MAX 0x3fff
#define RANGE_LPO_RTM 0x400
#define GEARS_HZ 1.56f
#define _32K_STAND_HZ 32000
#define CALIB_NUM 50 // ms
#define CALIB_TIME_MS 10 // ms
#define CALIB_DELAY_CHECK (CALIB_TIME_MS + 20) // ms
#define CALIB_STEP_CYCLE_32K (CALIB_TIME_MS * 32)
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static volatile uint32_t mid = RC_ADJ_VAL_MID; // MID_LPO_RTM;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief xc_rc32k_calib_init
* @details RC32k calibration initialization
*
* @param uint16_t - rc_adj_val
* @retval void
*/
void xc_rc32k_calib_init(uint16_t rc_adj_val)
{
if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M)) {
cpr_ctl_pclk_grctl__ctl_pclk_gr_upd__setf(0x1UL);
cpr_ctl_pclk_grctl__ctl_pclk_gr__setf(4U);
} else if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_96M)) {
cpr_ctl_pclk_grctl__ctl_pclk_gr__setf(2U);
cpr_ctl_pclk_grctl__ctl_pclk_gr_upd__setf(0x1UL);
} else if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_16M)) {
cpr_ctl_pclk_grctl__ctl_pclk_gr_upd__setf(0x1UL);
cpr_ctl_pclk_grctl__ctl_pclk_gr__setf(8U);
}
cpr_ctlapbclken_grctl__rtc_pclk_en__setf(0x1UL);
cprao_aon_clken_grctl__rtc_clk_en__setf(0x1UL);
rtc_rccal_lfcfg_set(0x100031);
if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_16M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M)) {
rtc_rccal_hfcfg_set(25000);
rtc_rccal_lim1_set(3);
rtc_rccal_lim2_set(13);
} else if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_96M)) {
rtc_rccal_hfcfg_set(37500);
rtc_rccal_lim1_set(4);
rtc_rccal_lim2_set(19);
}
rtc_rccal_adj_step_set(0x1404);
rtc_rccal_adj_val_set(0x1fff);
rtc_rccal_adj_cfg_set(0x1fff4000 | rc_adj_val);
rtc_rccal_intsta_set(0x03);
rtc_rccal_inten_set(0x01);
for (uint16_t dly = 0; dly < 1000; dly++)
;
rtc_rccal_en_set(0x01);
}
/**
* @brief xc_flfclk_calcu
* @details Frequency lfclk value calculation
*
* @param uint32_t - hfcnt_val
* @retval uint16_t - f_lfclk
*/
uint16_t xc_flfclk_calcu(uint32_t hfcnt_val)
{
uint32_t hfcnt_load = rtc_rccal_hfcfg_get();
uint32_t lfdiv = rtc_rccal_lfcfg_get();
uint8_t hfcnt_dir = (hfcnt_val >> 31);
uint16_t f_lfclk = 0;
if (hfcnt_dir == 0) {
if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_16M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M)) {
f_lfclk =
CLOCK_HFCLK_IN_16M * (lfdiv + 1) / (hfcnt_load - hfcnt_val);
} else if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_96M)) {
f_lfclk = 24000000 * (lfdiv + 1) / (hfcnt_load - hfcnt_val);
}
} else {
if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_16M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M)) {
f_lfclk = CLOCK_HFCLK_IN_16M * (lfdiv + 1) /
(hfcnt_load + hfcnt_val - 0x80000000);
} else if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_96M)) {
f_lfclk =
24000000 * (lfdiv + 1) / (hfcnt_load + hfcnt_val - 0x80000000);
}
}
return f_lfclk;
}
/**
* @brief xc_rc32k_freq_scope
* @details RC32k frequency scope
*
* @param uint16_t - freq
* @retval eLFREQ_Sta - ret
*/
eLFREQ_Sta xc_rc32k_freq_scope(uint16_t freq)
{
eLFREQ_Sta ret = LFREQ_UNKNOW;
uint16_t offset = (CLOCK_RC_LFCLK_IN_32K * 2 / 100);
uint16_t rc32_offset_min = (CLOCK_RC_LFCLK_IN_32K - offset);
uint16_t rc32_offset_max = CLOCK_RC_LFCLK_IN_32K;
if (freq < rc32_offset_min)
ret = LFREQ_LOWER;
else if (freq >= rc32_offset_max)
ret = LFREQ_HIGHER;
else
ret = LFREQ_GOOD;
return ret;
}
/**
* @brief RC32k_Calib_by_hw
* @details Calibrating RC32k through hardware.
*
* @param uint16_t - freq
* @retval eLFREQ_Sta - ret
*/
void xc_rc32k_calib_by_hw(void)
{
uint16_t f_lfclk = 0;
uint8_t rccal_int_sta;
eLFREQ_Sta f_lf_sta;
xc_rc32k_calib_init(mid);
while (1) {
do {
rccal_int_sta = rtc_rccal_intsta_get();
} while (!(rccal_int_sta & 0x01));
rtc_rccal_inten_set(0x00);
rtc_rccal_intsta_set(rccal_int_sta);
f_lfclk = xc_flfclk_calcu(rtc_rccal_hfcnt_val_get());
f_lf_sta = xc_rc32k_freq_scope(f_lfclk);
if (LFREQ_GOOD != f_lf_sta) {
rtc_rccal_en_set(0x00);
// XC_RTC->RCCAL_EN = 0x00;
if (f_lf_sta == LFREQ_LOWER) {
mid += 100;
if (mid > RC_ADJ_VAL_MAX) {
mid = RC_ADJ_VAL_MIN;
}
} else {
mid -= 10;
if (mid < 10) {
mid = RC_ADJ_VAL_MAX;
}
}
rtc_rccal_adj_cfg_set(0x1fff4000 | mid);
rtc_rccal_inten_set(0x01);
rtc_rccal_en_set(0x01);
} else {
DEBUG("f_lfclk: %d\n", f_lfclk);
break;
}
}
rtc_rccal_en_set(0x00);
rtc_rccal_adj_cfg_set(0x00001fff);
rtc_rccal_adj_cfg__freq_adj_offset__setf(mid);
rtc_rccal_adj_cfg__freq_adj_hw_clr__setf(0x01);
rtc_rccal_intsta_set(0x03);
for (uint16_t dly = 0; dly < 1000; dly++)
;
rtc_rccal_en_set(0x01);
}
/**
* @brief rc32k_calib_by_soft
* @details Calibrate RC32k by software.
*
* @param uint16_t - freq
* @retval eLFREQ_Sta - ret
*/
void xc_rc32k_calib_by_soft(void)
{
uint32_t f_lfclk = 0;
uint32_t t32k_cnt = 0;
uint8_t ao_intr;
xc_rc32k_calib_init(mid);
rtc_rccal_inten_set(0x00);
rtc_rccal_intsta_set(0x03);
while (1) {
rtc_ao_timer_ctl_set(0);
rtc_ao_timer_ctl__rtc_ao_timer_value__setf(CALIB_STEP_CYCLE_32K);
rtc_ao_timer_ctl__rtc_freq_timer_en__setf(1);
do {
ao_intr = rtc_all_intr_ao_get();
} while ((ao_intr & 0x20) == 0);
t32k_cnt = rtc_freq_32k_timer_val_get();
rtc_ao_timer_ctl__rtc_ao_timer_clr__setf(0x1UL);
rtc_ao_timer_ctl_set(0);
if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_16M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M)) {
f_lfclk = (uint32_t)((((float)((16.0) * CALIB_STEP_CYCLE_32K)) /
t32k_cnt) *
1000000);
} else if ((xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) ||
(xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_96M)) {
f_lfclk = (uint32_t)((((float)((24.0) * CALIB_STEP_CYCLE_32K)) /
t32k_cnt) *
1000000);
}
if (f_lfclk > _32K_STAND_HZ) {
mid = mid - ((uint32_t)(((float)(f_lfclk - _32K_STAND_HZ)) /
(float)GEARS_HZ));
} else if (f_lfclk < _32K_STAND_HZ) {
mid = mid + ((uint32_t)(((float)(_32K_STAND_HZ - f_lfclk)) /
(float)GEARS_HZ));
}
// DEBUG("f_lfclk: %d\n", f_lfclk);
rtc_rccal_en_set(0x00);
rtc_rccal_adj_cfg_set(0x1fff4000 | mid);
rtc_rccal_en_set(0x01);
if (f_lfclk == _32K_STAND_HZ)
break;
}
}
@@ -0,0 +1,73 @@
/*!
* \file xc_drv_calib.h
*
* \brief The header of xc_drv_calib.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_CALIB_H_
#define _XC_DRV_CALIB_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define RC32K_CALIB_BY_HW 0
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
LFREQ_GOOD = 0,
LFREQ_LOWER,
LFREQ_HIGHER,
LFREQ_UNKNOW = 0xff
} eLFREQ_Sta;
typedef enum
{
CLOCK_RC_LFCLK_IN_32K = 32000,
CLOCK_XTAL_LFCLK_IN_32K = 32768,
} CLOCK_LowFreq_In_Typedef;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_rc32k_calib_by_hw(void);
void xc_rc32k_calib_by_soft(void);
#endif // _XC_DRV_AOTIMER_H_
@@ -0,0 +1,518 @@
/*!
* \file xc_drv_clock.c
*
* \brief Target xinchip clock driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_clock.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
CLOCK_InitCfg_t clock_cb;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief xc_clock_bbpll_common_cfg
* @details Common Settings for frequency doubling
* @param[in] void
* @param[in] void
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_bbpll_common_cfg(void)
{
cpr_bt_clk_ctl__bt_clk_en__setf(ENABLE);
cpr_ctlapbclken_grctl__bt_pclk_en__setf(ENABLE);
bt_rf_pm_reg__bt_en_pm__setf(ENABLE);
cprao_aon_coreldo_en_set(ENABLE);
}
/**
****************************************************************************************
* @brief xc_clock_bbpll_freq_cfg
* @details Initializes the frequency doubling clock
* @param[in] hfclk_src :Source clock
* @param[in] loopdiv :clock multiplier factor
* @param[in] clk_div :Frequency division coefficient
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_bbpll_freq_cfg(CLOCK_HFCLK_Src_Typedef hfclk_src, uint16_t loopdiv,
uint8_t clk_div)
{
if (CLOCK_HFCLK_SRC_RC == hfclk_src)
rf_ana27__bbpll_16m_sel__setf(ENABLE);
else
rf_ana27__bbpll_16m_sel__setf(DISABLE);
if(loopdiv != 0x03)
rf_ana27__bbpll_core_96m_en__setf(ENABLE);
else
rf_ana27__bbpll_core_96m_en__setf(DISABLE);
rf_ana26__bbpll_loopdiv__setf(loopdiv);
rf_ana26__clk_bbpll_en__setf(ENABLE);
rf_ana26__clk_bbpll_rstn__setf(ENABLE);
rf_ana26__bbpll_en__setf(ENABLE);
rf_ana26__bbpll_core_64m_en__setf(ENABLE);
cpr_rf_reg4__bbpll_clk_div__setf(clk_div);
cpr_rf_reg4__bbpll_clk_en__setf(ENABLE);
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m
* @details The clock is set to RC16M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m(CLOCK_InitCfg_t *cb)
{
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_RC16M);
cb->hfclk_in = CLOCK_HFCLK_IN_16M;
cb->systick_unit = SYSTICK_UNIT_IN_16M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_32m
* @details RC16M clock overclocked to 32M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_32m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x08, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_32M;
cb->systick_unit = SYSTICK_UNIT_IN_32M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_48m
* @details RC16M clock overclocked to 48M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_48m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x0C, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_48M;
cb->systick_unit = SYSTICK_UNIT_IN_48M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_64m
* @details RC16M clock overclocked to 64M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_64m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x08, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_64M;
cb->systick_unit = SYSTICK_UNIT_IN_64M;
}
/**
****************************************************************************************
* @brief xc_clock_set_rc16m_bbpll_96m
* @details RC16M clock overclocked to 96M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_rc16m_bbpll_96m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x0C, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_96M;
cb->systick_unit = SYSTICK_UNIT_IN_96M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_16m
* @details osc32M Clock overclocked to 16M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_16m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x06, 0x05);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_16M;
cb->systick_unit = SYSTICK_UNIT_IN_16M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_div_16m
* @details osc32M Clock divided into 16M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_div_16m(CLOCK_InitCfg_t *cb)
{
//M0_FCLK
cpr_m0_fclk_ctl__m0_fclk_div_p__setf(0x1);
cpr_m0_fclk_ctl__m0_fclk_direct_sw__setf(0x1);
//CTL_PCLK
cpr_ctl_pclk_grctl__ctl_pclk_gr__setf(0x8);
cpr_ctl_pclk_grctl__ctl_pclk_gr_upd__setf(0x1);
cprao_aon_bbldo_adj_set(0x3c);
/* The value needs to be configured to 7,
otherwise the current drop will be slower during sleep
and the clock accuracy of the rc32k will be affected.
*/
cprao_aon_lpoldo_adj_set(0x7);
cb->hfclk_in = CLOCK_HFCLK_IN_16M;
cb->systick_unit = SYSTICK_UNIT_IN_16M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m
* @details The clock is set to osc32M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m(CLOCK_InitCfg_t *cb)
{
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_OSC32M);
cb->hfclk_in = CLOCK_HFCLK_IN_32M;
cb->systick_unit = SYSTICK_UNIT_IN_32M;
}
#if (CONFIG_HFCLK_IS_OSC32M_PLL_32M)
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_32m
* @details osc32M Clock overclocked to 64M and hflck is 32M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_32m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x04, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_32M;
cb->systick_unit = SYSTICK_UNIT_IN_32M;
}
#endif
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_48m
* @details osc32M Clock overclocked to 48M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_48m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x03, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL_DIV);
cb->hfclk_in = CLOCK_HFCLK_IN_48M;
cb->systick_unit = SYSTICK_UNIT_IN_48M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_64m
* @details osc32M Clock overclocked to 64M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_64m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x04, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_64M;
cb->systick_unit = SYSTICK_UNIT_IN_64M;
}
/**
****************************************************************************************
* @brief xc_clock_set_osc32m_bbpll_96m
* @details osc32M Clock overclocked to 96M
* @param[in] CLOCK_InitCfg_t *cb
* @param[in]
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_set_osc32m_bbpll_96m(CLOCK_InitCfg_t *cb)
{
xc_clock_bbpll_common_cfg();
xc_clock_bbpll_freq_cfg(cb->hfclk_src, 0x03, 0x01);
cpr_rf_reg3__mclk_src_sel__setf(CLOCK_SRC_BBPLL);
cb->hfclk_in = CLOCK_HFCLK_IN_96M;
cb->systick_unit = SYSTICK_UNIT_IN_96M;
}
/**
****************************************************************************************
* @brief xc_clock_hfclk_set
* @details High speed clock setting
* @param[in] CLOCK_HFCLK_Src_Typedef hfclk_src
* @param[in] CLOCK_HFCLK_In_Typedef hfclk_in
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_hfclk_set(CLOCK_HFCLK_Src_Typedef hfclk_src,
CLOCK_HFCLK_In_Typedef hfclk_in)
{
uint32_t baudrate, uart_clk, div, mul, clk_ctl, adj_div, m0_fclk_div;
CLOCK_InitCfg_t *pclock_cb = &clock_cb;
pclock_cb->hfclk_src = hfclk_src;
switch (hfclk_src) {
case CLOCK_HFCLK_SRC_RC: {
if (CLOCK_HFCLK_IN_16M == hfclk_in) {
xc_clock_set_rc16m(pclock_cb);
} else if (CLOCK_HFCLK_IN_32M == hfclk_in) {
xc_clock_set_rc16m_bbpll_32m(pclock_cb);
} else if (CLOCK_HFCLK_IN_48M == hfclk_in) {
xc_clock_set_rc16m_bbpll_48m(pclock_cb);
} else if (CLOCK_HFCLK_IN_64M == hfclk_in) {
xc_clock_set_rc16m_bbpll_64m(pclock_cb);
} else if (CLOCK_HFCLK_IN_96M == hfclk_in) {
xc_clock_set_rc16m_bbpll_96m(pclock_cb);
}
} break;
case CLOCK_HFCLK_SRC_XTAL: {
// if(cpr_m0_fclk_ctl__m0_fclk_div__getf( )) {
// cpr_m0_fclk_ctl__m0_fclk_div_p__setf(0);
// cpr_m0_fclk_ctl__m0_fclk_direct_sw__setf(0x1);
// }
if (CLOCK_HFCLK_IN_16M == hfclk_in) {
xc_clock_set_osc32m_div_16m(pclock_cb);
} else if (CLOCK_HFCLK_IN_32M == hfclk_in) {
#if (CONFIG_HFCLK_IS_OSC32M_PLL_32M)
xc_clock_set_osc32m_bbpll_32m(pclock_cb);
#else
xc_clock_set_osc32m(pclock_cb);
#endif
} else if (CLOCK_HFCLK_IN_48M == hfclk_in) {
xc_clock_set_osc32m_bbpll_48m(pclock_cb);
} else if (CLOCK_HFCLK_IN_64M == hfclk_in) {
xc_clock_set_osc32m_bbpll_64m(pclock_cb);
} else if (CLOCK_HFCLK_IN_96M == hfclk_in) {
xc_clock_set_osc32m_bbpll_96m(pclock_cb);
}
} break;
}
m0_fclk_div = cpr_m0_fclk_ctl__m0_fclk_div__getf( );
uart_clk = xc_clock_hfclk_in_get() * (m0_fclk_div+1);
baudrate = cpr_uart0_clk_ctl_get();
mul = (baudrate >> 16) & 0xFFFF;
div = (baudrate & 0xFFFF);
adj_div = uart_clk / 1000000;
clk_ctl = (mul << 16) | (div * adj_div / 32);
cpr_uart0_clk_ctl_set(clk_ctl);
}
/**
****************************************************************************************
* @brief xc_clock_lfclk_set
* @details Low speed clock setting
* @param[in] CLOCK_LFCLK_Src_Typedef lfclk_src
* @param[in] CLOCK_LFCLK_In_Typedef lfclk_in
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_lfclk_set(CLOCK_LFCLK_Src_Typedef lfclk_src,
CLOCK_LFCLK_In_Typedef lfclk_in)
{
clock_cb.lfclk_src = lfclk_src;
clock_cb.lfclk_in = lfclk_in;
if(lfclk_src == CLOCK_LFCLK_SRC_XTAL)
{
GPIO_InitCfg_t gpio_cfg = {0};
gpio_cfg.Mux = GPIO_Mux0;
gpio_cfg.FunSel = GPIO_Dx;
gpio_cfg.Dir = GPIO_DIR_INPUT;
gpio_cfg.Pull = GPIO_NOPULL;
gpio_cfg.Int = NOT_INT;
gpio_cfg.Pin = 20;
xc_gpio_init(&gpio_cfg);
gpio_cfg.Pin = 21;
xc_gpio_init(&gpio_cfg);
cprao_aon_xtl32k_val__xtl32k_v__setf(0x01);
cprao_aon_xtl32k_val__xtl32k_en__setf(ENABLE);
cprao_aon_ctl_clk32k__osc32k_sel__setf(2);
}
else if(lfclk_src == CLOCK_LFCLK_SRC_RC)
{
}
}
/**
****************************************************************************************
* @brief xc_clock_init_cfg
* @details Configure the clock initially
* @param[in] CLOCK_InitCfg_t *clock_cfg
* @param[out] void
* @retval void
****************************************************************************************
*/
void xc_clock_init_cfg(CLOCK_InitCfg_t *clock_cfg)
{
xc_clock_hfclk_set(clock_cfg->hfclk_src, clock_cfg->hfclk_in);
xc_clock_lfclk_set(clock_cfg->lfclk_src, clock_cfg->lfclk_in);
xc_pwr_vol_set();
}
/**
****************************************************************************************
* @brief xc_clock_hfclk_in_get
* @details Gets the current high speed clock ( system clock )
* @param[in]
* @param[out] void
* @retval clock_cb.hfclk_in
****************************************************************************************
*/
CLOCK_HFCLK_In_Typedef xc_clock_hfclk_in_get(void) { return clock_cb.hfclk_in; }
/**
****************************************************************************************
* @brief xc_clock_lfclk_in_get
* @details Gets the current low speed clock ( Low power clock )
* @param[in]
* @param[out] void
* @retval clock_cb.lfclk_in
****************************************************************************************
*/
CLOCK_LFCLK_In_Typedef xc_clock_lfclk_in_get(void) { return clock_cb.lfclk_in; }
/**
****************************************************************************************
* @brief xc_clock_hfclk_src_get
* @details Obtain the current high-speed source clock
* @param[in]
* @param[out] void
* @retval clock_cb.hfclk_src
****************************************************************************************
*/
CLOCK_HFCLK_Src_Typedef xc_clock_hfclk_src_get(void) { return clock_cb.hfclk_src; }
/**
****************************************************************************************
* @brief xc_clock_lfclk_src_get
* @details Obtain the current low-speed source clock
* @param[in]
* @param[out] void
* @retval clock_cb.lfclk_src
****************************************************************************************
*/
CLOCK_LFCLK_Src_Typedef xc_clock_lfclk_src_get(void) { return clock_cb.lfclk_src; }
/**
****************************************************************************************
* @brief xc_systick_unit_get
* @details Obtain the current systick unit
* @param[in]
* @param[out] void
* @retval clock_cb.lfclk_src
****************************************************************************************
*/
Systick_Unit_Typedef xc_systick_unit_get(void) { return clock_cb.systick_unit; }
@@ -0,0 +1,113 @@
/*!
* \file xc_drv_clock.h
*
* \brief The header of xc_drv_clock.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_CLOCK_H_
#define _XC_DRV_CLOCK_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define CLOCK_SRC_OSC32M 0x00
#define CLOCK_SRC_BBPLL 0x01
#define CLOCK_SRC_BBPLL_DIV 0x02
#define CLOCK_SRC_RC16M 0x03
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
CLOCK_LFCLK_SRC_RC = 0, /* Internal 32 KHz RC oscillator. */
CLOCK_LFCLK_SRC_XTAL = 1, /* External 32 KHz crystal oscillator. */
} CLOCK_LFCLK_Src_Typedef;
typedef enum
{
CLOCK_LFCLK_IN_32K = 32000,
CLOCK_LFCLK_IN_32768 = 32768,
} CLOCK_LFCLK_In_Typedef;
typedef enum
{
CLOCK_HFCLK_SRC_RC = 0, /* Internal 16 MHz RC oscillator. */
CLOCK_HFCLK_SRC_XTAL = 1, /* External 32 MHz crystal oscillator. */
} CLOCK_HFCLK_Src_Typedef;
typedef enum
{
CLOCK_HFCLK_IN_16M = 16000000,
CLOCK_HFCLK_IN_32M = 32000000,
CLOCK_HFCLK_IN_48M = 48000000,
CLOCK_HFCLK_IN_64M = 64000000,
CLOCK_HFCLK_IN_96M = 96000000,
CLOCK_HFCLK_IN_128M = 128000000,
} CLOCK_HFCLK_In_Typedef;
typedef enum
{
SYSTICK_UNIT_IN_16M = 16,
SYSTICK_UNIT_IN_32M = 32,
SYSTICK_UNIT_IN_48M = 48,
SYSTICK_UNIT_IN_64M = 64,
SYSTICK_UNIT_IN_96M = 96
} Systick_Unit_Typedef;
typedef struct
{
CLOCK_HFCLK_Src_Typedef hfclk_src;
CLOCK_HFCLK_In_Typedef hfclk_in;
CLOCK_LFCLK_Src_Typedef lfclk_src;
CLOCK_LFCLK_In_Typedef lfclk_in;
Systick_Unit_Typedef systick_unit;
} CLOCK_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern CLOCK_InitCfg_t clock_cb;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_clock_bbpll_common_cfg(void);
void xc_clock_init_cfg(CLOCK_InitCfg_t *clock_cfg);
CLOCK_HFCLK_In_Typedef xc_clock_hfclk_in_get(void);
CLOCK_LFCLK_In_Typedef xc_clock_lfclk_in_get(void);
CLOCK_HFCLK_Src_Typedef xc_clock_hfclk_src_get(void);
CLOCK_LFCLK_Src_Typedef xc_clock_lfclk_src_get(void);
Systick_Unit_Typedef xc_systick_unit_get(void);
#endif // _XC_DRV_CLOCK_H_
@@ -0,0 +1,208 @@
/*!
* \file xc6xxx_conf.h
*
* \brief The header of xc6xxx config
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC6xxx_CONF_H__
#define __XC6xxx_CONF_H__
#ifdef __cplusplus
extern "C"
{
#endif
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/* ########################## Module Selection
* ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_CLOCK_MODULE_ENABLED
#define HAL_SYSTICK_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED
#define HAL_AOTIMER_MODULE_ENABLED
#define HAL_TIMER_MODULE_ENABLED
#define HAL_RTC_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
#define HAL_UART_DMA_MODULE_ENABLED
#define HAL_QDEC_MODULE_ENABLED
#define HAL_DMAC_MODULE_ENABLED
#define HAL_SPI_MODULE_ENABLED
#define HAL_FMC_SPI_MODULE_ENABLED
#define HAL_FMC_SPI_DMA_MODULE_ENABLED
#define HAL_SPI_DMA_MODULE_ENABLED
#define HAL_I2C_MODULE_ENABLED
#define HAL_WDT_MODULE_ENABLED
#define HAL_ADC_MODULE_ENABLED
#define HAL_CAN_MODULE_ENABLED
#define SW_I2C_MODULE_ENABLED
#define HAL_PWM_MODULE_ENABLED
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_reg_cpr.h"
#include "xc_reg_cprao.h"
#include "xc_reg_offset.h"
#include "xc_reg_rf.h"
#include "xc_reg_adc.h"
#include "xc_reg_aotimer.h"
#include "xc_reg_dma.h"
#include "xc_reg_fmc.h"
#include "xc_reg_fmc_cache.h"
#include "xc_reg_gpio.h"
#include "xc_reg_i2c.h"
#include "xc_reg_qdec.h"
#include "xc_reg_pwm.h"
#include "xc_reg_pwm_comn.h"
#include "xc_reg_rtc.h"
#include "xc_reg_spi.h"
#include "xc_reg_timer.h"
#include "xc_reg_uart.h"
#include "xc_reg_wdt.h"
#include "xc_reg_pwm_timer.h"
/**
* @brief Include module's header file
*/
#ifdef HAL_CLOCK_MODULE_ENABLED
#include "xc_drv_calib.h"
#include "xc_drv_clock.h"
#endif /* HAL_CLOCK_MODULE_ENABLED */
#ifdef HAL_SYSTICK_MODULE_ENABLED
#include "xc_drv_systick.h"
#endif /* HAL_SYSTICK_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "xc_drv_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "xc_drv_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_AOTIMER_MODULE_ENABLED
#include "xc_drv_aotimer.h"
#endif
#ifdef HAL_TIMER_MODULE_ENABLED
#include "xc_drv_timer.h"
#endif /* HAL_TIMER_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "xc_drv_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "xc_drv_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_QDEC_MODULE_ENABLED
#include "xc_reg_qdec.h"
#endif /* HAL_QDEC_MODULE_ENABLED */
#ifdef HAL_DMAC_MODULE_ENABLED
#include "xc_drv_dma.h"
#endif /* HAL_DMAC_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "xc_drv_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_SPI_DMA_MODULE_ENABLED
#include "xc_drv_spi_dma.h"
#endif /* HAL_SPI_DMA_MODULE_ENABLED */
#ifdef HAL_FMC_SPI_MODULE_ENABLED
#if (USE_ROM_FLASH)
#include "xc6xxx_fmc_spi.h"
#else
#include "xc_drv_fmc_spi.h"
#endif // (USE_ROM_FLASH)
#endif /* HAL_FMC_SPI_MODULE_ENABLED */
#ifdef HAL_FMC_SPI_DMA_MODULE_ENABLED
#include "xc_drv_fmc_spi_dma.h"
#endif
#ifdef HAL_UART_DMA_MODULE_ENABLED
#include "xc_drv_uart_dma.h"
#endif /* HAL_UART_DMA_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "xc_drv_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef SW_I2C_MODULE_ENABLED
#include "xc_drv_sw_i2c.h"
#endif /* SW_I2C_MODULE_ENABLED */
#ifdef HAL_WDT_MODULE_ENABLED
#include "xc_drv_wdt.h"
#endif /* HAL_WDT_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "xc_drv_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_PWM_MODULE_ENABLED
#include "xc_drv_pwm.h"
#endif
#ifdef __cplusplus
}
#endif
#endif /* __XC6xxx_CONF_H__ */
@@ -0,0 +1,839 @@
/*!
* \file xc_drv_dma.c
*
* \brief Target xinchip dma driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_dma.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
DMA_Instance_t DMA_Instance;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
* @brief xc_dma_set_test_mode
* @details DMAC test mode set
*
* @param uint8_t - mode
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE void xc_dma_set_test_mode(uint8_t mode)
{
dma_test_reg_set(mode);
}
/**
* @brief xc_dma_set_channel_priority_order
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE void xc_dma_set_channel_priority_order(DMA_Instance_t *inst)
{
uint8_t priority[DMA_MAX_CHANNELS];
uint8_t i, ch_priority, order;
for (i = 0; i < DMA_MAX_CHANNELS; i++) {
priority[i] = 0;
inst->Ch_Order[i] = i;
}
for (uint8_t ch_num = 0; ch_num < DMA_MAX_CHANNELS; ch_num++) {
// read the priority of the current channel
ch_priority = dma_cfg_l__ch_prior__getf(ch_num);
// Check the channel order array to see what position
// this channel comes in the priority list.
for (i = 0; i <= DMA_MAX_CHANNELS; i++) {
if (A_MAXEQ_B(ch_priority, priority[i]) || i == DMA_MAX_CHANNELS) {
order = i;
break;
}
}
// Now we know the order for this channel insert in the correct
// array position and shift current priority ordering to suite.
for (i = ch_num; i > order; i--) {
priority[i] = priority[i - 1];
inst->Ch_Order[i] = inst->Ch_Order[i - 1];
}
priority[order] = ch_priority;
inst->Ch_Order[order] = ch_num;
}
}
/**
* @brief xc_dma_reset_instance
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE void xc_dma_reset_instance(DMA_Instance_t *inst)
{
for (uint8_t i = 0; i < DMA_MAX_CHANNELS; i++) {
switch (i) {
case 0:
inst->Ch[i].ch_num = DMA_CHANNEL0;
break;
case 1:
inst->Ch[i].ch_num = DMA_CHANNEL1;
break;
// case 2:
// inst->Ch[i].ch_num = DMA_CHANNEL2;
// break;
// case 3:
// inst->Ch[i].ch_num = DMA_CHANNEL3;
// break;
}
inst->Ch[i].userCallback = NULL;
inst->Ch[i].userListener = NULL;
}
// Set the channel priority order
xc_dma_set_channel_priority_order(inst);
}
/**
* @brief xc_dma_check_channel_range
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_check_channel_range(eDMA_Ch_Num ch_num)
{
uint8_t errorCode = DMA_OK;
if (ch_num == DMA_NO_CHANNEL || ch_num > DMA_ALL_CHANNELS) {
errorCode = DMA_ECHRNG;
}
return errorCode;
}
/**
* @brief xc_dma_check_channel_busy
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_check_channel_busy(eDMA_Ch_Num ch_num)
{
uint8_t errorCode = DMA_OK;
if (ch_num == DMA_NO_CHANNEL || ch_num & (~DMA_ALL_CHANNELS)) {
errorCode = DMA_ECHRNG;
} else {
if (((uint16_t)dma_ch_en_reg_get( )) & ch_num) {
errorCode = DMA_EBUSY;
}
}
return errorCode;
}
/**
* @brief xc_dma_get_channel_index
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_get_channel_index(eDMA_Ch_Num ch_num)
{
uint8_t ch_enum = 1;
uint8_t ch_index = 0;
ch_num &= (DMA_ALL_CHANNELS >> 8);
while (ch_index < DMA_MAX_CHANNELS) {
if (ch_enum == ch_num) {
break;
}
ch_enum *= 2;
ch_index++;
}
return ch_index;
}
/**
* @brief xc_dma_enable
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE void xc_dma_enable(void) { dma_cfg_reg_set(ENABLE); }
/**
* @brief xc_dma_disable
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_disable(void)
{
uint8_t errorCode = 0;
uint8_t dma_en = dma_cfg_reg__dma_en__getf( );
if (dma_en != 0) {
dma_cfg_reg_set(DISABLE);
// Ensure that the DMA was disabled
// May not disable due to split response on one
// of the DMA channels
if (dma_cfg_reg_get( )) {
errorCode = DMA_EBUSY;
}
}
return errorCode;
}
/**
* @brief xc_dma_is_enable
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
bool xc_dma_is_enable(void)
{
bool ret;
ret = (bool)dma_cfg_reg__dma_en__getf( );
return ret;
}
/**
* @brief xc_dma_enable_channel
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_enable_channel(eDMA_Ch_Num ch_num)
{
uint8_t errorCode = 0;
// Check for valid channel number and not busy
errorCode = xc_dma_check_channel_busy(ch_num);
if (errorCode == 0) {
// The dw_dmac_channel_number enum is declared such that
// the enumerated value maps exactly to the value that
// needs to be written into the ChEnReg for enabling.
dma_ch_en_reg_set(ch_num);
}
return errorCode;
}
/**
* @brief xc_dma_disable_channel
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_disable_channel(eDMA_Ch_Num ch_num)
{
uint8_t errorCode = 0;
uint32_t enabled_ch;
// Check for valid channel number
errorCode = xc_dma_check_channel_range(ch_num);
if (errorCode == 0) {
enabled_ch = (dma_ch_en_reg_get( ) & ch_num);
if (enabled_ch != 0) {
dma_ch_en_reg_set((ch_num & (DMA_ALL_CHANNELS << 8)));
// Ensure that the channel(s) was disabled.
// Channel may not disable due to a split response.
if (dma_ch_en_reg_get( ) & ch_num) {
errorCode = DMA_EBUSY;
}
}
}
return errorCode;
}
/**
* @brief xc_dma_is_channel_enabled
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
bool xc_dma_is_channel_enabled(eDMA_Ch_Num ch_num)
{
uint8_t ch_index;
bool ret;
ch_index = xc_dma_get_channel_index(ch_num);
// Allow only ONE channel to be specified
if (ch_index == DMA_MAX_CHANNELS)
return false;
// Check that the specified channel is in range
if (ch_num & (~DMA_ALL_CHANNELS))
return false;
ret = (bool)REG_BIT_VAL_GET(dma_ch_en_reg__ch_en__getf( ), 1 << ch_index, ch_index);
return ret;
}
/**
* @brief xc_dma_enable_channel_irq
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_enable_channel_irq(eDMA_Ch_Num ch_num)
{
uint8_t errorCode = DMA_OK;
// Check for valid channel number and not busy
errorCode = xc_dma_check_channel_busy(ch_num);
if (errorCode == 0) {
// Loop through each channel in turn and disable
// the channel Irq for the selected channels.
for (uint8_t x = 0; x < DMA_MAX_CHANNELS; x++) {
if (ch_num & (1 << x)) {
if (dma_ctl_l__int_en__getf(x) != 0x1) {
dma_ctl_l__int_en__setf(x, ENABLE);
}
}
}
}
return errorCode;
}
/**
* @brief xc_dma_disable_channel_irq
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_disable_channel_irq(eDMA_Ch_Num ch_num)
{
uint8_t errorCode = DMA_OK;
// Check for valid channel number and not busy
errorCode = xc_dma_check_channel_busy(ch_num);
if (errorCode == 0) {
// Loop through each channel in turn and disable
// the channel Irq for the selected channels.
for (uint8_t x = 0; x < DMA_MAX_CHANNELS; x++) {
if (ch_num & (1 << x)) {
if (dma_ctl_l__int_en__getf(x) != 0x0) {
dma_ctl_l__int_en__setf(x, DISABLE);
}
}
}
}
return errorCode;
}
/**
* @brief xc_dma_mask_irq
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_mask_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
{
uint8_t errorCode = DMA_OK;
uint16_t reg;
// Check for valid channel number
errorCode = xc_dma_check_channel_range(ch_num);
if (errorCode == 0) {
// Loop through and clear the selected channel Irq
// for the targeted channels.
reg = (ch_num & (DMA_ALL_CHANNELS << 8));
for (uint8_t x = 0; x < DMA_MAX_INTERRUPTS; x++) {
if (ch_irq & (1 << x)) {
switch (x) {
case 0:
dma_mask_tfr_set(reg);
break;
case 1:
dma_mask_block_set(reg);
break;
case 2:
dma_mask_src_tran_set(reg);
break;
case 3:
dma_mask_dst_tran_set(reg);
break;
case 4:
dma_mask_err_set(reg);
break;
}
}
}
}
return errorCode;
}
/**
* @brief xc_dma_unmask_irq
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
uint8_t xc_dma_unmask_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
{
uint8_t errorCode = DMA_OK;
uint16_t reg;
// Check for valid channel number
errorCode = xc_dma_check_channel_range(ch_num);
if (errorCode == 0) {
// Loop through and clear the selected channel Irq
// for the targeted channels.
reg = ch_num;
for (uint8_t x = 0; x < DMA_MAX_INTERRUPTS; x++) {
if (ch_irq & (1 << x)) {
switch (x) {
case 0:
dma_mask_tfr_set(reg);
break;
case 1:
dma_mask_block_set(reg);
break;
case 2:
dma_mask_src_tran_set(reg);
break;
case 3:
dma_mask_dst_tran_set(reg);
break;
case 4:
dma_mask_err_set(reg);
break;
}
}
}
}
return errorCode;
}
/**
* @brief xc_dma_clear_irq
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_clear_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
{
uint8_t errorCode = DMA_OK;
uint16_t reg;
// Check for valid channel number
errorCode = xc_dma_check_channel_range(ch_num);
if (errorCode == 0) {
// Loop through and clear the selected channel Irq
// for the targeted channels.
reg = (ch_num & (DMA_ALL_CHANNELS >> 8));
for (uint8_t x = 0; x < DMA_MAX_INTERRUPTS; x++) {
if (ch_irq & (1 << x)) {
switch (x) {
case 0:
dma_clear_tfr_set(reg);
break;
case 1:
dma_clear_block_set(reg);
break;
case 2:
dma_clear_src_tran_set(reg);
break;
case 3:
dma_clear_dst_tran_set(reg);
break;
case 4:
dma_clear_err_set(reg);
break;
}
}
}
}
return errorCode;
}
/**
* @brief xc_dma_init
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_init(void)
{
// Remove from test mode
xc_dma_set_test_mode(DISABLE);
// Reset the DMA instance structure
xc_dma_reset_instance(&DMA_Instance);
// Disable the DMA controller
uint8_t errorCode = xc_dma_disable( );
if (errorCode == 0) {
// Disable all DMA channels
errorCode = xc_dma_disable_channel(DMA_ALL_CHANNELS);
}
if (errorCode == 0) {
// Disable all channel interrupts
errorCode = xc_dma_disable_channel_irq(DMA_ALL_CHANNELS);
}
if (errorCode == 0) {
// Mask all channel interrupts
errorCode = xc_dma_mask_irq(DMA_ALL_CHANNELS, DMA_IRQ_ALL);
}
if (errorCode == 0) {
// Clear any pending interrupts
errorCode = xc_dma_clear_irq(DMA_ALL_CHANNELS, DMA_IRQ_ALL);
}
return errorCode;
}
/**
* @brief xc_dma_set_channel_config
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_set_channel_config(eDMA_Ch_Num ch_num,
DMA_Chx_Cfg_t *ch)
{
uint8_t errorCode;
uint8_t ch_index;
ch_index = xc_dma_get_channel_index(ch_num);
// Check for valid channel number and not busy
errorCode = xc_dma_check_channel_busy(ch_num);
if (errorCode == 0) {
// Set the control register
dma_ctl_l_pack(ch_index, ch->ctl_tt_fc, ch->ctl_src_msize, ch->ctl_dst_msize,
ch->ctl_sinc, ch->ctl_dinc, ch->ctl_src_tr_width, ch->ctl_dst_tr_width,
0);
dma_ctl_h__block_ts__setf(ch_index, ch->ctl_block_ts);
// Set the config register
dma_cfg_l__hs_sel_src__setf(ch_index, ch->cfg_hs_sel_src);
dma_cfg_l__hs_sel_dst__setf(ch_index, ch->cfg_hs_sel_dst);
dma_cfg_h_pack(ch_index, (ch->cfg_dst_per & 0xf), (ch->cfg_src_per & 0xf), (ch->cfg_fifo_mode & 0x1));
// set the SAR/DAR registers
dma_sar_set(ch_index, ch->sar);
dma_dar_set(ch_index, ch->dar);
};
return errorCode;
}
/**
* @brief xc_dma_set_listener
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE bool xc_dma_set_listener(eDMA_Ch_Num ch_num,
DMA_Callback userFunction)
{
uint8_t ch_index;
DMA_Instance_t *inst = &DMA_Instance;
ch_index = xc_dma_get_channel_index(ch_num);
// Allow only ONE channel to be specified
if (ch_index == DMA_MAX_CHANNELS)
return false;
// Check that the specified channel is in range
if (ch_num & (~DMA_ALL_CHANNELS))
return false;
inst->Ch[ch_index].userListener = userFunction;
return true;
}
/**
* @brief xc_dma_start_transfer
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE uint8_t xc_dma_start_transfer(eDMA_Ch_Num ch_num, DMA_Callback cb_func)
{
uint8_t errorCode;
uint8_t ch_index;
DMA_Instance_t *inst = &DMA_Instance;
// Update the channel instance
ch_index = xc_dma_get_channel_index(ch_num);
// Allow only ONE channel to be specified
if (ch_index == DMA_MAX_CHANNELS) {
errorCode = DMA_ECHRNG;
} else {
// Check for valid channel number and not busy
errorCode = xc_dma_check_channel_busy(ch_num);
}
if (errorCode == 0) {
// Disable the channels interrupts
errorCode = xc_dma_disable_channel_irq(ch_num);
}
if (errorCode == 0) {
// set the call back function, the number of blocks
// in the transfer and the source and destination states.
inst->Ch[ch_index].userCallback = cb_func;
// always want to unmask the tfr, block and err interrupts
xc_dma_unmask_irq(ch_num, DMA_IRQ_TRF);
xc_dma_unmask_irq(ch_num, DMA_IRQ_ERR);
// Enable the channel interrupts for the type of transfer
errorCode = xc_dma_enable_channel_irq(ch_num);
if (errorCode == 0) {
// Enable the DMA channel
errorCode = xc_dma_enable_channel(ch_num);
}
}
return errorCode;
}
/**
* @brief dma_irq_handler
* @details
*
* @param
* @param
* @return void
* @retval void
* @retval void
* @note
*/
__RAM_CODE bool dma_irq_handler(DMA_Instance_t *inst)
{
bool retval;
uint8_t i, ch_index, callbackArg;
uint32_t reg, mask;
DMA_Callback userCallback;
// Assume an interrupt will be processed. The return value will be
// set to false if an active interrupt is not found.
retval = true;
// ERR INTERRUPT
if (dma_status_int__err__getf( )) {
reg = dma_status_err_get( );
// Loop through the channels until we find
// active interrupt. We start at the highest priority
// channel and work down to the lowest priority.
for (i = 0; i < DMA_MAX_CHANNELS; i++) {
mask = 1 << inst->Ch_Order[i];
if (reg & mask) {
ch_index = inst->Ch_Order[i];
break;
}
}
// run the listener function
if (inst->Ch[ch_index].userListener != NULL) {
userCallback = inst->Ch[ch_index].userListener;
callbackArg = DMA_IRQ_ERR;
userCallback(callbackArg);
}
// clear the interrupt
dma_clear_err_set(mask);
}
// TFR INTERRUPT
else if (dma_status_int__tfr__getf( )) {
reg = dma_status_tfr_get( );
// Loop through the channels until we find
// active interrupt. We start at the highest priority
// channel and work down to the lowest priority.
for (i = 0; i < DMA_MAX_CHANNELS; i++) {
mask = 1 << inst->Ch_Order[i];
if (reg & mask) {
ch_index = inst->Ch_Order[i];
break;
}
}
// Disable all channel interrupts
xc_dma_disable_channel_irq(inst->Ch[ch_index].ch_num);
// clear any pending block/srcTran/dstTran interrupts
dma_clear_block_set(mask);
dma_clear_src_tran_set(mask);
dma_clear_dst_tran_set(mask);
xc_dma_clear_irq(inst->Ch[ch_index].ch_num, DMA_IRQ_TRF);
// Mask all channel interrupts
xc_dma_mask_irq(inst->Ch[ch_index].ch_num, DMA_IRQ_ALL);
// run the callback function
if (inst->Ch[ch_index].userCallback != NULL) {
userCallback = inst->Ch[ch_index].userCallback;
callbackArg = 0;
userCallback(callbackArg);
}
} else {
// If we've reached this point, either the enabling and
// disabling of DW_ahb_dmac interrupts is not being handled
// properly or this function is being called unnecessarily.
retval = false;
}
return retval;
}
__RAM_CODE void DMA_Handler(void) { dma_irq_handler(&DMA_Instance); }
@@ -0,0 +1,287 @@
/*!
* \file xc_drv_dma.h
*
* \brief The header of xc_drv_dma.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_DMA_H_
#define _XC_DRV_DMA_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
// Macro definitions for DMA operation return code
#define DMA_OK 0 // operation normal
#define DMA_EPERM 1 // operation not permitted
#define DMA_EIO 5 // I/O error
#define DMA_ENXIO 6 // no such device or address
#define DMA_ENOMEM 12 // out of memory
#define DMA_EACCES 13 // permission denied
#define DMA_EBUSY 16 // device or resource busy
#define DMA_ENODEV 19 // no such device
#define DMA_EINVAL 22 // invalid argument
#define DMA_ENOSPC 28 // no space left on device
#define DMA_ENOSYS 38 // function not implemented/supported
#define DMA_ECHRNG 44 // channel number out of range
#define DMA_ENODATA 61 // no data available
#define DMA_ETIME 62 // timer expired
#define DMA_EPROTO 71 // protocol error
// Macro definitions for DMA controller limits
#define DMA_MAX_CHANNELS 2U //5A 2 CH; 5B 4 CH
#define DMA_MAX_INTERRUPTS 5U
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef void (*DMA_Callback)(uint8_t eCode);
typedef enum dmac_channel_number
{
// 4 channel configuration
DMA_NO_CHANNEL = 0x0000,
DMA_CHANNEL0 = 0x0101,
DMA_CHANNEL1 = 0x0202,
DMA_ALL_CHANNELS = 0x0303,
// DMA_CHANNEL2 = 0x0404,
// DMA_CHANNEL3 = 0x0808,
// DMA_ALL_CHANNELS = 0x0f0f
} eDMA_Ch_Num;
typedef enum dmac_src_dst_select
{
DMA_SRC = 0x1,
DMA_DST = 0x2,
DMA_SRC_DST = 0x3
} eDMA_Src_Dst_Select;
typedef enum dmac_ch_state
{
DMA_IDLE = 0x0,
DMA_SINGLE_REGION = 0x1,
DMA_BURST_REGION = 0x2
} eDMA_CH_State;
typedef enum dmac_transfer_type
{
DMA_TRANSFER_ROW1 = 0x1, /* single block or last multi-block */
/* no write back */
DMA_TRANSFER_ROW2 = 0x2, /* multi-block auto-reload DAR */
/* contiguous SAR no write back */
DMA_TRANSFER_ROW3 = 0x3, /* multi-block auto reload SAR */
/* contiguous DAR no write back */
DMA_TRANSFER_ROW4 = 0x4, /* multi-block auto-reload SAR DAR */
/* no write back */
DMA_TRANSFER_ROW5 = 0x5, /* single block or last multi-block */
/* with write back */
DMA_TRANSFER_ROW6 = 0x6, /* multi-block linked list DAR */
/* contiguous SAR with write back */
DMA_TRANSFER_ROW7 = 0x7, /* multi-block linked list DAR auto */
/* reload SAR with write back */
DMA_TRANSFER_ROW8 = 0x8, /* multi-block linked list SAR */
/* contiguous DAR with write back */
DMA_TRANSFER_ROW9 = 0x9, /* multi-block linked list SAR auto */
/* reload DAR with write back */
DMA_TRANSFER_ROW10 = 0xa /* multi-block linked list SAR DAR */
/* with write back */
} eDMA_Trans_Type;
typedef enum dw_dmac_irq
{
DMA_IRQ_NONE = 0x00, // no interrupts
DMA_IRQ_TRF = 0x01, // transfer complete
DMA_IRQ_BLOCK = 0x02, // block transfer complete
DMA_IRQ_SRCTRAN = 0x04, // source transaction complete
DMA_IRQ_DSTTRAN = 0x08, // destination transaction complete
DMA_IRQ_ERR = 0x10, // error
DMA_IRQ_ALL = 0x1f // all interrupts
} eDMA_Irq;
typedef enum dmac_burst_trans_length
{
DMA_MSIZE_1 = 0x0,
DMA_MSIZE_4 = 0x1,
DMA_MSIZE_8 = 0x2,
DMA_MSIZE_16 = 0x3,
DMA_MSIZE_32 = 0x4,
DMA_MSIZE_64 = 0x5,
DMA_MSIZE_128 = 0x6,
DMA_MSIZE_256 = 0x7
} eDMA_Burst_Trans_Len;
typedef enum dmac_address_increment
{
DMA_ADDR_INCREMENT = 0x0,
DMA_ADDR_DECREMENT = 0x1,
DMA_ADDR_NOCHANGE = 0x2
} eDMA_Addr_Increment;
typedef enum dmac_transfer_width
{
DMA_TRANS_WIDTH_8 = 0x0,
DMA_TRANS_WIDTH_16 = 0x1,
DMA_TRANS_WIDTH_32 = 0x2,
DMA_TRANS_WIDTH_64 = 0x3,
DMA_TRANS_WIDTH_128 = 0x4,
DMA_TRANS_WIDTH_256 = 0x5
} eDMA_Trans_Width;
typedef enum dw_dmac_sw_hw_hs_select
{
DMA_HS_HARDWARE = 0x0,
DMA_HS_SOFTWARE = 0x1
} eDMA_SW_HW_HS_Select;
typedef enum dmac_hs_interface
{
UART0_DMA_TX_HS_IF0 = 0x0,
UART1_DMA_TX_HS_IF1 = 0x1,
SSI0_DMA_TX_HS_IF2 = 0x2,
SSI1_DMA_TX_HS_IF3 = 0x3,
SSI2_DMA_TX_HS_IF4 = 0x4,
I2S_DMA_TX_HS_IF5 = 0x5,
DMA_HS_IF6 = 0x6,
DMA_HS_IF7 = 0x7,
UART0_DMA_RX_HS_IF8 = 0x8,
UART1_DMA_RX_HS_IF9 = 0x9,
SSI0_DMA_RX_HS_IF10 = 0xa,
SSI1_DMA_RX_HS_IF11 = 0xb,
GPADC_DMA_RX_HS_IF12 = 0xc,
CDC_DMA_RX_HS_IF13 = 0xd,
SSI2_DMA_RX_HS_IF14 = 0xe,
I2S_DMA_RX_HS_IF15 = 0xf
} eDMA_HS_Interface;
typedef enum dmac_transfer_flow
{
DMA_MEM2MEM_DMA = 0x0, /* mem to mem - DMA flow ctlr */
DMA_MEM2PRF_DMA = 0x1, /* mem to prf - DMA flow ctlr */
DMA_PRF2MEM_DMA = 0x2, /* prf to mem - DMA flow ctlr */
DMA_PRF2PRF_DMA = 0x3, /* prf to prf - DMA flow ctlr */
DMA_PRF2MEM_PRF = 0x4, /* prf to mem - periph flow ctlr */
DMA_PRF2PRF_SRCPRF = 0x5, /* prf to prf - source flow ctlr */
DMA_MEM2PRF_PRF = 0x6, /* mem to prf - periph flow ctlr */
DMA_PRF2PRF_DSTPRF = 0x7 /* prf to prf - dest flow ctlr */
} eDMA_Trans_Flow;
typedef enum dmac_fifo_mode
{
DMA_FIFO_MODE_SINGLE = 0x0,
DMA_FIFO_MODE_HALF = 0x1
} eDMA_Fifo_Mode;
typedef enum dw_dmac_channel_priority
{
DMA_PRIORITY_0 = 0x0,
DMA_PRIORITY_1 = 0x1,
DMA_PRIORITY_2 = 0x2,
DMA_PRIORITY_3 = 0x3,
DMA_PRIORITY_4 = 0x4,
DMA_PRIORITY_5 = 0x5,
DMA_PRIORITY_6 = 0x6,
DMA_PRIORITY_7 = 0x7
} eDMA_CH_Priority;
typedef struct dmac_channel_config
{
uint32_t sar;
uint32_t dar;
eDMA_Burst_Trans_Len ctl_src_msize;
eDMA_Burst_Trans_Len ctl_dst_msize;
eDMA_Addr_Increment ctl_sinc;
eDMA_Addr_Increment ctl_dinc;
eDMA_Trans_Width ctl_src_tr_width;
eDMA_Trans_Width ctl_dst_tr_width;
eDMA_HS_Interface cfg_dst_per;
eDMA_HS_Interface cfg_src_per;
uint32_t ctl_block_ts;
eDMA_Trans_Flow ctl_tt_fc;
eDMA_Fifo_Mode cfg_fifo_mode;
eDMA_SW_HW_HS_Select cfg_hs_sel_src;
eDMA_SW_HW_HS_Select cfg_hs_sel_dst;
eDMA_CH_Priority cfg_ch_prior;
} DMA_Chx_Cfg_t;
typedef struct dmac_param_s
{
bool encoded_params; /* include encoded hardware parameters */
uint8_t num_channels; /* number of DMA channels */
uint8_t num_hs_int; /* number of handshaking interfaces */
uint8_t intr_io; /* individual or combined interrupts */
bool big_endian; /* big or little endian 1=big */
uint16_t s_hdata_width; /* AHB slave data bus width */
} DMA_Params_t;
typedef struct dma_instance_s
{
struct
{
eDMA_Ch_Num ch_num; // channel number
DMA_Callback userCallback; // callback functon for IRQ handler
DMA_Callback userListener; // listener functon for IRQ handler
} Ch[DMA_MAX_CHANNELS];
uint8_t Ch_Order[DMA_MAX_CHANNELS];
} DMA_Instance_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern DMA_Instance_t DMA_Instance;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
uint8_t xc_dma_init(void);
void xc_dma_enable(void);
uint8_t xc_dma_disable(void);
bool xc_dma_is_enable(void);
uint8_t xc_dma_enable_channel(eDMA_Ch_Num ch_num);
uint8_t xc_dma_disable_channel(eDMA_Ch_Num ch_num);
bool xc_dma_is_channel_enabled(eDMA_Ch_Num ch_num);
uint8_t xc_dma_enable_channel_irq(eDMA_Ch_Num ch_num);
uint8_t xc_dma_set_channel_config(eDMA_Ch_Num ch_num, DMA_Chx_Cfg_t *ch);
bool xc_dma_set_listener(eDMA_Ch_Num ch_num, DMA_Callback userFunction);
uint8_t xc_dma_start_transfer(eDMA_Ch_Num ch_num, DMA_Callback cb_func);
void xc_dma_set_test_mode(uint8_t mode);
void xc_dma_set_channel_priority_order(DMA_Instance_t *inst);
void xc_dma_reset_instance(DMA_Instance_t *inst);
uint8_t xc_dma_check_channel_range(eDMA_Ch_Num ch_num);
uint8_t xc_dma_check_channel_range(eDMA_Ch_Num ch_num);
uint8_t xc_dma_get_channel_index(eDMA_Ch_Num ch_num);
bool dma_irq_handler(DMA_Instance_t *inst);
#endif /* _XC_DRV_DMA_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,312 @@
/*!
* \file xc_drv_fmc_spi.h
*
* \brief The header of xc_drv_fmc_spi.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC_DRV_FMC_SPI_H_
#define __XC_DRV_FMC_SPI_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define __RAM_CODE __attribute__((section("ram_code")))
#define __WRITE_REG32(REG, VAL) ((*REG) = (VAL))
#define __READ_REG32(REG, VAL) ((VAL) = (*REG))
#define __SET_BIT(REG, BIT) ((REG) |= (BIT))
#define __CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
#define FMC_SSI_CTRL0_DFS_LEN_4BIT (0x03UL)
#define FMC_SSI_CTRL0_DFS_LEN_5BIT (0x04UL)
#define FMC_SSI_CTRL0_DFS_LEN_6BIT (0x05UL)
#define FMC_SSI_CTRL0_DFS_LEN_7BIT (0x06UL)
#define FMC_SSI_CTRL0_DFS_LEN_8BIT (0x07UL)
#define FMC_SSI_CTRL0_DFS_LEN_9BIT (0x08UL)
#define FMC_SSI_CTRL0_DFS_LEN_10BIT (0x09UL)
#define FMC_SSI_CTRL0_DFS_LEN_11BIT (0x0aUL)
#define FMC_SSI_CTRL0_DFS_LEN_12BIT (0x0bUL)
#define FMC_SSI_CTRL0_DFS_LEN_13BIT (0x0cUL)
#define FMC_SSI_CTRL0_DFS_LEN_14BIT (0x0dUL)
#define FMC_SSI_CTRL0_DFS_LEN_15BIT (0x0eUL)
#define FMC_SSI_CTRL0_DFS_LEN_16BIT (0x0fUL)
#define FMC_SSI_CTRL0_DFS_LEN_17BIT (0x10UL)
#define FMC_SSI_CTRL0_DFS_LEN_18BIT (0x11UL)
#define FMC_SSI_CTRL0_DFS_LEN_19BIT (0x12UL)
#define FMC_SSI_CTRL0_DFS_LEN_20BIT (0x13UL)
#define FMC_SSI_CTRL0_DFS_LEN_21BIT (0x14UL)
#define FMC_SSI_CTRL0_DFS_LEN_22BIT (0x15UL)
#define FMC_SSI_CTRL0_DFS_LEN_23BIT (0x16UL)
#define FMC_SSI_CTRL0_DFS_LEN_24BIT (0x17UL)
#define FMC_SSI_CTRL0_DFS_LEN_25BIT (0x18UL)
#define FMC_SSI_CTRL0_DFS_LEN_26BIT (0x19UL)
#define FMC_SSI_CTRL0_DFS_LEN_27BIT (0x1AUL)
#define FMC_SSI_CTRL0_DFS_LEN_28BIT (0x1BUL)
#define FMC_SSI_CTRL0_DFS_LEN_29BIT (0x1CUL)
#define FMC_SSI_CTRL0_DFS_LEN_30BIT (0x1DUL)
#define FMC_SSI_CTRL0_DFS_LEN_31BIT (0x1EUL)
#define FMC_SSI_CTRL0_DFS_LEN_32BIT (0x1FUL)
#define FMC_SSI_CTRL0_FRF_MOTOROLA (0x0UL)
#define FMC_SSI_CTRL0_FRF_TI (0x1UL)
#define FMC_SSI_CTRL0_SCPHA_LEAD (0x0UL)
#define FMC_SSI_CTRL0_SCPHA_TRAIL (0x1UL)
#define FMC_SSI_CTRL0_SCPOL_HIGH (0x1UL)
#define FMC_SSI_CTRL0_SCPOL_LOW (0x0UL)
#define FMC_SSI_CTRL0_TMOD_WR (0x0UL)
#define FMC_SSI_CTRL0_TMOD_W (0x1UL)
#define FMC_SSI_CTRL0_TMOD_R (0x2UL)
#define FMC_SSI_CTRL0_SLV_OE_ENABLE (0x0UL)
#define FMC_SSI_CTRL0_SLV_OE_DISABLE (0x1UL)
#define FMC_SSI_CTRL0_SRL_NORMAL (0x0UL)
#define FMC_SSI_CTRL0_SRL_LOOKBACK (0x1UL)
#define FMC_SSI_CTRL0_SSTE_ENABLE (0x1UL)
#define FMC_SSI_CTRL0_SSTE_DISABLE (0x0UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_01 (0x0UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_02 (0x1UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_03 (0x2UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_04 (0x3UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_05 (0x4UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_06 (0x5UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_07 (0x6UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_08 (0x7UL)
#define FMC_SSI_CTRL0_CFS_SIZE_Bit_09 (0x8UL)
#define FMC_SSI_CTRL0_SPI_FRF_STANDARD (0x0UL)
#define FMC_SSI_CTRL0_SPI_FRF_DUAL (0x1UL)
#define FMC_SSI_CTRL0_SPI_FRF_QUAD (0x2UL)
#define FMC_SSI_CTRL0_SPI_FRF_OCTAL (0x3UL)
#define FMC_SSI_EN_SEN_ENABLE (0x1UL)
#define FMC_SSI_EN_SEN_DISABLE (0x0UL)
#define FMC_SSI_SE_SS0_SELECT_YES (0x1UL)
#define FMC_SSI_SE_SS0_SELECT_NO (0x0UL)
#define FMC_SSI_BAUD_DIV_2 (0x02UL)
#define FMC_SSI_BAUD_DIV_4 (0x04UL)
#define FMC_SSI_BAUD_DIV_6 (0x06UL)
#define FMC_SSI_BAUD_DIV_8 (0x08UL)
#define FMC_SSI_BAUD_DIV_10 (0x10UL)
#define FMC_SSI_BAUD_DIV_12 (0x12UL)
#define FMC_SSI_TXFTL_FIFO_0 (0x00UL)
#define FMC_SSI_TXFTL_FIFO_1 (0x01UL)
#define FMC_SSI_TXFTL_FIFO_2 (0x02UL)
#define FMC_SSI_TXFTL_FIFO_3 (0x03UL)
#define FMC_SSI_TXFTL_FIFO_4 (0x04UL)
#define FMC_SSI_TXFTL_FIFO_5 (0x05UL)
#define FMC_SSI_TXFTL_FIFO_6 (0x06UL)
#define FMC_SSI_TXFTL_FIFO_7 (0x07UL)
#define FMC_SSI_RXFTL_FIFO_0 (0x00UL)
#define FMC_SSI_RXFTL_FIFO_1 (0x01UL)
#define FMC_SSI_RXFTL_FIFO_2 (0x02UL)
#define FMC_SSI_RXFTL_FIFO_3 (0x03UL)
#define FMC_SSI_RXFTL_FIFO_4 (0x04UL)
#define FMC_SSI_RXFTL_FIFO_5 (0x05UL)
#define FMC_SSI_RXFTL_FIFO_6 (0x06UL)
#define FMC_SSI_RXFTL_FIFO_7 (0x07UL)
#define FMC_SSI_STS_BUSY_SET (0x1UL << BUSY_POS)
#define FMC_SSI_STS_BUSY_RESET (0x0UL << BUSY_POS)
#define FMC_SSI_STS_TFNF_SET (0x1UL << TFNF_POS)
#define FMC_SSI_STS_TFNF_RESET (0x0UL << TFNF_POS)
#define FMC_SSI_STS_TFE_SET (0x1UL << TFE_POS)
#define FMC_SSI_STS_TFE_RESET (0x0UL << TFE_POS)
#define FMC_SSI_STS_RFNE_SET (0x1UL << RFNE_POS)
#define FMC_SSI_STS_RFNE_RESET (0x0UL << RFNE_POS)
#define FMC_SSI_STS_RFF_SET (0x1UL << RFF_POS)
#define FMC_SSI_STS_RFF_RESET (0x0UL << RFF_POS)
#define FMC_SSI_STS_TXE_SET (0x1UL << TXE_POS)
#define FMC_SSI_STS_TXE_RESET (0x0UL << TXE_POS)
#define FMC_SSI_IE_TXEIE_ENABLE (0x1UL << TXEIE_POS)
#define FMC_SSI_IE_TXEIE_DISABLE (0x0UL << TXEIE_POS)
#define FMC_SSI_IE_TXOIE_ENABLE (0x1UL << TXOIE_POS)
#define FMC_SSI_IE_TXOIE_DISABLE (0x0UL << TXOIE_POS)
#define FMC_SSI_IE_RXUIE_ENABLE (0x1UL << RXUIE_POS)
#define FMC_SSI_IE_RXUIE_DISABLE (0x0UL << RXUIE_POS)
#define FMC_SSI_IE_RXOIE_ENABLE (0x1UL << RXOIE_POS)
#define FMC_SSI_IE_RXOIE_DISABLE (0x0UL << RXOIE_POS)
#define FMC_SSI_IE_RXFIE_ENABLE (0x1UL << RXFIE_POS)
#define FMC_SSI_IE_RXFIE_DISABLE (0x0UL << RXFIE_POS)
#define FMC_SSI_IS_TXEIS_SET (0x1UL << TXEIS_POS)
#define FMC_SSI_IS_TXEIS_RESET (0x0UL << TXEIS_POS)
#define FMC_SSI_IS_TXOIS_SET (0x1UL << TXOIS_POS)
#define FMC_SSI_IS_TXOIS_RESET (0x0UL << TXOIS_POS)
#define FMC_SSI_IS_RXUIS_SET (0x1UL << RXUIS_POS)
#define FMC_SSI_IS_RXUIS_RESET (0x0UL << RXUIS_POS)
#define FMC_SSI_IS_RXOIS_SET (0x1UL << RXOIS_POS)
#define FMC_SSI_IS_RXOIS_RESET (0x0UL << RXOIS_POS)
#define FMC_SSI_SSI_IS_RXFIS_SET (0x1UL << RXFIS_POS)
#define FMC_SSI_SSI_IS_RXFIS_RESET (0x0UL << RXFIS_POS)
#define FMC_SSI_RIS_TXEIR_SET (0x1UL << TXEIR_POS)
#define FMC_SSI_RIS_TXEIR_RESET (0x0UL << TXEIR_POS)
#define FMC_SSI_RIS_TXOIR_SET (0x1UL << TXOIR_POS)
#define FMC_SSI_RIS_TXOIR_RESET (0x0UL << TXOIR_POS)
#define FMC_SSI_RIS_RXUIR_SET (0x1UL << RXUIR_POS)
#define FMC_SSI_RIS_RXUIR_RESET (0x0UL << RXUIR_POS)
#define FMC_SSI_RIS_RXOIR_SET (0x1UL << RXOIR_POS)
#define FMC_SSI_RIS_RXOIR_RESET (0x0UL << RXOIR_POS)
#define FMC_SSI_RIS_RXFIR_SET (0x1UL << RXFIR_POS)
#define FMC_SSI_RIS_RXFIR_RESET (0x0UL << RXFIR_POS)
#define PUYA_FLASH_STATUS_WIP_SET (0x01UL)
#define PUYA_FLASH_STATUS_WIP_RESET (0x00UL)
#define CMD_READ_DATA (uint8_t)0x03
#define CMD_READ_STATUS (uint8_t)0x05
#define CMD_CHIP_ERASE (uint8_t)0xc7
#define CMD_WRITE_ENABLE (uint8_t)0x06
#define CMD_WRITE_DISABLE (uint8_t)0x04
#define CMD_PAGE_PROGRAM (uint8_t)0x02
#define CMD_BLOCK_ERASE (uint8_t)0xD8
#define CMD_SECTOR_ERASE (uint8_t)0x20
#define CMD_PAGE_ERASE (uint8_t)0x81
#define CMD_RELEASE_PWRDWN (uint8_t)0xAB
#define CMD_PWRDWN (uint8_t)0xB9
#define CMD_RUID (uint8_t)0x4B
#define CMD_RDID (uint8_t)0x9F
#define CMD_QREMS (uint8_t)0x94
#define CMD_WRITE_STATUS_REG (uint8_t)0x01
#define FLASH_PAGE_SIZE 256
#define FLASH_SECTOR_SIZE 4096
#define CUR_PAGE_NUM(addr) (addr / FLASH_PAGE_SIZE)
#define CUR_START_PSR(addr) (addr % FLASH_PAGE_SIZE)
#define CUR_SECTOR_NUM(addr) (addr / FLASH_SECTOR_SIZE)
#define CUR_SECTOR_PSR(addr) (addr % FLASH_SECTOR_SIZE)
#define BLE_COMMON_BASE 0x53022000UL
#define BLE_COMN_AGC_REG_OUT0 ((volatile uint32_t *)(BLE_COMMON_BASE + 0x28))
#define FMC_IDLE_STATUS ((uint32_t)0x01 << 31)
#define CMD_ERASE_SECURITY_REG (uint8_t)0x44
#define CMD_READ_SECURITY_REG (uint8_t)0x48
#define CMD_PROGRAM_SECURITY_REG (uint8_t)0x42
#define OTP_PROGRAM_PAGE_0 (uint8_t)0x0
#define OTP_PROGRAM_PAGE_1 (uint8_t)0x10
#define OTP_PROGRAM_PAGE_2 (uint8_t)0x20
#define OTP_PROGRAM_PAGE_3 (uint8_t)0x30
#define FLASH_2M_FLAG 0x15
#define FLASH_1M_FLAG 0x14
#define FLASH_512K_FLAG 0x13
#define FLASH_256K_FLAG 0x12
#define FLASH_128K_FLAG 0x11
#define FLASH_2M_SIZE 1024*2048
#define FLASH_1M_SIZE 1024*1024
#define FLASH_512K_SIZE 1024*512
#define FLASH_256K_SIZE 1024*256
#define FLASH_128K_SIZE 1024*128
#define YOUCUN_FLASH 0x60B3
#define PURAN_128K_FLASH 0x4485
#define GD25WD40_512K_FLASH 0x64C8
#define FLASH_PAGE_SIZE 256
#define FLASH_SECTOR_SIZE 4096
typedef struct board_c
{
uint32_t adc2v4_cail;
uint32_t adc2v4_reverse_verif;
uint32_t flash_id;
uint32_t flash_id_reverse_verif;
uint32_t ft_rest;
uint32_t ft_rest_reverse_verif;
uint32_t chip_cnt;
uint32_t chip_cnt_reverse_verif;
uint32_t rc_cail;
uint32_t rc_cail_reverse_verif;
}board_card_t;
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_fmc_spi_init_oprt(void);
void xc_fmc_spi_flash_power_down(void);
void xc_fmc_spi_flash_wake_up(void);
void xc_fmc_spi_flash_wait_busy(void);
void xc_fmc_spi_flash_write_enable(void);
void xc_fmc_spi_flash_erase_sector(uint32_t addr);
void xc_fmc_spi_flash_erase_page(uint32_t addr);
void xc_fmc_spi_flash_write_page(uint32_t addr, uint8_t *buff,
uint16_t size);
void xc_fmc_spi_flash_read_page(uint32_t addr, uint8_t *buff,
uint16_t size);
void xc_fmc_spi_otp_read_page(uint32_t addr, uint8_t *data,
uint16_t size);
uint8_t xc_fmc_spi_flash_write(uint32_t addr, uint8_t *buff,
uint16_t len);
uint8_t xc_fmc_spi_flash_read(uint32_t addr, uint8_t *buff,
uint16_t len);
void xc_fmc_spi_flash_ruid(uint8_t *ruid);
void xc_fmc_spi_flash_rdid(uint8_t *rdid);
bool flash_size_and_type_get(uint32_t *flash_size, uint16_t *flash_type);
bool xc_adc_2v4_calibrate_read(uint16_t * adc_calibrate);
bool xc_unique_identification_read(uint8_t *unique_id);
#endif /* __XC6xxx_FMC_SPI_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,76 @@
/*!
* \file xc_drv_fmc_spi_dma.h
*
* \brief The header of xc_drv_fmc_spi_dma.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC_DRV_FMC_SPI_DMA_H_
#define __XC_DRV_FMC_SPI_DMA_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define FMC_SSI_DMAC_RDMAE_DISABLE DISABLE
#define FMC_SSI_DMAC_RDMAE_ENABLE ENABLE
#define FMC_SSI_DMAC_TDMAE_DISABLE DISABLE
#define FMC_SSI_DMAC_TDMAE_ENABLE ENABLE
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
__RAM_CODE void xc_fmc_spi_init(void);
__RAM_CODE void xc_fmc_spi_dma_flash_power_down(void);
__RAM_CODE void xc_fmc_spi_dma_flash_wake_up(void);
void xc_fmc_spi_dma_flash_erase_sector(uint32_t Dst_Addr);
void xc_fmc_spi_dma_flash_erase_page(uint32_t Dst_Addr);
void xc_fmc_spi_dma_flash_read_page(uint32_t ReadAddr, uint8_t *data,
uint16_t size);
void xc_fmc_spi_dma_flash_write_page(uint32_t WriteAddr, uint8_t *data,
uint16_t size);
eXC_RESULT xc_fmc_spi_dma_flash_read(uint32_t readAddr, uint8_t *buff,
uint16_t size);
eXC_RESULT xc_fmc_spi_dma_flash_write(uint32_t writeAddr, uint8_t *buff,
uint16_t size);
__RAM_CODE void xc_fmc_spi_dma_write_and_read_data(
uint8_t *w_data, uint16_t w_size,
uint8_t *r_data, uint16_t r_size);
void xc_fmc_spi_dma_read_and_write_data(
uint8_t *w_data, uint16_t w_size,
uint8_t *r_data, uint16_t r_size);
void xc_fmc_spi_dma_flash_rdid(uint8_t *rdid);
void xc_fmc_spi_dma_flash_ruid(uint8_t *ruid);
#endif /* __XC_DRV_FMC_SPI_DMA_H_ */
@@ -0,0 +1,312 @@
/*!
* \file xc_drv_aotimer.c
*
* \brief Target xc aotimer driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_gpio.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
**************************************************************************************
* @brief xc_gpio_init
* @details Initializes the GPIO port based on structure parameters
* @param[in] init_cfg This is the structure parameter that the GPIO initializes
* @param[out] void
* @retval void
* @other
GPIO_InitCfg.Mux = GPIO_Mux0;
GPIO_InitCfg.FunSel = GPIO_Dx;
GPIO_InitCfg.Pull = GPIO_NOPULL;
// Board Led1 Initialization
GPIO_InitCfg.Dir = GPIO_DIR_OUTPUT;
GPIO_InitCfg.Int = NOT_INT;
GPIO_InitCfg.Pin = GPIO_0;
xc_gpio_init(&GPIO_InitCfg);
// Gpio NVIC Enable
//NVIC_EnableIRQ(GPIO_IRQn);
***************************************************************************************
*/
void xc_gpio_init(GPIO_InitCfg_t *init_cfg)
{
xc_gpio_mux_ctl(init_cfg->Pin, init_cfg->Mux);
xc_gpio_fun_sel(init_cfg->Pin, init_cfg->FunSel);
xc_gpio_direction_config(init_cfg->Pin, init_cfg->Dir);
xc_gpio_it_config(init_cfg->Pin, init_cfg->Int);
xc_gpio_pull_config(init_cfg->Pin, init_cfg->Pull);
}
/**
**************************************************************************************
* @brief xc_gpio_init
* @details GPIO Function Selection
* @param[in] num : GPIO number (GPIO_0 -> GPIO_35)
* @param[in] mux : Function Selection
* @param[out] void
* @retval void
* @other
- GPIO0 : < mux=0 gpio_d[0] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO1 : < mux=0 gpio_d[1] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO2 : < mux=0 gpio_d[2] > < mux=1 test_pin[2] > < mux=2 NA > < mux=3 NA >
- GPIO3 : < mux=0 gpio_d[3] > < mux=1 pwm_capture[0] > < mux=2 NA > < mux=3 NA >
- GPIO4 : < mux=0 gpio_d[4] > < mux=1 pwm_brk[0] > < mux=2 NA > < mux=3 NA >
- GPIO5 : < mux=0 gpio_d[5] > < mux=1 pwm_brk[1] > < mux=2 NA > < mux=3 NA >
- GPIO6 : < mux=0 gpio_d[6] > < mux=1 pwm_brk[2] > < mux=2 NA > < mux=3 NA >
- GPIO7 : < mux=0 gpio_d[7] > < mux=1 fmc_d[2] > < mux=2 NA > < mux=3 NA >
- GPIO8 : < mux=0 gpio_d[8] > < mux=1 pwm_capture[1] > < mux=2 NA > < mux=3 NA >
- GPIO9 : < mux=0 gpio_d[9] > < mux=1 pwm_capture[2] > < mux=2 NA > < mux=3 NA >
- GPIO10: < mux=0 gpio_d[10] > < mux=1 fmc_d[3] > < mux=2 NA > < mux=3 NA >
- GPIO11: < mux=0 BOOT_CTL > < mux=1 NA > < mux=2 txen > < mux=3 NA >
- GPIO12: < mux=0 SWI的 SWCK > < mux=1 NA > < mux=2 rxen > < mux=3 NA >
- GPIO13: < mux=0 SWI的 SWD > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO14: < mux=0 gpio_d[14] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO15: < mux=0 gpio_d[15] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO16: < mux=0 gpio_d[16] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO17: < mux=0 gpio_d[17] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO18: < mux=0 gpio_d[18] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO19: < mux=0 gpio_d[19] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO20: < mux=0 gpio_d[20] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO21: < mux=0 gpio_d[21] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO22: < mux=0 gpio_d[22] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO23: < mux=0 gpio_d[23] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO24: < mux=0 gpio_d[24] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO25: < mux=0 gpio_d[25] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO27: < mux=0 gpio_d[27] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO28: < mux=0 gpio_d[28] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO29: < mux=0 gpio_d[29] > < mux=1 gpio_d[29] > < mux=1 NA > < mux=2 NA >
- GPIO30: < mux=0 gpio_d[30] > < mux=1 gpio_d[30] > < mux=1 NA > < mux=2 NA >
- GPIO31: < mux=0 gpio_d[31] > < mux=1 gpio_d[31] > < mux=1 NA > < mux=2 NA >
- GPIO32: < mux=0 gpio_d[32] > < mux=1 NA > < mux=2 NA > < mux=3 NA >
- GPIO33: < mux=0 gpio_d[33] > < mux=1 gpio_d[29] > < mux=1 NA > < mux=2 NA >
- GPIO34: < mux=0 gpio_d[34] > < mux=1 gpio_d[30] > < mux=1 NA > < mux=2 NA >
- GPIO35: < mux=0 gpio_d[35] > < mux=1 gpio_d[31] > < mux=1 NA > < mux=2 NA >
***************************************************************************************
*/
void xc_gpio_mux_ctl(uint8_t num, GPIO_MUX_TypeDef mux)
{
uint8_t reg_idx = num >> 4UL;
uint8_t pin_idx = num & 0xFUL;
uint32_t val;
if (mux > 3)
return;
if (num >= 35)
return;
if (reg_idx == 0) {
val = cpr_ctl_muxctl1_get();
val = (val & (~(0x3 << (pin_idx << 1)))) | (mux << (pin_idx << 1));
cpr_ctl_muxctl1_set(val);
} else if (reg_idx == 1) {
val = cpr_ctl_muxctl2_get();
val = (val & (~(0x3 << (pin_idx << 1)))) | (mux << (pin_idx << 1));
cpr_ctl_muxctl2_set(val);
} else if (reg_idx == 2) {
val = cpr_ctl_muxctl3_get();
val = (val & (~(0x3 << (pin_idx << 1)))) | (mux << (pin_idx << 1));
cpr_ctl_muxctl3_set(val);
}
}
void xc_gpio_fun_sel(uint8_t num, GPIO_FUN_SEL_TypeDef sel)
{
uint32_t val;
uint8_t reg_idx = num >> 2UL;
uint8_t pin_idx = num & 0x3UL;
if (num > 28)
return;
val = cpr_gpio_fun_sel_get(reg_idx);
val = (val & ~(0x1FUL << (pin_idx << 3UL))) | (sel << (pin_idx << 3UL));
cpr_gpio_fun_sel_set(reg_idx, val);
}
void xc_gpio_pull_config(uint8_t num, GPIO_PULL_TypeDef pull)
{
uint8_t reg_idx;
uint8_t pin_idx;
uint32_t val;
reg_idx = num >> 4UL;
pin_idx = num & 0xFUL;
if (num >= 32) {
pin_idx += 2;
}
if (GPIO_PULLUP == pull) {
if (reg_idx == 0) {
val = cprao_aon_pectrl1_get();
SET_BIT(val, 1 << ((pin_idx << 1) + 1));
CLEAR_BIT(val, 1 << (pin_idx << 1));
cprao_aon_pectrl1_set(val);
} else if (reg_idx == 1) {
val = cprao_aon_pectrl2_get();
SET_BIT(val, 1 << ((pin_idx << 1) + 1));
CLEAR_BIT(val, 1 << (pin_idx << 1));
cprao_aon_pectrl2_set(val);
} else if (reg_idx == 2) {
val = cprao_aon_puctrl1_get();
SET_BIT(val, 1 << ((pin_idx << 1) + 1));
CLEAR_BIT(val, 1 << (pin_idx << 1));
cprao_aon_puctrl1_set(val);
}
} else if (GPIO_PULLDOWN == pull) {
if (reg_idx == 0) {
val = cprao_aon_pectrl1_get();
CLEAR_BIT(val, 1 << ((pin_idx << 1) + 1));
SET_BIT(val, 1 << (pin_idx << 1));
cprao_aon_pectrl1_set(val);
} else if (reg_idx == 1) {
val = cprao_aon_pectrl2_get();
CLEAR_BIT(val, 1 << ((pin_idx << 1) + 1));
SET_BIT(val, 1 << (pin_idx << 1));
cprao_aon_pectrl2_set(val);
} else if (reg_idx == 2) {
val = cprao_aon_puctrl1_get();
CLEAR_BIT(val, 1 << ((pin_idx << 1) + 1));
SET_BIT(val, 1 << (pin_idx << 1));
cprao_aon_puctrl1_set(val);
}
} else if (GPIO_NOPULL == pull) {
if (reg_idx == 0) {
val = cprao_aon_pectrl1_get();
CLEAR_BIT(val, 1 << ((pin_idx << 1) + 1));
CLEAR_BIT(val, 1 << (pin_idx << 1));
cprao_aon_pectrl1_set(val);
} else if (reg_idx == 1) {
val = cprao_aon_pectrl2_get();
CLEAR_BIT(val, 1 << ((pin_idx << 1) + 1));
CLEAR_BIT(val, 1 << (pin_idx << 1));
cprao_aon_pectrl2_set(val);
} else if (reg_idx == 2) {
val = cprao_aon_puctrl1_get();
CLEAR_BIT(val, 1 << ((pin_idx << 1) + 1));
CLEAR_BIT(val, 1 << (pin_idx << 1));
cprao_aon_puctrl1_set(val);
}
}
}
void xc_gpio_it_config(uint8_t num, GPIO_INT_TypeDef inter)
{
uint32_t val;
uint8_t reg_idx = num >> 2UL;
uint8_t pin_idx = num & 0x3UL;
val = gpio_intr_ctrl_get(reg_idx);
val = (val & ~(0xF0000UL) & ~(0xFUL << (pin_idx << 2UL))) |
(inter << (pin_idx << 2UL)) | ((0x01UL << pin_idx) << 16UL);
gpio_intr_ctrl_set(reg_idx, val);
}
void xc_gpio_direction_config(uint8_t num, GPIO_DIR_TypeDef direction)
{
uint8_t reg_idx = num >> 4UL;
uint8_t pin_idx = num & 0xFUL;
uint32_t val;
val = (direction << pin_idx) | (1 << 16 << pin_idx);
gpio_port_ddr_set(reg_idx, val);
}
uint32_t xc_gpio_read_pin(uint8_t num)
{
uint8_t reg_idx = num >> 5UL;
uint8_t pin_idx = num & 0x1FUL;
uint32_t value = gpio_ext_port_get(reg_idx);
return (value & (0x01UL << pin_idx)) ? (1) : (0);
}
void xc_gpio_write_pin(uint8_t num, GPIO_PinState pin_state)
{
uint8_t reg_idx = num >> 4UL;
uint8_t pin_idx = num & 0xFUL;
gpio_port_dr_set(reg_idx, (1 << DR_WE_LSB | pin_state) << pin_idx);
}
void xc_gpio_toggle_pin(uint8_t num)
{
uint8_t reg_idx = num >> 4UL;
uint8_t pin_idx = num & 0xFUL;
if ((gpio_port_dr_get(reg_idx) & (1 << pin_idx)) != GPIO_PIN_RESET) {
gpio_port_dr_set(reg_idx, (1 << DR_WE_LSB | GPIO_PIN_RESET) << pin_idx);
} else {
gpio_port_dr_set(reg_idx, (1 << DR_WE_LSB | GPIO_PIN_SET) << pin_idx);
}
}
void GPIO_Handler(void)
{
uint64_t intr_sta;
uint64_t val;
intr_sta = gpio_intr_status_c_get(0);
val = intr_sta;
gpio_intr_clr_set(0, (uint32_t)intr_sta);
intr_sta = gpio_intr_status_c_get(1);
val |= intr_sta << 32;
gpio_intr_clr_set(1, (uint32_t)intr_sta);
gpio_intr_callback(val);
}
__WEAK void gpio_intr_callback(uint64_t intr_sta)
{
/* Gpio 中断回调处理函数 */
}
@@ -0,0 +1,181 @@
/*!
* \file xc_drv_aotimer.h
*
* \brief The header of xc_drv_aotimer.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_GPIO_H_
#define _XC_DRV_GPIO_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
GPIO_PIN_RESET = 0u,
GPIO_PIN_SET
} GPIO_PinState;
enum
{
GPIO_0,
GPIO_1,
GPIO_2,
GPIO_3,
GPIO_4,
GPIO_5,
GPIO_6,
GPIO_7,
GPIO_8,
GPIO_9,
GPIO_10,
GPIO_11,
GPIO_12,
GPIO_13,
GPIO_14,
GPIO_15,
GPIO_16,
GPIO_17,
GPIO_18,
GPIO_19,
GPIO_20,
GPIO_21,
GPIO_22,
GPIO_23,
GPIO_24,
GPIO_25,
GPIO_26,
GPIO_27,
GPIO_28,
GPIO_29,
GPIO_30,
GPIO_31,
GPIO_32,
GPIO_33,
GPIO_34,
GPIO_35,
GPIO_36,
GPIO_37,
GPIO_38,
GPIO_39,
GPIO_MAX,
GPIO_NONE
};
typedef enum
{
GPIO_Mux0 = 0,
GPIO_Mux1,
GPIO_Mux2,
GPIO_Mux3
} GPIO_MUX_TypeDef;
typedef enum
{
GPIO_Dx = 0,
UART0_TX,
UART0_RX,
UART0_CTS,
UART0_RTS,
I2C_SCL,
I2C_SDA,
UART1_RX,
UART1_TX,
SIM_IO,
SIM_RST,
SIM_CLK_OUT,
PWM0,
PWM1,
SSI1_CLK,
SSI1_SSN,
SSI1_RX,
SSI1_TX,
PWM0_INV,
PWM1_INV,
} GPIO_FUN_SEL_TypeDef;
typedef enum
{
GPIO_PULLUP = 0,
GPIO_PULLDOWN = 1,
GPIO_NOPULL = 2,
} GPIO_PULL_TypeDef;
typedef enum
{
GPIO_DIR_INPUT = 0,
GPIO_DIR_OUTPUT
} GPIO_DIR_TypeDef;
typedef enum
{
NOT_INT = 0,
NA1_INT,
NA2_INT,
NA3_INT,
NA4_INT,
RIS_EDGE_INT,
NA6_INT,
FAIL_EDGE_INT,
NA8_INT,
RIS_FAIL_EDGE_INT,
} GPIO_INT_TypeDef;
typedef struct
{
uint16_t Pin;
GPIO_MUX_TypeDef Mux;
GPIO_FUN_SEL_TypeDef FunSel;
GPIO_DIR_TypeDef Dir;
GPIO_PULL_TypeDef Pull;
GPIO_INT_TypeDef Int;
} GPIO_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_gpio_init(GPIO_InitCfg_t *init_cfg);
void xc_gpio_mux_ctl(uint8_t num, GPIO_MUX_TypeDef mux);
void xc_gpio_fun_sel(uint8_t num, GPIO_FUN_SEL_TypeDef sel);
void xc_gpio_pull_config(uint8_t num, GPIO_PULL_TypeDef pull);
void xc_gpio_it_config(uint8_t num, GPIO_INT_TypeDef inter);
void xc_gpio_direction_config(uint8_t num, GPIO_DIR_TypeDef direction);
uint32_t xc_gpio_read_pin(uint8_t num);
void xc_gpio_write_pin(uint8_t num, GPIO_PinState pin_state);
void xc_gpio_toggle_pin(uint8_t num);
void gpio_intr_callback(uint64_t intr_sta);
#endif // _XC_DRV_AOTIMER_H_
@@ -0,0 +1,272 @@
/*!
* \file xc_drv_i2c.c
*
* \brief Target xc i2c driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*------------------------------------------------------------------------------------
INCLUDE HEADE FILES
-------------------------------------------------------------------------------------*/
#include "xc_drv_i2c.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
I2C_Block_t i2c_ctl_block;
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
void xc_i2c_ctl_block_reset(void);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_i2c_init(I2C_InitCfg_t *init_cfg)
{
cpr_ctlapbclken_grctl__i2c_pclk_en__setf(ENABLE);
cpr_rstctl_subrst_sw__i2c_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__i2c_rstn__setf(RSTCTL_DISABLE);
cpr_i2c_clk_ctl__i2c_clk_en__setf(ENABLE);
cpr_i2c_clk_ctl__i2c_clk_div__setf(init_cfg->DivClk);
i2c_flag_status_get(I2C_STATUS_ACTIVITY_SET);
i2c_enable__enable__setf(I2C_ENABLE_EN_DISABLE);
i2c_rx_tl__rx_tl__setf(I2C_RX_TL_FIFO_1);
i2c_tx_tl__tx_tl__setf(I2C_TX_TL_FIFO_0);
i2c_intr_en_set(I2C_INTR_EN_RX_UNDER_DISABLE | I2C_INTR_EN_RX_OVER_DISABLE | I2C_INTR_EN_RX_FULL_DISABLE |
I2C_INTR_EN_TX_OVER_DISABLE | I2C_INTR_EN_TX_EMPTY_DISABLE | I2C_INTR_EN_RD_REQ_DISABLE |
I2C_INTR_EN_TX_ABRT_DISABLE | I2C_INTR_EN_RX_DONE_DISABLE | I2C_INTR_EN_ACTIVITY_DISABLE |
I2C_INTR_EN_STOP_DET_DISABLE | I2C_INTR_EN_START_DET_DISABLE | I2C_INTR_EN_GEN_CALL_DISABLE);
i2c_tar__i2c_10bitaddr_master__setf(I2C_TAR_I2C_7BITADDR_MODE);
if (init_cfg->I2C_Mode == I2C_MODE_MASTER) {
i2c_tar__i2c_tar__setf(init_cfg->I2C_SlaveAddr);
i2c_con__master_mode__setf(I2C_CON_MASTER_MODE_ENABLE);
i2c_con__slave_disable__setf(I2C_CON_SLAVE_DISABLE_DISABLE);
} else if (init_cfg->I2C_Mode == I2C_MODE_SLAVE) {
i2c_sar__setf(init_cfg->I2C_SlaveAddr);
i2c_con__master_mode__setf(I2C_CON_MASTER_MODE_DISABLE);
i2c_con__slave_disable__setf(I2C_CON_SLAVE_DISABLE_ENABLE);
i2c_con__addr_10bit_slave__setf(I2C_CON_7BITADDR_SLAVE_MODE);
i2c_con__restart_en__setf(I2C_CON_RESTART_EN_DISABLE);
}
xc_i2c_ctl_block_reset();
if (init_cfg->I2C_ClockSpeed == I2C_FREQUENCY_100K) {
i2c_con__speed__setf(I2C_CON_SPEED_STANDARD_MODE);
if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) {
i2c_ss_scl_hcnt__ss_scl_hcnt__setf(I2C_MLCK32M_FREQUENCY_HCNT_100K);
i2c_ss_scl_lcnt__ss_scl_lcnt__setf(I2C_MLCK32M_FREQUENCY_LCNT_100K);
} else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) {
i2c_ss_scl_hcnt__ss_scl_hcnt__setf(I2C_MLCK48M_FREQUENCY_HCNT_100K);
i2c_ss_scl_lcnt__ss_scl_lcnt__setf(I2C_MLCK48M_FREQUENCY_LCNT_100K);
} else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) {
i2c_ss_scl_hcnt__ss_scl_hcnt__setf(I2C_MLCK64M_FREQUENCY_HCNT_100K);
i2c_ss_scl_lcnt__ss_scl_lcnt__setf(I2C_MLCK64M_FREQUENCY_LCNT_100K);
}
} else if (init_cfg->I2C_ClockSpeed == I2C_FREQUENCY_400K) {
i2c_con__speed__setf(I2C_CON_SPEED_FAST_MODE);
if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) {
i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK32M_FREQUENCY_HCNT_400K);
i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MLCK32M_FREQUENCY_LCNT_400K);
} else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) {
i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK48M_FREQUENCY_HCNT_400K);
i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MLCK48M_FREQUENCY_LCNT_400K);
} else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) {
i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK64M_FREQUENCY_HCNT_400K);
i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MLCK64M_FREQUENCY_LCNT_400K);
}
} else {
i2c_con__speed__setf(I2C_CON_SPEED_FAST_MODE);
if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) {
i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK32M_FREQUENCY_HCNT_1M);
i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MCLK32M_FREQUENCY_LCNT_1M);
} else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) {
i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK48M_FREQUENCY_HCNT_1M);
i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MCLK48M_FREQUENCY_LCNT_1M);
} else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) {
i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK64M_FREQUENCY_HCNT_1M);
i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MCLK64M_FREQUENCY_LCNT_1M);
}
}
i2c_flag_status_get(I2C_STATUS_ACTIVITY_SET);
i2c_enable__enable__setf(I2C_ENABLE_EN_ENABLE);
}
void xc_i2c_enable_it(uint32_t val) { i2c_intr_en_set(val); }
void xc_i2c_fifo_rxtl_set(uint32_t val) { i2c_rx_tl__rx_tl__setf(val); }
void xc_i2c_fifo_txtl_set(uint32_t val) { i2c_tx_tl__tx_tl__setf(val); }
void xc_i2c_ctl_block_reset(void)
{
memset(&i2c_ctl_block, 0, sizeof(i2c_ctl_block));
i2c_ctl_block.i2c_read_cb = NULL;
i2c_ctl_block.i2c_write_cb = NULL;
}
void xc_i2c_register_read_cb(i2c_read_callback i2c_cb) { i2c_ctl_block.i2c_read_cb = i2c_cb; }
void xc_i2c_register_write_cb(i2c_write_callback i2c_cb) { i2c_ctl_block.i2c_write_cb = i2c_cb; }
void xc_i2c_slave_addr_set(uint8_t addr)
{
i2c_enable__enable__setf(I2C_ENABLE_EN_DISABLE);
i2c_tar__i2c_tar__setf(addr);
i2c_enable__enable__setf(I2C_ENABLE_EN_ENABLE);
}
uint32_t xc_i2c_write_block(uint8_t dev_addr, uint8_t *src, size_t len, uint16_t reset, uint16_t stop)
{
xc_i2c_slave_addr_set(dev_addr);
uint32_t abort_reason = 0;
uint16_t timeout = 0xFFFF;
for (int i = 0; i < len; i++) {
i2c_data_cmd_set(I2C_DATA_CMD_CMD_WRITE | stop | reset | *src++);
do {
} while (timeout-- && !(i2c_raw_intr_stat_get() & I2C_RAW_INTR_STAT_TX_EMPTY_SET));
if (!timeout) {
break;
}
abort_reason = i2c_tx_abrt_source_get();
if (abort_reason) {
i2c_clr_tx_abrt_get();
break;
}
}
return abort_reason;
}
uint32_t xc_i2c_read_block(uint8_t dev_addr, uint8_t *dst, size_t len, uint16_t reset, uint16_t stop)
{
xc_i2c_slave_addr_set(dev_addr);
uint32_t abort_reason;
uint16_t timeout = 0xFFFF;
for (int i = 0; i < len; i++) {
while (!(I2C_FIFO_LEN - i2c_txflr_get()))
;
i2c_data_cmd_set(I2C_DATA_CMD_CMD_READ | stop | reset);
do {
} while (timeout-- && !i2c_rxflr_get());
if (!timeout) {
DEBUG("xc_i2c_read_block timeout\n");
break;
}
abort_reason = i2c_tx_abrt_source_get();
if (abort_reason) {
DEBUG("xc_i2c_read_block tx_abrt\n");
i2c_clr_tx_abrt_get();
break;
}
*dst++ = i2c_data_cmd_get();
}
return abort_reason;
}
void i2c_user_handler()
{
uint8_t val;
uint32_t stat;
stat = i2c_intr_stat_get();
val = i2c_clr_intr_get();
if (stat & I2C_INTR_STAT_RX_DONE_SET) {
}
if (stat & I2C_INTR_STAT_RX_FULL_SET) {
val = i2c_data_cmd__dat__getf();
if (i2c_ctl_block.i2c_read_cb != NULL) {
i2c_ctl_block.i2c_read_cb(&val, 1);
}
}
if (stat & I2C_INTR_STAT_RD_REQ_SET) {
if (i2c_ctl_block.i2c_write_cb != NULL) {
i2c_ctl_block.i2c_write_cb();
}
}
if (stat & I2C_INTR_STAT_TX_EMPTY_SET) {
}
if (stat & I2C_INTR_STAT_STOP_DET_SET) {
}
}
FlagStatus i2c_flag_status_get(uint32_t i2c_flag)
{
FlagStatus bitstatus = RESET;
if ((i2c_status_get() & i2c_flag) != (uint32_t)RESET) {
bitstatus = SET;
} else {
bitstatus = RESET;
}
return bitstatus;
}
void I2C_Handler() { i2c_user_handler(); }
@@ -0,0 +1,312 @@
/*!
* \file xc_drv_i2c.h
*
* \brief The header of xc_drv_i2c.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_I2C_H_
#define _XC_DRV_I2C_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
#define I2C_FIFO_LEN 16
/* I2C Init structure definition */
typedef struct
{
uint32_t I2C_ClockSpeed;
uint16_t I2C_Mode;
uint16_t I2C_SlaveAddr;
uint8_t DivClk;
} I2C_InitCfg_t;
enum
{
I2C_FREQUENCY_100K = 0,
I2C_FREQUENCY_400K = 1,
I2C_FREQUENCY_1M = 2,
};
typedef void (*i2c_write_callback)(void);
typedef void (*i2c_read_callback)(uint8_t* buff, uint16_t len);
typedef struct{
i2c_read_callback i2c_read_cb;
i2c_write_callback i2c_write_cb;
} I2C_Block_t;
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define I2C_CON_MASTER_MODE_ENABLE (0x1UL)
#define I2C_CON_MASTER_MODE_DISABLE (0x0UL)
#define I2C_CON_SPEED_STANDARD_MODE (0x1UL)
#define I2C_CON_SPEED_FAST_MODE (0x2UL)
#define I2C_CON_10BITADDR_SLAVE_MODE (0x1UL)
#define I2C_CON_7BITADDR_SLAVE_MODE (0x0UL)
#define I2C_CON_10BITADDR_MASTER_MODE (0x1UL)
#define I2C_CON_7BITADDR_MASTER_MODE (0x0UL)
#define I2C_CON_RESTART_EN_ENABLE (0x1UL)
#define I2C_CON_RESTART_EN_DISABLE (0x0UL)
#define I2C_CON_SLAVE_DISABLE_ENABLE (0x0UL)
#define I2C_CON_SLAVE_DISABLE_DISABLE (0x1UL)
#define I2C_TAR_GC_OR_START_GC (0x0UL)
#define I2C_TAR_GC_OR_START_Start (0x1UL)
#define I2C_TAR_SPECIA_EXECUTE (0x1UL)
#define I2C_TAR_SPECIA_IGNORE (0x0UL)
#define I2C_TAR_I2C_10BITADDR_MODE (0x1UL)
#define I2C_TAR_I2C_7BITADDR_MODE (0x0UL)
#define I2C_DATA_CMD_CMD_READ (0x1UL << CMD_POS)
#define I2C_DATA_CMD_CMD_WRITE (0x0UL << CMD_POS)
#define I2C_DATA_CMD_STOP_SET (0x1UL << I2C_STOP_POS)
#define I2C_DATA_CMD_STOP_RESET (0x0UL << I2C_STOP_POS)
#define I2C_DATA_CMD_RESTART_SET (0x1UL << RESTART_POS)
#define I2C_DATA_CMD_RESTART_RESET (0x0UL << RESTART_POS)
#define I2C_DATA_CMD_DAT_SET (0x1UL << DAT_LSB)
#define I2C_DATA_CMD_DAT_RESET (0x0UL << DAT_LSB)
#define I2C_MLCK32M_FREQUENCY_HCNT_100K (0x8EUL)
#define I2C_MLCK32M_FREQUENCY_LCNT_100K (0x9EUL)
#define I2C_MLCK32M_FREQUENCY_HCNT_400K (0x18UL)
#define I2C_MLCK32M_FREQUENCY_LCNT_400K (0x25UL)
#define I2C_MLCK32M_FREQUENCY_HCNT_1M (0x07UL)
#define I2C_MCLK32M_FREQUENCY_LCNT_1M (0x0AUL)
#define I2C_MLCK48M_FREQUENCY_HCNT_100K (0xDBUL)
#define I2C_MLCK48M_FREQUENCY_LCNT_100K (0xEBUL)
#define I2C_MLCK48M_FREQUENCY_HCNT_400K (0x28UL)
#define I2C_MLCK48M_FREQUENCY_LCNT_400K (0x38UL)
#define I2C_MLCK48M_FREQUENCY_HCNT_1M (0x0DUL)
#define I2C_MCLK48M_FREQUENCY_LCNT_1M (0x0FUL)
#define I2C_MLCK64M_FREQUENCY_HCNT_100K (0x128UL)
#define I2C_MLCK64M_FREQUENCY_LCNT_100K (0x138UL)
#define I2C_MLCK64M_FREQUENCY_HCNT_400K (0x39UL)
#define I2C_MLCK64M_FREQUENCY_LCNT_400K (0x49UL)
#define I2C_MLCK64M_FREQUENCY_HCNT_1M (0x10UL)
#define I2C_MCLK64M_FREQUENCY_LCNT_1M (0x14UL)
#define I2C_INTR_STAT_RX_UNDER_RESET (0x0UL << R_RX_UNDER_POS)
#define I2C_INTR_STAT_RX_UNDER_SET (0x1UL << R_RX_UNDER_POS)
#define I2C_INTR_STAT_RX_OVER_RESET (0x0UL << R_RX_OVER_POS)
#define I2C_INTR_STAT_RX_OVER_SET (0x1UL << R_RX_OVER_POS)
#define I2C_INTR_STAT_RX_FULL_RESET (0x0UL << R_RX_FULL_POS)
#define I2C_INTR_STAT_RX_FULL_SET (0x1UL << R_RX_FULL_POS)
#define I2C_INTR_STAT_TX_OVER_RESET (0x0UL << R_TX_OVER_POS)
#define I2C_INTR_STAT_TX_OVER_SET (0x1UL << R_TX_OVER_POS)
#define I2C_INTR_STAT_TX_EMPTY_RESET (0x0UL << R_TX_EMPTY_POS)
#define I2C_INTR_STAT_TX_EMPTY_SET (0x1UL << R_TX_EMPTY_POS)
#define I2C_INTR_STAT_RD_REQ_RESET (0x0UL << R_RD_REQ_POS)
#define I2C_INTR_STAT_RD_REQ_SET (0x1UL << R_RD_REQ_POS)
#define I2C_INTR_STAT_TX_ABRT_RESET (0x0UL << R_TX_ABRT_POS)
#define I2C_INTR_STAT_TX_ABRT_SET (0x1UL << R_TX_ABRT_POS)
#define I2C_INTR_STAT_RX_DONE_RESET (0x0UL << R_RX_DONE_POS)
#define I2C_INTR_STAT_RX_DONE_SET (0x1UL << R_RX_DONE_POS)
#define I2C_INTR_STAT_ACTIVITY_RESET (0x0UL << R_ACTIVITY_POS)
#define I2C_INTR_STAT_ACTIVITY_SET (0x1UL << R_ACTIVITY_POS)
#define I2C_INTR_STAT_STOP_DET_RESET (0x0UL << R_STOP_DET_POS)
#define I2C_INTR_STAT_STOP_DET_SET (0x1UL << R_STOP_DET_POS)
#define I2C_INTR_STAT_START_DET_RESET (0x1UL << R_START_DET_POS)
#define I2C_INTR_STAT_START_DET_SET (0x1UL << R_START_DET_POS)
#define I2C_INTR_STAT_GEN_CALL_RESET (0x0UL << R_GEN_CALL_POS)
#define I2C_INTR_STAT_GEN_CALL_SET (0x1UL << R_GEN_CALL_POS)
#define I2C_INTR_EN_RX_UNDER_DISABLE (0x0UL << EN_RX_UNDER_POS)
#define I2C_INTR_EN_RX_UNDER_ENABLE (0x1UL << EN_RX_UNDER_POS)
#define I2C_INTR_EN_RX_OVER_DISABLE (0x0UL << EN_RX_OVER_POS)
#define I2C_INTR_EN_RX_OVER_ENABLE (0x1UL << EN_RX_OVER_POS)
#define I2C_INTR_EN_RX_FULL_DISABLE (0x0UL << EN_RX_FULL_POS)
#define I2C_INTR_EN_RX_FULL_ENABLE (0x1UL << EN_RX_FULL_POS)
#define I2C_INTR_EN_TX_OVER_DISABLE (0x0UL << EN_TX_OVER_POS)
#define I2C_INTR_EN_TX_OVER_ENABLE (0x1UL << EN_TX_OVER_POS)
#define I2C_INTR_EN_TX_EMPTY_DISABLE (0x0UL << EN_TX_EMPTY_POS)
#define I2C_INTR_EN_TX_EMPTY_ENABLE (0x1UL << EN_TX_EMPTY_POS)
#define I2C_INTR_EN_RD_REQ_DISABLE (0x0UL << EN_RD_REQ_POS)
#define I2C_INTR_EN_RD_REQ_ENABLE (0x1UL << EN_RD_REQ_POS)
#define I2C_INTR_EN_TX_ABRT_DISABLE (0x0UL << EN_TX_ABRT_POS)
#define I2C_INTR_EN_TX_ABRT_ENABLE (0x1UL << EN_TX_ABRT_POS)
#define I2C_INTR_EN_RX_DONE_DISABLE (0x0UL << EN_RX_DONE_POS)
#define I2C_INTR_EN_RX_DONE_ENABLE (0x1UL << EN_RX_DONE_POS)
#define I2C_INTR_EN_ACTIVITY_DISABLE (0x0UL << EN_ACTIVITY_POS)
#define I2C_INTR_EN_ACTIVITY_ENABLE (0x1UL << EN_ACTIVITY_POS)
#define I2C_INTR_EN_STOP_DET_DISABLE (0x0UL << EN_STOP_DET_POS)
#define I2C_INTR_EN_STOP_DET_ENABLE (0x1UL << EN_STOP_DET_POS)
#define I2C_INTR_EN_START_DET_DISABLE (0x0UL << EN_START_DET_POS)
#define I2C_INTR_EN_START_DET_ENABLE (0x1UL << EN_START_DET_POS)
#define I2C_INTR_EN_GEN_CALL_DISABLE (0x0UL << EN_GEN_CALL_POS)
#define I2C_INTR_EN_GEN_CALL_ENABLE (0x1UL << EN_GEN_CALL_POS)
#define I2C_RAW_INTR_STAT_RX_UNDER_RESET (0x0UL << RX_UNDER_POS)
#define I2C_RAW_INTR_STAT_RX_UNDERL_SET (0x1UL << RX_UNDER_POS)
#define I2C_RAW_INTR_STAT_RX_OVER_RESET (0x0UL << RX_OVER_POS)
#define I2C_RAW_INTR_STAT_RX_OVER_SET (0x1UL << RX_OVER_POS)
#define I2C_RAW_INTR_STAT_RX_FULL_RESET (0x0UL << RX_FULL_POS)
#define I2C_RAW_INTR_STAT_RX_FULL_SET (0x1UL << RX_FULL_POS)
#define I2C_RAW_INTR_STAT_TX_OVER_RESET (0x0UL << TX_OVER_POS)
#define I2C_RAW_INTR_STAT_TX_OVER_SET (0x1UL << TX_OVER_POS)
#define I2C_RAW_INTR_STAT_TX_EMPTY_RESET (0x0UL << TX_EMPTY_POS)
#define I2C_RAW_INTR_STAT_TX_EMPTY_SET (0x1UL << TX_EMPTY_POS)
#define I2C_RAW_INTR_STAT_RD_REQ_RESET (0x0UL << RD_REQ_POS)
#define I2C_RAW_INTR_STAT_RD_REQ_SET (0x1UL << RD_REQ_POS)
#define I2C_RAW_INTR_STAT_TX_ABRT_RESET (0x0UL << TX_ABRT_POS)
#define I2C_RAW_INTR_STAT_TX_ABRT_SET (0x1UL << TX_ABRT_POS)
#define I2C_RAW_INTR_STAT_RX_DONE_RESET (0x0UL << RX_DONE_POS)
#define I2C_RAW_INTR_STAT_RX_DONE_SET (0x1UL << RX_DONE_POS)
#define I2C_RAW_INTR_STAT_ACTIVITY_RESET (0x0UL << ACTIVITY_POS)
#define I2C_RAW_INTR_STAT_ACTIVITY_SET (0x1UL << ACTIVITY_POS)
#define I2C_RAW_INTR_STAT_STOP_DET_RESET (0x0UL << STOP_DET_POS)
#define I2C_RAW_INTR_STAT_STOP_DET_SET (0x1UL << STOP_DET_POS)
#define I2C_RAW_INTR_STAT_START_DET_RESET (0x0UL << START_DET_POS)
#define I2C_RAW_INTR_STAT_START_DET_SET (0x1UL << START_DET_POS)
#define I2C_RAW_INTR_STAT_GEN_CALL_RESET (0x0UL << GEN_CALL_POS)
#define I2C_RAW_INTR_STAT_GEN_CALL_SET (0x1UL << GEN_CALL_POS)
#define I2C_RX_TL_FIFO_1 (0x0UL)
#define I2C_RX_TL_FIFO_2 (0x1UL)
#define I2C_RX_TL_FIFO_3 (0x2UL)
#define I2C_RX_TL_FIFO_4 (0x3UL)
#define I2C_RX_TL_FIFO_5 (0x4UL)
#define I2C_RX_TL_FIFO_6 (0x5UL)
#define I2C_RX_TL_FIFO_7 (0x6UL)
#define I2C_RX_TL_FIFO_8 (0x7UL)
#define I2C_RX_TL_FIFO_9 (0x8UL)
#define I2C_RX_TL_FIFO_10 (0x9UL)
#define I2C_RX_TL_FIFO_11 (0xAUL)
#define I2C_RX_TL_FIFO_12 (0xBUL)
#define I2C_RX_TL_FIFO_13 (0xCUL)
#define I2C_RX_TL_FIFO_14 (0xDUL)
#define I2C_RX_TL_FIFO_15 (0xEUL)
#define I2C_RX_TL_FIFO_16 (0xFUL)
#define I2C_TX_TL_FIFO_0 (0x0UL)
#define I2C_TX_TL_FIFO_1 (0x1UL)
#define I2C_TX_TL_FIFO_2 (0x2UL)
#define I2C_TX_TL_FIFO_3 (0x3UL)
#define I2C_TX_TL_FIFO_4 (0x4UL)
#define I2C_TX_TL_FIFO_5 (0x5UL)
#define I2C_TX_TL_FIFO_6 (0x6UL)
#define I2C_TX_TL_FIFO_7 (0x7UL)
#define I2C_TX_TL_FIFO_8 (0x8UL)
#define I2C_TX_TL_FIFO_9 (0x9UL)
#define I2C_TX_TL_FIFO_10 (0xAUL)
#define I2C_TX_TL_FIFO_11 (0xBUL)
#define I2C_TX_TL_FIFO_12 (0xCUL)
#define I2C_TX_TL_FIFO_13 (0xDUL)
#define I2C_TX_TL_FIFO_14 (0xEUL)
#define I2C_TX_TL_FIFO_15 (0xFUL)
#define I2C_ENABLE_EN_DISABLE (0x0UL)
#define I2C_ENABLE_EN_ENABLE (0x1UL)
#define I2C_STATUS_ACTIVITY_RESET (0x0UL << I2C_ACTIVITY_POS)
#define I2C_STATUS_ACTIVITY_SET (0x1UL << I2C_ACTIVITY_POS)
#define I2C_STATUS_TFNF_RESET (0x0UL << TFNF_POS)
#define I2C_STATUS_TFNF_SET (0x1UL << TFNF_POS)
#define I2C_STATUS_TFE_RESET (0x0UL << TFE_POS)
#define I2C_STATUS_TFE_SET (0x1UL << TFE_POS)
#define I2C_STATUS_RFNE_RESET (0x0UL << RFNE_POS)
#define I2C_STATUS_RFNE_SET (0x1UL << RFNE_POS)
#define I2C_STATUS_RFF_RESET (0x0UL << RFF_POS)
#define I2C_STATUS_RFF_SET (0x1UL << RFF_POS)
#define I2C_STATUS_MST_ACTIVITY_RESET (0x0UL << 5)
#define I2C_STATUS_MST_ACTIVITY_SET (0x1UL << 5)
#define I2C_MODE_MASTER I2C_CON_MASTER_MODE_ENABLE
#define I2C_MODE_SLAVE I2C_CON_SLAVE_DISABLE_ENABLE
#define I2C_CLOCK_SPEED_100K I2C_FREQUENCY_100K
#define I2C_CLOCK_SPEED_400K I2C_FREQUENCY_400K
#define I2C_CLOCK_SPEED_1M I2C_FREQUENCY_1M
void xc_i2c_init(I2C_InitCfg_t *i2c_cfg);
void xc_i2c_enable_it(uint32_t val);
void xc_i2c_fifo_rxtl_set(uint32_t val);
void xc_i2c_fifo_txtl_set(uint32_t val);
FlagStatus i2c_flag_status_get(uint32_t i2c_flag);
void xc_i2c_register_read_cb(i2c_read_callback i2c_cb);
void xc_i2c_register_write_cb(i2c_write_callback i2c_cb);
uint32_t xc_i2c_write_block(uint8_t dev_addr, uint8_t *src, size_t len, uint16_t reset, uint16_t stop);
uint32_t xc_i2c_read_block(uint8_t dev_addr, uint8_t *dst, size_t len, uint16_t reset, uint16_t stop);
#endif
@@ -0,0 +1,243 @@
/*!
* \file xc_drv_pga.c
*
* \brief Target pga implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_pga.h"
#include "xc60xx.h"
#include "xc_reg_cpr.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/**
* @brief xc_pga_init
* @details
* @param void
* @retval void
*/
void xc_pga_init(PGA_InitCfg_t *pga_cfg)
{
/*opa level 1 gain +20DB*/
cpr_opa_ctrl_reg__micgain_2__setf(pga_cfg->gain2);
/*opa level 2 gain +22.6DB*/
cpr_opa_ctrl_reg__volr_2__setf(pga_cfg->volr2);
/*bias register controls current and difference MIC*/
cpr_opa_ctrl_reg__resadj__setf(pga_cfg->resadj);
/*Comparator hysteresis voltage control*/
cpr_opa_ctrl_reg__cmp_ctrl__setf(pga_cfg->cmp_ctrl);
/*Comparator current control*/
cpr_opa_ctrl_reg__cmp_ibc__setf(pga_cfg->cmp_ibc);
/*temperature sensor*/
cpr_opa_ctrl_reg__en_temp_sensor__setf(pga_cfg->en_temp_sensor);
/*open pdbias*/
cpr_opa_ctrl_reg__pdbias__setf(pga_cfg->bias);
cpr_opa_ctrl_reg__opa_ctrl__setf(pga_cfg->opa_ctrl);
/*opa pd signal*/
cpr_opa_ctrl_reg__pdopa__setf(pga_cfg->pdopa);
cpr_opa_ctrl_reg__micgain__setf(pga_cfg->micgain);
}
/**
********************************************************************************************
* @brief xc_pga_micgain_2_set
* @details
* @param micgain2 (BIT0) £ºinput First-order gain ( PGA_MIC_GAIN2_ENABLE - PGA_MIC_GAIN2_DISABLE)
* @retval void
*********************************************************************************************
**/
void xc_pga_micgain_2_set(uint8_t micgain2)
{
cpr_opa_ctrl_reg__micgain_2__setf(micgain2);
}
/**
********************************************************************************************
* @brief xc_pga_volr2_set
* @details
* @param volr2 (BIT0 - BIT3) £ºinput Two-stage gain ( PGA_VOLR2_GAIN_0_0DB - PGA_VOLR2_GAIN_0_0DB)
* @retval void
*********************************************************************************************
**/
void xc_pga_volr2_set(uint8_t volr2)
{
cpr_opa_ctrl_reg__volr_2__setf(volr2);
}
/**
********************************************************************************************
* @brief xc_pga_resadj_set
* @details
* @param resadj (BIT0 - BIT4) BIT2 -BIT4 :ELECTRICITY (PGA_ELECTRICITY_LEVEL0 - PGA_ELECTRICITY_LEVEL7)
BIT1:pga input (SINGLE or PGA_DIFFERENCE)
BIT0:unused
* @retval void
*********************************************************************************************
**/
void xc_pga_resadj_set(uint8_t resadj)
{
cpr_opa_ctrl_reg__resadj__setf(resadj);
}
/**
********************************************************************************************
* @brief xc_pga_cmp_ctrl_set
* @details
* @param cmp_ctrl : CMP_CTRL_VOLTAGE_LEVEL0 - CMP_CTRL_VOLTAGE_LEVEL3
* @retval void
*********************************************************************************************
**/
void xc_pga_cmp_ctrl_set(uint8_t cmp_ctrl)
{
cpr_opa_ctrl_reg__cmp_ctrl__setf(cmp_ctrl);
}
/**
********************************************************************************************
* @brief xc_pga_cmp_ibc_set
* @details
* @param cmp_ibc : CMP_IBC_ELECTRICITY_LEVEL0 - CMP_IBC_ELECTRICITY_LEVEL3
* @retval void
*********************************************************************************************
**/
void xc_pga_cmp_ibc_set(uint8_t cmp_ibc)
{
cpr_opa_ctrl_reg__cmp_ibc__setf(cmp_ibc);
}
/**
********************************************************************************************
* @brief xc_pga_temp_sensor_enable
* @details
* @param en_temp_sensor : TEMP_SENSOR_ENABLE / TEMP_SENSOR_DISABLE
* @retval void
*********************************************************************************************
**/
void xc_pga_temp_sensor_enable(uint8_t en_temp_sensor)
{
cpr_opa_ctrl_reg__en_temp_sensor__setf(en_temp_sensor);
}
/**
********************************************************************************************
* @brief xc_pga_volr_set
* @details unused
* @param volr
* @retval void
*********************************************************************************************
**/
void xc_pga_volr_set(uint8_t volr)
{
cpr_opa_ctrl_reg__volr__setf(volr);
}
/**
********************************************************************************************
* @brief xc_pga_pdbias_set
* @details
* @param pdbias :pdbias signal : 1:PD 0:EN
* @retval void
*********************************************************************************************
**/
void xc_pga_pdbias_set(uint8_t pdbias)
{
cpr_opa_ctrl_reg__pdbias__setf(pdbias);
}
/**
********************************************************************************************
* @brief xc_pga_opa_ctrl_set
* @details
* @param opa_ctrl (BIT0 - BIT2) BIT2:(pdopa signal : 1:pd 0:en)
BIT1:(pdopa signal input swap: 1:enable 0:disable)
BIT0:(pdopa CTRL ELECTRICITY: 1:min 0:max)
* @retval void
*********************************************************************************************
**/
void xc_pga_opa_ctrl_set(uint8_t opa_ctrl)
{
cpr_opa_ctrl_reg__opa_ctrl__setf(opa_ctrl);
}
/**
**********************************************************************************************
* @brief xc_pga_pdopa_set
* @details
* @param pdopa signal : 1:pd 0:en
* @retval void
**********************************************************************************************
*/
void xc_pga_pdopa_set(uint8_t pdopa)
{
cpr_opa_ctrl_reg__pdopa__setf(pdopa);
}
/**
**********************************************************************************************
* @brief xc_pga_micgain_set
* @details unused
* @param micgain
* @retval void
**********************************************************************************************
*/
void xc_pga_micgain_set(uint8_t micgain)
{
cpr_opa_ctrl_reg__micgain__setf(micgain);
}
@@ -0,0 +1,175 @@
/*!
* \file pga_adc.h
*
* \brief The head file of pga_adc.h
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC_DRV_PGA_H_
#define __XC_DRV_PGA_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
#define PGA_PDBIAS_EN 0
#define PGA_PDBIAS_PD 1
#define PGA_ELECTRICITY_LEVEL0 (0x07<<2)
#define PGA_ELECTRICITY_LEVEL1 (0x06<<2)
#define PGA_ELECTRICITY_LEVEL2 (0x05<<2)
#define PGA_ELECTRICITY_LEVEL3 (0x4<<2)
#define PGA_ELECTRICITY_LEVEL4 (0x3<<2)
#define PGA_ELECTRICITY_LEVEL5 (0x2<<2)
#define PGA_ELECTRICITY_LEVEL6 (0x1<<2)
#define PGA_ELECTRICITY_LEVEL7 (0x0<<2) /* max electricity*/
#define PGA_SINGLE (0x0<<1)
#define PGA_DIFFERENCE (0x1<<1)
#define CMP_CTRL_VOLTAGE_LEVEL0 (0x00) /* 0MV */
#define CMP_CTRL_VOLTAGE_LEVEL1 (0x01) /* 12MV */
#define CMP_CTRL_VOLTAGE_LEVEL2 (0x02) /* 23MV */
#define CMP_CTRL_VOLTAGE_LEVEL3 (0x03) /* max electricity 36MV*/
#define CMP_IBC_ELECTRICITY_LEVEL0 (0x03) /* 1.43ua */
#define CMP_IBC_ELECTRICITY_LEVEL1 (0x02) /* 2ua */
#define CMP_IBC_ELECTRICITY_LEVEL2 (0x01) /* 3.33ua */
#define CMP_IBC_ELECTRICITY_LEVEL3 (0x00) /* max electricity 10ua*/
#define TEMP_SENSOR_ENABLE 1
#define TEMP_SENSOR_DISABLE 0
#define PGA_OPA_CTRL_SIGNAL_PD (0x1<<2)
#define PGA_OPA_CTRL_SIGNAL_EN (0x0<<2)
#define PGA_OPA_CTRL_INPUT_SWAP_ENABLE (0x1<<1)
#define PGA_OPA_CTRL_INPUT_SWAP_DISABLE (0x0<<2)
#define PGA_OPA_CTRL_ELECTRICITY_MAX (0x0<<0)
#define PGA_OPA_CTRL_ELECTRICITY_MIN (0x1<<0)
#define PDOPA_SIGNAL_PD 1
#define PDOPA_SIGNAL_EN 0
typedef enum
{
PGA_MIC_GAIN2_DISABLE = 0,
PGA_MIC_GAIN2_ENABLE = 1,
} PGA_MIC_GAIN2TypeDef_t;
/* 0 - 22.3db */
typedef enum
{
PGA_VOLR2_GAIN_0_0DB = 0,
PGA_VOLR2_GAIN_1_6DB = 1,
PGA_VOLR2_GAIN_3_2DB = 2,
PGA_VOLR2_GAIN_4_8DB = 3,
PGA_VOLR2_GAIN_6_4DB = 4,
PGA_VOLR2_GAIN_8_0DB = 5,
PGA_VOLR2_GAIN_9_6DB = 6,
PGA_VOLR2_GAIN_11_2DB = 7,
PGA_VOLR2_GAIN_12_8DB = 8,
PGA_VOLR2_GAIN_14_4DB = 9,
PGA_VOLR2_GAIN_16_0DB = 10,
PGA_VOLR2_GAIN_17_6DB = 11,
PGA_VOLR2_GAIN_19_2DB = 12,
PGA_VOLR2_GAIN_20_8DB = 13,
PGA_VOLR2_GAIN_22_3DB = 14,
} PGA_VOLR2TypeDef_t;
/**
* @brief CPR_OPA_CTRL_REG register definition
* <pre>
* Bits Field Name Reset Value
* ----- ------------------ -----------
* 28 micgain2 0
* 27:24 volr2 0x0
* 23:19 resadj 0x0
* 18:17 cmp_ctrl 0x0
* 16:15 cmp_ibc 0x0
* 14 bg5v_ctrl 0
* 13 en_temp_sensor 0
* 12 pdbias 0
* 11:08 volr 0x0
* 07:05 opa_ctrl 0x0
* 04 pdopa 0
* 03:00 micgain 0x0
* </pre>
*/
typedef struct
{
PGA_MIC_GAIN2TypeDef_t gain2;
PGA_VOLR2TypeDef_t volr2;
uint8_t resadj;
uint8_t cmp_ctrl;
uint8_t cmp_ibc;
uint8_t bg5v_ctrl;
uint8_t en_temp_sensor;
uint8_t bias;
uint8_t volr;
uint8_t opa_ctrl;
uint8_t pdopa;
uint8_t micgain;
} PGA_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_pga_init(PGA_InitCfg_t *pga_cfg);
void xc_pga_micgain_2_set(uint8_t micgain2);
void xc_pga_volr2_set(uint8_t volr2);
void xc_pga_resadj_set(uint8_t resadj);
void xc_pga_cmp_ctrl_set(uint8_t cmp_ctrl);
void xc_pga_cmp_ibc_set(uint8_t cmp_ibc);
void xc_pga_temp_sensor_enable(uint8_t en_temp_sensor);
void xc_pga_volr_set(uint8_t volr);
void xc_pga_pdbias_set(uint8_t pdbias);
void xc_pga_opa_ctrl_set(uint8_t opa_ctrl);
void xc_pga_pdopa_set(uint8_t pdopa);
void xc_pga_micgain_set(uint8_t micgain);
#endif //__XC_DRV_PGA_H_
@@ -0,0 +1,435 @@
/*!
* \file xc_drv_pwm.c
*
* \brief Target xc pwm driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*------------------------------------------------------------------------------------
INCLUDE HEADE FILES
-------------------------------------------------------------------------------------*/
#include "xc_drv_pwm.h"
#include "xc_drv_gpio.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
STATE_UNINITIALIZED,
STATE_INITIALIZED,
} xincx_drv_state_t;
pwm_handler_callback pwm_n_callback[3] = {
pwm_capture_ch0_callback,
pwm_capture_ch1_callback,
pwm_capture_ch2_callback,
};
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static uint32_t pwm_clk_init_state = STATE_UNINITIALIZED;
static uint16_t pwm_freq_to_period(PWM_InitCfg_t *pwm_cfg, PWM_ClkDiv_TypeDef div_clk);
double period;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_pwm_init(uint8_t reg_idx, PWM_InitCfg_t *init_cfg)
{
if (pwm_clk_init_state == STATE_UNINITIALIZED) {
cpr_ctlapbclken_grctl__pwm_pclk_en__setf(ENABLE);
cpr_rstctl_ctlapb_sw__pwm_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_ctlapb_sw__pwm_rstn__setf(RSTCTL_DISABLE);
cpr_pwm_clk_ctl__pwm_clk_en__setf(ENABLE);
cpr_pwm_clk_ctl__pwm_clksel__setf(init_cfg->SrcClk);
cpr_pwm_clk_ctl__pwm_clk0_div__setf(init_cfg->DivClk);
cpr_pwm_clk_ctl__pwm_clk1_div__setf(init_cfg->DivClk);
pwm_clk_init_state = STATE_INITIALIZED;
}
pwm_pin_set(reg_idx, init_cfg);
pwm_en__en__setf(reg_idx, DISABLE);
pwm_en__en_sel__setf(reg_idx, init_cfg->SrcEnable);
xc_pwm_dutycycle_set(reg_idx, init_cfg->DutyCycleAcc, init_cfg->DutyCycle);
pwm_period__period__setf(reg_idx, pwm_freq_to_period(init_cfg, PWM_CLK_DIV0));
pwm_compen__pwmcompen__setf(reg_idx, init_cfg->InvertEnable);
pwm_comptime__comptime__setf(reg_idx, init_cfg->InvertDelay);
}
void xc_pwm_start(uint8_t reg_idx) { pwm_en__en__setf(reg_idx, PWM_EN_ENABLE); }
void xc_pwm_stop(uint8_t reg_idx) { pwm_en__en__setf(reg_idx, PWM_EN_DISABLE); }
void pwm_src_enable_set(uint8_t reg_idx, uint8_t src_enable) { pwm_en__en_sel__setf(reg_idx, src_enable); }
void xc_pwm_start_all(void) { pwm_en__pwm_en_all__setf(PWM0_IDX, PWM_EN_ALL_ENABLE); }
void xc_pwm_stop_all(void) { pwm_en__pwm_en_all__setf(PWM0_IDX, PWM_EN_ALL_DISABLE); }
void pwm_pin_set(uint8_t reg_idx, PWM_InitCfg_t *pwm_cfg)
{
GPIO_InitCfg_t gpio_cfg;
if(pwm_cfg->OutputPin==GPIO_11||pwm_cfg->OutputPin==GPIO_12||pwm_cfg->OutputPin==GPIO_13){
gpio_cfg.Mux = GPIO_Mux1;
}else
{
gpio_cfg.Mux = GPIO_Mux0;
}
gpio_cfg.Dir = GPIO_DIR_OUTPUT;
gpio_cfg.Pull = GPIO_PULLDOWN;
gpio_cfg.Int = NOT_INT;
gpio_cfg.Pin = pwm_cfg->OutputPin;
if (reg_idx == PWM0_IDX || reg_idx == PWM1_IDX) {
gpio_cfg.FunSel = (reg_idx == PWM0_IDX) ? PWM0 : PWM1;
xc_gpio_init(&gpio_cfg);
if (pwm_cfg->InvertEnable) {
gpio_cfg.FunSel = (reg_idx == PWM0_IDX) ? PWM0_INV : PWM1_INV;
gpio_cfg.Pin = pwm_cfg->OutputInvertPin;
xc_gpio_init(&gpio_cfg);
}
} else if (reg_idx == PWM2_IDX) {
gpio_cfg.Mux = GPIO_Mux3;
if (pwm_cfg->OutputPin == GPIO_12) {
xc_gpio_init(&gpio_cfg);
}
} else if (reg_idx == PWM3_IDX) {
gpio_cfg.Mux = GPIO_Mux3;
if (pwm_cfg->OutputPin == GPIO_13) {
xc_gpio_init(&gpio_cfg);
}
} else if (reg_idx == PWM4_IDX) {
gpio_cfg.Mux = GPIO_Mux2;
if (pwm_cfg->OutputPin == GPIO_0) {
xc_gpio_init(&gpio_cfg);
}
} else if (reg_idx == PWM5_IDX) {
gpio_cfg.Mux = GPIO_Mux2;
if (pwm_cfg->OutputPin == GPIO_1) {
xc_gpio_init(&gpio_cfg);
}
}
}
static uint16_t pwm_freq_to_period(PWM_InitCfg_t *pwm_cfg, PWM_ClkDiv_TypeDef div_clk)
{
uint32_t pwm_clk;
switch (pwm_cfg->SrcClk) {
case PWM_CLK_SRC_32M_DIV: {
pwm_clk = xc_clock_hfclk_in_get() / PWM_CLK_DIV_CAL(div_clk);
} break;
case PWM_CLK_SRC_32K_DIV: {
pwm_clk = xc_clock_lfclk_in_get() / PWM_CLK_DIV_CAL(div_clk);
} break;
case PWM_CLK_SRC_32K: {
pwm_clk = CLOCK_LFCLK_IN_32K;
} break;
default:
break;
}
uint32_t freq_max = PWM_FREQ_MAX_CAL(pwm_clk, pwm_cfg->DutyCycleAcc);
uint32_t freq = PWM_FREQ_CAL(pwm_clk, pwm_cfg->DutyCycleAcc, pwm_cfg->Period);
if (freq > freq_max) {
DEBUG("%s,line=%d,set freq=%d,The maximum configurable frequency %d hz "
"has been exceeded.\n",
__func__, __LINE__, freq, freq_max);
} else {
DEBUG("%s,line=%d,set freq=%d,maximum configurable frequency %d hz\n", __func__, __LINE__, freq, freq_max);
}
return pwm_cfg->Period;
}
void xc_pwm_dutycycle_set(uint8_t reg_idx, uint32_t dutycycle_acc, uint32_t dutycycle)
{
pwm_en__mode__setf(reg_idx, PWM_EN_MODE_EDGE_ALIGNED);
pwm_ocpy__ocpy_ratio_config__setf(reg_idx, (dutycycle_acc - 1));
pwm_ocpy__ocpy_ratio__setf(reg_idx, dutycycle_acc - dutycycle);
pwm_up__update__setf(reg_idx, PWM_UP_UPDATE_ENABLE);
}
void xc_pwm_lowpower_enable(uint8_t reg_idx) { pwm_en__sleep_en__setf(reg_idx, PWM_EN_SLEEP_EN_ENABLE); }
void xc_pwm_lowpower_disable(uint8_t reg_idx) { pwm_en__sleep_en__setf(reg_idx, PWM_EN_SLEEP_EN_DISABLE); }
void xc_pwm_lowpower_countdirection_set(uint8_t reg_idx, uint32_t direction)
{
pwm_en__sleep_incr__setf(reg_idx, direction);
}
void xc_pwm_brake_enable(uint8_t reg_idx)
{
uint32_t val;
val = pwm_break_ctl__pwm_brk_enable__getf(PWM0_IDX);
if (reg_idx == PWM0_IDX || reg_idx == PWM1_IDX) {
val &= ~(PWM_BRK0_ENABLE_ENABLE);
val |= (PWM_BRK0_ENABLE_ENABLE);
} else if (reg_idx == PWM2_IDX || reg_idx == PWM3_IDX) {
val &= ~(PWM_BRK1_ENABLE_ENABLE);
val |= (PWM_BRK1_ENABLE_ENABLE);
} else if (reg_idx == PWM4_IDX || reg_idx == PWM5_IDX) {
val &= ~(PWM_BRK2_ENABLE_ENABLE);
val |= (PWM_BRK2_ENABLE_ENABLE);
}
pwm_break_ctl__pwm_brk_enable__setf(PWM0_IDX, val);
}
void xc_pwm_brake_disable(uint8_t reg_idx)
{
uint32_t val;
val = pwm_break_ctl__pwm_brk_enable__getf(PWM0_IDX);
if (reg_idx == PWM0_IDX || reg_idx == PWM1_IDX) {
val &= ~(PWM_BRK0_ENABLE_ENABLE);
} else if (reg_idx == PWM2_IDX || reg_idx == PWM3_IDX) {
val &= ~(PWM_BRK1_ENABLE_ENABLE);
} else if (reg_idx == PWM4_IDX || reg_idx == PWM5_IDX) {
val &= ~(PWM_BRK2_ENABLE_ENABLE);
}
pwm_break_ctl__pwm_brk_enable__setf(PWM0_IDX, val);
}
uint8_t xc_pwm_brake_signal_valid_get(void) { return pwm_break_ctl__pwm_brk_sync__getf(PWM0_IDX); }
void xc_pwm_brake_signal_mask_set(uint32_t mask) { pwm_break_ctl__pwm_brk_mask__setf(PWM0_IDX, mask); }
void xc_pwm_brake_signal_trigger_level_set(uint32_t level) { pwm_break_ctl__pwm_brk_inv__setf(PWM0_IDX, level); }
void xc_pwm_brake_recovery_mode_set(uint32_t mode) { pwm_break_ctl__brk_mode__setf(PWM0_IDX, mode); }
uint8_t xc_pwm_brake_recovery_mode_get(void) { return (pwm_break_ctl__brk_mode__getf(PWM0_IDX)); }
void xc_pwm_brake_debounce_set(uint32_t debounce, uint32_t step)
{
pwm_break_ctl__brk_dbc_en__setf(PWM0_IDX, debounce);
pwm_break_ctl__brk_dbc_step__setf(PWM0_IDX, step);
}
void xc_pwm_brake_clear() { pwm_break_ctl__clear__setf(PWM0_IDX, PWM_BRK_BRK_CLEAR_EXIT); }
void xc_pwm_capture_enable(uint8_t ch) { cap_tim_ctl__capture_enable__setf(ch, PWM_CAPTURE_ENABLE); }
void xc_pwm_capture_disable(uint8_t ch) { cap_tim_ctl__capture_enable__setf(ch, PWM_CAPTURE_DISABLE); }
void xc_pwm_capture_enable_it(uint8_t ch)
{
if (ch == 0) {
pwm_cap_tim_int_en__capture_upd_0_en__setf(ENABLE);
} else if (ch == 1) {
pwm_cap_tim_int_en__capture_upd_1_en__setf(ENABLE);
} else if (ch == 2) {
pwm_cap_tim_int_en__capture_upd_2_en__setf(ENABLE);
}
}
void xc_pwm_capture_disable_it(uint8_t ch)
{
if (ch == PWM_IC_CH0) {
pwm_cap_tim_int_en__capture_upd_0_en__setf(DISABLE);
} else if (ch == PWM_IC_CH1) {
pwm_cap_tim_int_en__capture_upd_1_en__setf(DISABLE);
} else if (ch == PWM_IC_CH2) {
pwm_cap_tim_int_en__capture_upd_2_en__setf(DISABLE);
}
}
void xc_pwm_capture_signal_set(uint8_t ch, uint32_t signal) { cap_tim_ctl__capture_sig_sel__setf(ch, signal); }
void xc_pwm_capture_debounce_enable(uint8_t ch, uint32_t step)
{
cap_tim_ctl__dbc_en__setf(ch, PWM_CAPTURE_DBC_ENABLE);
cap_tim_ctl__dbc_step__setf(ch, step);
}
void xc_pwm_capture_debounce_disable(uint8_t ch, uint32_t step)
{
cap_tim_ctl__dbc_en__setf(ch, PWM_CAPTURE_DBC_DISABLE);
cap_tim_ctl__dbc_step__setf(ch, step);
}
void xc_pwm_capture_edge_set(uint8_t ch, uint32_t edge) { cap_tim_ctl__capture_mode__setf(ch, edge); }
void xc_pwm_capture_psc_set(uint8_t ch, uint32_t psc) { cap_tim_ctl__capture_psc__setf(ch, psc); }
void xc_pwm_capture_counter_enable(uint8_t ch)
{
cap_tim_ctl__common_cnt_enable__setf(ch, PWM_CAPTURE_COMMON_CNT_ENABLE);
}
void xc_pwm_capture_counter_disable(uint8_t ch)
{
cap_tim_ctl__common_cnt_enable__setf(ch, PWM_CAPTURE_COMMON_CNT_DISABLE);
}
uint16_t xc_pwm_capture_val_get(uint8_t ch) { return cap_tim_val__capture_value__getf(ch); }
/*
*-----------------------------------------------------------------------------------------------
* PWM Timer
*-----------------------------------------------------------------------------------------------
*/
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_pwm_timer_init(uint8_t reg_idx, PWM_Timer_InitCfg_t *init_cfg)
{
if (reg_idx > PWM_TIMER5_IDX)
return;
if (pwm_clk_init_state == STATE_UNINITIALIZED) {
cpr_ctlapbclken_grctl__pwm_pclk_en__setf(ENABLE);
cpr_rstctl_ctlapb_sw__pwm_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_ctlapb_sw__pwm_rstn__setf(RSTCTL_DISABLE);
cpr_pwm_clk_ctl__pwm_clk_en__setf(ENABLE);
cpr_pwm_clk_ctl__pwm_clksel__setf(init_cfg->src_clk);
cpr_pwm_clk_ctl__pwm_clk0_div__setf(init_cfg->clk_div);
cpr_pwm_clk_ctl__pwm_clk1_div__setf(init_cfg->clk_div);
pwm_clk_init_state = STATE_INITIALIZED;
}
uint32_t ctl_reg = (init_cfg->timer_mode << TIMER_MODE_POS) | (init_cfg->timer_int_mask_en << TIMER_INT_MASK_POS) |
(init_cfg->timer_pwm_en << TIMER_PWM_POS) |
(init_cfg->timer_0to100_pwm_en << TIMER_ON10OPWM_EN_POS);
pwm_timer_controlreg_set(reg_idx, ctl_reg);
}
void xc_pwm_timer_deinit(uint8_t reg_idx)
{
pwm_clk_init_state = STATE_UNINITIALIZED;
cpr_ctlapbclken_grctl__pwm_pclk_en__setf(DISABLE);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_pwm_timer_set_freq(uint8_t reg_idx, uint32_t freq) { period = xc_clock_hfclk_in_get() / 2 / freq; }
void xc_pwm_timer_set_dutycycle(uint8_t reg_idx, double dutycycle)
{
uint16_t high_cnt = ((uint32_t)(period * dutycycle) / 100);
uint16_t low_cnt = (uint32_t)(period - high_cnt);
pwm_timer_loadcount__timer_lc__setf(reg_idx, low_cnt);
pwm_timer_loadcount2__timer_lc2__setf(reg_idx, high_cnt);
}
void xc_pwm_timer_set_high_cnt(uint8_t reg_idx, uint16_t high_cnt)
{
pwm_timer_loadcount2__timer_lc2__setf(reg_idx, high_cnt);
}
void xc_pwm_timer_set_low_cnt(uint8_t reg_idx, uint16_t low_cnt)
{
pwm_timer_loadcount__timer_lc__setf(reg_idx, low_cnt);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_pwm_timer_start(uint8_t reg_idx) { pwm_timer_controlreg__timer_en__setf(reg_idx, ENABLE); }
void xc_pwm_timer_stop(uint8_t reg_idx) { pwm_timer_controlreg__timer_en__setf(reg_idx, DISABLE); }
/*-----------------------------------------------------------------------------------------------*/
void PWM_Handler(void)
{
uint32_t cap_tim_int;
cap_tim_int = pwm_cap_tim_int_get();
pwm_cap_tim_int_set(cap_tim_int); // clear inter
if ((cap_tim_int & PWM_CAPTURE_UPD0_EN_ENABLE) == PWM_CAPTURE_UPD0_EN_ENABLE) {
pwm_capture_ch0_callback(NULL);
}
if ((cap_tim_int & PWM_CAPTURE_UPD1_EN_ENABLE) == PWM_CAPTURE_UPD1_EN_ENABLE) {
pwm_capture_ch1_callback(NULL);
}
if ((cap_tim_int & PWM_CAPTURE_UPD2_EN_ENABLE) == PWM_CAPTURE_UPD2_EN_ENABLE) {
pwm_capture_ch2_callback(NULL);
}
}
__WEAK uint8_t pwm_capture_ch0_callback(void *context) { return 0; }
__WEAK uint8_t pwm_capture_ch1_callback(void *context) { return 0; }
__WEAK uint8_t pwm_capture_ch2_callback(void *context) { return 0; }
@@ -0,0 +1,319 @@
/*!
* \file xc_drv_pwm.h
*
* \brief The header of xc_drv_pwm.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_PWM_H_
#define _XC_DRV_PWM_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define PWM_CLK_DIV_CAL(div) (2 * (div + 1))
#define PWM_FREQ_MAX_CAL(pwm_clk, dutycycle_acc) \
(pwm_clk / (dutycycle_acc * (0 + 1)) / 2)
#define PWM_FREQ_CAL(pwm_clk, dutycycle_acc, period) \
(pwm_clk / (dutycycle_acc * (period + 1)) / 2)
#define PWM_UP_UPDATE_ENABLE (1UL)
#define PWM_UP_UPDATE_DISABLE (0UL)
#define PWM_EN_ENABLE (0x01UL)
#define PWM_EN_DISABLE (0x00UL)
#define PWM_EN_ALL_ENABLE (0x01UL)
#define PWM_EN_ALL_DISABLE (0x00UL)
#define PWM_EN_SLEEP_EN_ENABLE (0x01UL)
#define PWM_EN_SLEEP_EN_DISABLE (0x00UL)
#define PWM_EN_MODE_EDGE_ALIGNED (0x03UL)
#define PWM_EN_MODE_CENTER_ALIGNED (0x02UL)
#define PWM_COMP_TIME_PWMCOMPTIME_Pos (0x00UL)
#define PWM_COMP_TIME_PWMCOMPTIME_Msk (0xFFUL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_1CLK (0x00UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_2CLK (0x01UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_3CLK (0x02UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_4CLK (0x03UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_5CLK (0x04UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_6CLK (0x05UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_7CLK (0x06UL)
#define PWM_COMP_TIME_PWMCOMPTIME_VAL_8CLK (0x07UL)
#define PWM_BRK_BRK_CLEAR_EXIT (0x01UL)
#define PWM_BRK_DBC_EN_ENABLE (0x01UL)
#define PWM_BRK_DBC_EN_DISABLE (0x00UL)
#define PWM_BRK_DBC_STEP1 (0x01UL)
#define PWM_BRK_DBC_STEP2 (0x02UL)
#define PWM_BRK_DBC_STEP3 (0x03UL)
#define PWM_BRK_DBC_STEP4 (0x04UL)
#define PWM_BRK_DBC_STEP5 (0x05UL)
#define PWM_BRK_DBC_STEP6 (0x06UL)
#define PWM_BRK_DBC_STEP7 (0x07UL)
#define PWM_BRK_DBC_STEP8 (0x08UL)
#define PWM_BRK_DBC_STEP9 (0x09UL)
#define PWM_BRK_DBC_STEP10 (0x0AUL)
#define PWM_BRK0_INV_ENABLE (0x01UL)
#define PWM_BRK0_INV_DISABLE (0x00UL)
#define PWM_BRK1_INV_ENABLE (0x02UL)
#define PWM_BRK1_INV_DISABLE (0x00UL)
#define PWM_BRK2_INV_ENABLE (0x04UL)
#define PWM_BRK2_INV_DISABLE (0x00UL)
#define PWM_BRK0_MASK_ENABLE (0x01UL)
#define PWM_BRK0_MASK_DISABLE (0x00UL)
#define PWM_BRK1_MASK_ENABLE (0x02UL)
#define PWM_BRK1_MASK_DISABLE (0x00UL)
#define PWM_BRK2_MASK_ENABLE (0x04UL)
#define PWM_BRK2_MASK_DISABLE (0x00UL)
#define PWM_BRK0_ENABLE_ENABLE (0x01UL)
#define PWM_BRK0_ENABLE_DISABLE (0x00UL)
#define PWM_BRK1_ENABLE_ENABLE (0x02UL)
#define PWM_BRK1_ENABLE_DISABLE (0x00UL)
#define PWM_BRK2_ENABLE_ENABLE (0x04UL)
#define PWM_BRK2_ENABLE_DISABLE (0x00UL)
#define PWM_CAPTURE_UPD0_EN_ENABLE (0x01UL)
#define PWM_CAPTURE_UPD1_EN_ENABLE (0x02UL)
#define PWM_CAPTURE_UPD2_EN_ENABLE (0x04UL)
#define PWM_CAPTURE_PSC_1 (0x00UL)
#define PWM_CAPTURE_PSC_2 (0x01UL)
#define PWM_CAPTURE_PSC_3 (0x02UL)
#define PWM_CAPTURE_MODE_RISE (0x00UL)
#define PWM_CAPTURE_MODE_FALL (0x01UL)
#define PWM_CAPTURE_MODE_BOTH (0x02UL)
#define PWM_CAPTURE_DBC_STEP0 (0x00UL)
#define PWM_CAPTURE_DBC_STEP1 (0x01UL)
#define PWM_CAPTURE_DBC_STEP2 (0x02UL)
#define PWM_CAPTURE_DBC_STEP3 (0x03UL)
#define PWM_CAPTURE_DBC_STEP4 (0x04UL)
#define PWM_CAPTURE_DBC_STEP5 (0x05UL)
#define PWM_CAPTURE_DBC_STEP6 (0x06UL)
#define PWM_CAPTURE_DBC_STEP7 (0x07UL)
#define PWM_CAPTURE_DBC_STEP8 (0x08UL)
#define PWM_CAPTURE_DBC_STEP9 (0x09UL)
#define PWM_CAPTURE_DBC_STEP10 (0x0AUL)
#define PWM_CAPTURE_DBC_STEP11 (0x0BUL)
#define PWM_CAPTURE_DBC_STEP12 (0x0CUL)
#define PWM_CAPTURE_SIG_SEL_PWM_CAPTURE0 (0x00UL)
#define PWM_CAPTURE_SIG_SEL_PWM_CAPTURE1 (0x01UL)
#define PWM_CAPTURE_SIG_SEL_PWM_CAPTURE2 (0x02UL)
#define PWM_CAPTURE_SIG_SEL_PWM_BRK0 (0x03UL)
#define PWM_CAPTURE_SIG_SEL_PWM_BRK1 (0x04UL)
#define PWM_CAPTURE_SIG_SEL_PWM_BRK2 (0x05UL)
#define PWM_CAPTURE_CLK_DIV_VAL_0 (0x00UL)
#define PWM_CAPTURE_CLK_DIV_VAL_2 (0x01UL)
#define PWM_CAPTURE_CLK_DIV_VAL_3 (0x02UL)
#define PWM_CAPTURE_CLK_DIV_VAL_4 (0x03UL)
#define PWM_CAPTURE_CLK_DIV_VAL_5 (0x04UL)
#define PWM_CAPTURE_CLK_DIV_VAL_6 (0x05UL)
#define PWM_CAPTURE_CLK_DIV_VAL_7 (0x06UL)
#define PWM_CAPTURE_CLK_DIV_VAL_8 (0x07UL)
#define PWM_CAPTURE_CLK_DIV_VAL_9 (0x08UL)
#define PWM_CAPTURE_CLK_DIV_VAL_10 (0x09UL)
#define PWM_CAPTURE_CLK_DIV_VAL_11 (0x0AUL)
#define PWM_CAPTURE_CLK_DIV_VAL_12 (0x0BUL)
#define PWM_CAPTURE_CLK_DIV_VAL_13 (0x0CUL)
#define PWM_CAPTURE_ENABLE (0x01UL)
#define PWM_CAPTURE_DISABLE (0x00UL)
#define PWM_CAPTURE_DBC_ENABLE (0x01UL)
#define PWM_CAPTURE_DBC_DISABLE (0x00UL)
#define PWM_CAPTURE_COMMON_CNT_ENABLE (0x01UL)
#define PWM_CAPTURE_COMMON_CNT_DISABLE (0x00UL)
#define PWM_CAPTURE_UPD_EN_ENABLE (0x01UL)
#define PWM_CAPTURE_UPD_EN_DISABLE (0x00UL)
#define PWM_SIGNAL_CAPTURE0_GPIO3 GPIO_3
#define PWM_SIGNAL_CAPTURE1_GPIO8 GPIO_8
#define PWM_SIGNAL_CAPTURE2_GPIO9 GPIO_9
#define PWM_SIGNAL_BRK0_GPIO4 GPIO_4
#define PWM_SIGNAL_BRK1_GPIO5 GPIO_5
#define PWM_SIGNAL_BRK2_GPIO6 GPIO_6
#define PWM_IC_CH0 0
#define PWM_IC_CH1 1
#define PWM_IC_CH2 2
#define PWM_BRK_SYNC_VALID 1
#define PWM_BRK_SYNC_INVALID 0
#define PWM_BRK0_HIGH_LEVEL PWM_BRK0_INV_DISABLE
#define PWM_BRK0_LOW_LEVEL PWM_BRK0_INV_ENABLE
#define PWM_BRK1_HIGH_LEVEL PWM_BRK1_INV_DISABLE
#define PWM_BRK1_LOW_LEVEL PWM_BRK1_INV_ENABLE
#define PWM_BRK2_HIGH_LEVEL PWM_BRK2_INV_DISABLE
#define PWM_BRK2_LOW_LEVEL PWM_BRK2_INV_ENABLE
#define PWM_ICSIG_CAPTURE0 PWM_CAPTURE_SIG_SEL_PWM_CAPTURE0
#define PWM_ICSIG_CAPTURE1 PWM_CAPTURE_SIG_SEL_PWM_CAPTURE1
#define PWM_ICSIG_CAPTURE2 PWM_CAPTURE_SIG_SEL_PWM_CAPTURE2
#define PWM_ALL_ENABLE PWM_EN_ALL_ENABLE
#define PWM_ALL_DISABLE PWM_EN_ALL_DISABLE
#define PWM_SLEEP_COUNT_DIRECTION_UP (0x01UL)
#define PWM_SLEEP_COUNT_DIRECTION_DOWN (0x00UL)
#define PWM_SLEEP_ENABLE PWM_SLEEP_EN_ENABLE
#define PWM_SLEEP_DISABLE PWM_SLEEP_EN_DISABLE
#define PWM_EN_SEL_SELF (0x00UL)
#define PWM_EN_SEL_ALL (0x01UL)
#define PWM_BRK_MODE_HARDWARE (0x00UL)
#define PWM_BRK_MODE_SOFTWARE (0x01UL)
#define PWM_TIMER_MODE_USER_DEFINED (0x01UL)
#define PWM_TIMER_MODE_FREE_RUNNING (0x00UL)
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
PWM_CLK_SRC_32M_DIV = 0, /*PWM CLK SRC 32MHz div.*/
PWM_CLK_SRC_32K_DIV = 1, /*PWM CLK SRC 32kHz div.*/
PWM_CLK_SRC_32K = 4, /*PWM CLK SRC 32kHz.*/
} PWM_ClkSrc_TypeDef;
typedef enum
{
PWM_CLK_DIV0 = 0UL, /*PWM CLK 16 MHz or 16KHz*/
PWM_CLK_DIV1 = 1UL, /*PWM CLK 8 MHz or 8KHz*/
PWM_CLK_DIV3 = 3UL, /*PWM CLK 4 MHz or 4KHz.*/
PWM_CLK_DIV7 = 7UL, /*PWM CLK 2 MHz or 2KHz.*/
PWM_CLK_DIV15 = 15UL, /*PWM CLK 1 MHz or 1KHz.*/
PWM_CLK_DIV31 = 31UL, /*PWM CLK 500 kHz or 500Hz.*/
PWM_CLK_DIV63 = 63UL, /*PWM CLK 250 kHz or 250Hz.*/
PWM_CLK_DIV127 = 127UL, /*PWM CLK 125 kHz or 125Hz.*/
PWM_CLK_DIV255 = 255UL, /*PWM CLK 62500 Hz or 62.5Hz.*/
} PWM_ClkDiv_TypeDef;
typedef enum pwm_timer_number
{
PWM_NO_TIMER = 0x00,
PWM_TIMER_1 = 0x01,
PWM_TIMER_2 = 0x02,
PWM_TIMER_3 = 0x04,
PWM_TIMER_4 = 0x08,
PWM_TIMER_5 = 0x10,
PWM_TIMER_6 = 0x20,
PWM_ALL_TIMER = 0x3F,
} ePWM_Timer_Num;
typedef struct
{
PWM_ClkSrc_TypeDef SrcClk;
uint8_t Mode;
uint32_t DutyCycleAcc;
uint32_t DutyCycle;
uint8_t SrcEnable;
uint8_t Period;
uint8_t DivClk;
uint8_t OutputPin;
uint8_t OutputInvertPin;
uint8_t InvertDelay;
bool InvertEnable;
} PWM_InitCfg_t;
typedef struct
{
PWM_ClkSrc_TypeDef src_clk;
PWM_ClkDiv_TypeDef clk_div;
uint8_t timer_0to100_pwm_en;
uint8_t timer_pwm_en;
uint8_t timer_int_mask_en;
uint8_t timer_mode; /* 0x0 FREE_RUNNING; 0x1 USER_DEFINED */
} PWM_Timer_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
typedef uint8_t (*pwm_handler_callback)(void *context);
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_pwm_init(uint8_t reg_idx, PWM_InitCfg_t *pwm_cfg);
void xc_pwm_start(uint8_t reg_idx);
void xc_pwm_stop(uint8_t reg_idx);
void xc_pwm_start_all(void);
void xc_pwm_stop_all(void);
void pwm_pin_set(uint8_t reg_idx, PWM_InitCfg_t *pwm_cfg);
void xc_pwm_dutycycle_set(uint8_t reg_idx,uint32_t dutycycle_acc, uint32_t dutycycle);
void xc_pwm_lowpower_enable(uint8_t reg_idx);
void xc_pwm_lowpower_disable(uint8_t reg_idx);
void xc_pwm_lowpower_countdirection_set(uint8_t reg_idx, uint32_t direction);
void xc_pwm_brake_enable(uint8_t reg_idx);
void xc_pwm_brake_disable(uint8_t reg_idx);
uint8_t xc_pwm_brake_signal_valid_get(void);
void xc_pwm_brake_signal_mask_set(uint32_t mask);
void xc_pwm_brake_signal_trigger_level_set(uint32_t invert);
void xc_pwm_brake_recovery_mode_set(uint32_t mode);
uint8_t xc_pwm_brake_recovery_mode_get(void);
void xc_pwm_brake_debounce_set(uint32_t debounce, uint32_t step);
void xc_pwm_brake_clear(void);
void xc_pwm_capture_enable(uint8_t ch);
void xc_pwm_capture_disable(uint8_t ch);
void xc_pwm_capture_enable_it(uint8_t ch);
void xc_pwm_capture_disable_it(uint8_t ch);
void xc_pwm_capture_signal_set(uint8_t ch, uint32_t signal);
void xc_pwm_capture_debounce_enable(uint8_t ch, uint32_t step);
void xc_pwm_capture_debounce_disable(uint8_t ch, uint32_t step);
void xc_pwm_capture_edge_set(uint8_t ch, uint32_t edge);
void xc_pwm_capture_psc_set(uint8_t ch, uint32_t psc);
void xc_pwm_capture_counter_enable(uint8_t ch);
void xc_pwm_capture_counter_disable(uint8_t ch);
uint16_t xc_pwm_capture_val_get(uint8_t ch);
void xc_pwm_timer_init(uint8_t reg_idx, PWM_Timer_InitCfg_t *init_cfg);
void xc_pwm_timer_deinit(uint8_t reg_idx);
void xc_pwm_timer_set_freq(uint8_t reg_idx, uint32_t freq);
void xc_pwm_timer_set_dutycycle(uint8_t reg_idx, double dutycycle);
void xc_pwm_timer_start(uint8_t reg_idx);
void xc_pwm_timer_stop(uint8_t reg_idx);
void xc_pwm_timer_set_high_cnt(uint8_t reg_idx, uint16_t high_cnt);
void xc_pwm_timer_set_low_cnt(uint8_t reg_idx, uint16_t high_cnt);
uint8_t pwm_capture_ch0_callback(void *context);
uint8_t pwm_capture_ch1_callback(void *context);
uint8_t pwm_capture_ch2_callback(void *context);
#endif // _XC_DRV_PWM_H_
@@ -0,0 +1,905 @@
/*!
* \file xc_drv_pwr.c
*
* \brief Target xc6xxx hal power implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_pwr.h"
#if (USE_ROM_FLASH)
#include "xc6xxx_fmc_spi.h"
#endif // (USE_ROM_FLASH)
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_pwr_vol_set(void)
{
uint32_t hf_clk = xc_clock_hfclk_in_get();
switch (hf_clk) {
case CLOCK_HFCLK_IN_16M: {
cprao_aon_bbldo_adj_set(0x3C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x3C; // 0x4a;
// XC_CPR_AO->LPOLDO_ADJ = 4; // 1;
} break;
case CLOCK_HFCLK_IN_32M: {
// if use usb driver, bbldo is at least 0x4E.
// cprao_aon_bbldo_adj_set(0x4E);
cprao_aon_bbldo_adj_set(0x2c);
cprao_aon_lpoldo_adj_set(7);
// XC_CPR_AO->BBLDO_ADJ = 0x9E; // 0x2C;
// XC_CPR_AO->LPOLDO_ADJ = 7;
} break;
case CLOCK_HFCLK_IN_48M: {
cprao_aon_bbldo_adj_set(0x3C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x9C;
// XC_CPR_AO->LPOLDO_ADJ = 4;
} break;
case CLOCK_HFCLK_IN_64M: {
cprao_aon_bbldo_adj_set(0x9C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x9C;
// XC_CPR_AO->LPOLDO_ADJ = 4;
} break;
case CLOCK_HFCLK_IN_96M: {
cprao_aon_bbldo_adj_set(0x9C);
cprao_aon_lpoldo_adj_set(7);
// XC_CPR_AO->BBLDO_ADJ = 0x9e;
// XC_CPR_AO->LPOLDO_ADJ = 7;
} break;
default: {
cprao_aon_bbldo_adj_set(0x9C);
cprao_aon_lpoldo_adj_set(4);
// XC_CPR_AO->BBLDO_ADJ = 0x9C;
// XC_CPR_AO->LPOLDO_ADJ = 4;
} break;
}
}
/**
**************************************************************************************
* @brief xc_adc_powerdown
* @details adc power down
* @param void
* @retval void
***************************************************************************************
*/
void xc_adc_powerdown(void)
{
adc_rf_ctl__pd_adc__setf(ADC_RF_CTL_PD_GADC_POWERDOWN);
}
/**
**************************************************************************************
* @brief xc_adc_wakeup
* @details adc wakeup
* @param void
* @retval void
***************************************************************************************
*/
void xc_adc_wakeup(void)
{
adc_rf_ctl__pd_adc__setf(ADC_RF_CTL_PD_GADC_WAKWUP);
}
__RAM_CODE void xc_pwr_ao_timer_pclk32k_set(void)
{
uint32_t val;
cprao_aon_reg1__timer_ao_sleep_clksw__setf(1);
val = cprao_aon_reg1__timer_ao_sleep_clksw__getf();
while ((val & 0x01) != 1) {
__NOP();
__NOP();
val = cprao_aon_reg1__timer_ao_sleep_clksw__getf();
}
}
void xc_pwr_ao_timer_pclk32m_Set()
{
cprao_aon_reg1__timer_ao_sleep_clksw__setf(0);
}
void xc_pwr_sleep_init(PWR_InitCfg_t *pwr_cfg)
{
cprao_aon_sys_time_set((RST_READY_TIME << 12) | (OSC32_STABLE_TIME));
if (pwr_cfg->pwr_sleep_mode == LIGHT_SLEEP_MODE) {
xc_pwr_pd_lightsleep_set();
xc_pwr_sleepsrc_mask_set(0x1e001e);
} else if (pwr_cfg->pwr_sleep_mode == DEEP_SLEEP_MODE) {
xc_pwr_pd_deepsleep_set();
delay_us(100);
xc_pwr_sleepsrc_mask_set(0x1e001e);
}
xc_pwr_osc_off();
xc_pwr_wake_it_set(pwr_cfg->pwr_wake_it_src);
}
// __RAM_CODE void xc_sleep_init()
// {
// xc_adc_powerdown();
// xc_pwr_usb_off();
// xc_pwr_rc16m_off();
// xc_pwr_rc32k_calib_off();
// // xc_pwr_rom_off();
// xc_pwr_opa_tempsensor_off();
// xc_pwr_opa_volr_off();
// xc_pwr_revddldo_off();
// xc_pwr_dcdc_close();
// xc_pwr_rfdigital_off();
// xc_pwr_modem_off();
// xc_pwr_pd_lightsleep_set();
// }
__RAM_CODE void xc_pwr_ble_sleep_enter(void)
{
#if (USE_XIP == 1)
#if (USE_ROM_FLASH)
FMC_SPI_Flash_PowerDown();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_power_down();
#endif // USE_ROM_FLASH
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close fmc
for (int i = 0; i < 10; i++) {
__NOP();
__NOP();
__NOP();
}
#endif // USE_XIP
__disable_irq();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__WFI();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#if (USE_XIP == 1)
cpr_fmc_ctl_set(0x3503); // open FMC
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
xc_pwr_rom_on();
#if (USE_ROM_FLASH)
FMC_SPI_Flash_WakeUp();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_wake_up();
#endif // (USE_ROM_FLASH)
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#endif
xc_pwr_ao_timer_pclk32m_Set();
// xc_pwr_rom_on();
__enable_irq();
#ifdef USED_DCDC
xc_pwr_dcdc_open();
#endif
xc_pwr_modem_on();
xc_pwr_rfdigital_on();
xc_adc_wakeup();
}
__RAM_CODE void xc_sleep(void)
{
xc_adc_powerdown();
xc_pwr_usb_off();
xc_pwr_rc16m_off();
// xc_pwr_rom_off();
xc_pwr_modem_off();
xc_pwr_opa_tempsensor_off();
xc_pwr_opa_volr_off();
xc_pwr_revddldo_off();
cprao_aon_reg4__bb_coreldo_normal_sw_mux__setf(1);
xc_pwr_bor_off();
xc_pwr_dcdc_close();
xc_pwr_rfdigital_off();
xc_pwr_rc32k_calib_off();
rtc_rccal_en_set(0x00);
xc_pwr_pd_lightsleep_set();
#if (USE_XIP == 1)
#if (USE_ROM_FLASH)
FMC_SPI_Flash_PowerDown();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_power_down();
#endif // (USE_ROM_FLASH)
xc_pwr_rom_off();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close fmc
for (int i = 0; i < 10; i++) {
__NOP();
__NOP();
__NOP();
}
#endif
__disable_irq();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__WFI();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#if (USE_XIP == 1)
cpr_fmc_ctl_set(0x3503); // open FMC
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
xc_pwr_rom_on();
#if (USE_ROM_FLASH)
FMC_SPI_Flash_WakeUp();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_wake_up();
#endif // (USE_ROM_FLASH)
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#endif
xc_pwr_ao_timer_pclk32m_Set();
// xc_pwr_rom_on();
__enable_irq();
#ifdef USED_DCDC
xc_pwr_dcdc_open();
#endif
xc_pwr_modem_on();
xc_pwr_rfdigital_on();
xc_adc_wakeup();
}
__RAM_CODE void xc_deep_sleep()
{
xc_pwr_ao_timer_pclk32k_set();
adc_rf_ctl__pd_adc__setf(ADC_RF_CTL_PD_GADC_POWERDOWN);
xc_pwr_usb_off();
xc_pwr_rc16m_off();
xc_pwr_rfdigital_off();
xc_pwr_modem_off();
xc_pwr_pd_deepsleep_set();
xc_pwr_rom_on();
xc_pwr_dcdc_close();
#if (USE_XIP == 1)
#if (USE_ROM_FLASH)
FMC_SPI_Flash_PowerDown();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_power_down();
#endif // (USE_ROM_FLASH)
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
cpr_fmc_ctl_set(0x3000 | (1 << 9)); // close FMC
for (int i = 0; i < 10; i++) {
__NOP();
__NOP();
__NOP();
}
#endif
__disable_irq();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__WFI();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#if (USE_XIP == 1)
cpr_fmc_ctl_set(0x3503);
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
xc_pwr_rom_on();
#if (USE_ROM_FLASH)
FMC_SPI_Flash_WakeUp();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_wake_up();
#endif // (USE_ROM_FLASH)
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#endif
xc_pwr_ao_timer_pclk32m_Set();
// xc_pwr_rom_on();
__enable_irq();
#ifdef USED_DCDC
xc_pwr_dcdc_open();
#endif
xc_pwr_modem_on();
xc_pwr_rfdigital_on();
xc_adc_wakeup();
}
__RAM_CODE void xc_pwr_cpu_sleep_enter(void)
{
xc_pwr_ao_timer_pclk32k_set();
xc_adc_powerdown();
xc_pwr_usb_off();
xc_pwr_rc16m_off();
xc_pwr_rfdigital_off();
xc_pwr_modem_off();
xc_pwr_pd_lightsleep_set(); // auto switch core ldo voltage 1.17v to 0.89v
xc_pwr_opa_tempsensor_off();
xc_pwr_opa_volr_off();
xc_pwr_dcdc_close();
#if (USE_XIP == 1)
#if (USE_ROM_FLASH)
FMC_SPI_Flash_PowerDown();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_power_down();
#endif // (USE_ROM_FLASH)
cpr_fmc_ctl_set(0x3000 | (1 << 11) | (1 << 9)); // close FMC
#endif // USE_XIP
xc_pwr_rom_off();
__disable_irq();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__WFI(); // waiting to wake up
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
#if (USE_XIP == 1)
cpr_fmc_ctl_set(0x3503); // open FMC
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
xc_pwr_rom_on();
#if (USE_ROM_FLASH)
FMC_SPI_Flash_WakeUp();
#else // (USE_ROM_FLASH)
xc_fmc_spi_flash_wake_up();
#endif // (USE_ROM_FLASH)
#endif // USE_XIP
xc_pwr_ao_timer_pclk32m_Set();
// xc_pwr_rom_on();
__enable_irq();
#ifdef USED_DCDC
xc_pwr_dcdc_open();
#endif
xc_pwr_modem_on();
xc_pwr_rfdigital_on();
xc_adc_wakeup();
}
void xc_pwr_gpio_sleep_config(void)
{
#if (USE_XIP == 1)
/* puctrl1= 0xf ,clk,cs,d0,d1 must pulldown */
// cprao_aon_puctrl1_set(0xf);
cprao_aon_puctrl1_set(0x5555F);
#else
// if (sleep_mode == LIGHT_SLEEP_MODE) {
// XC_CPR_AO->PU_CTRLx[0] = 0x4;
// } else if (sleep_mode == DEEP_SLEEP_MODE) {
// XC_CPR_AO->PU_CTRLx[0] = 0xf;
// }
#endif
NVIC_DisableIRQ(GPIO_IRQn);
GPIO_InitCfg_t gpio_cfg = {0};
gpio_cfg.Mux = GPIO_Mux0;
gpio_cfg.Dir = GPIO_DIR_INPUT;
gpio_cfg.FunSel = GPIO_Dx;
gpio_cfg.Int = NOT_INT;
gpio_cfg.Pull = GPIO_PULLDOWN;
// The gpio scripts used cannot be configured. gpio36-39 cannot be
// configured.
for (int i = 0; i < GPIO_36; i++) {
gpio_cfg.Pin = i;
if (i == 18 || i == 19 ) // Default for uart0
{
} else if (i == 33 || i == 34) {
gpio_cfg.Pull = GPIO_PULLDOWN;
xc_gpio_init(&gpio_cfg);
}
else if (i == 35) {
gpio_cfg.Pull = GPIO_PULLDOWN;
xc_gpio_init(&gpio_cfg);
} else if (i == 20 || i == 21) {
// Pins required when using an external 32k crystal
if (xc_clock_lfclk_src_get() != CLOCK_LFCLK_SRC_XTAL) {
xc_gpio_init(&gpio_cfg);
}
} else {
xc_gpio_init(&gpio_cfg);
}
}
}
// void xc_gpio_sleep_config(void)
// {
// #if (USE_XIP == 1)
// cprao_aon_puctrl1_set(0xf);
// // XC_CPR_AO->PU_CTRLx[0] = 0xf; /* puctrl1= 0xf ,clk,cs,d0,d1 must pulldown */
// #endif
// NVIC_DisableIRQ(GPIO_IRQn);
// GPIO_InitCfg_t gpio_cfg = {0};
// gpio_cfg.Mux = GPIO_Mux0;
// gpio_cfg.Dir = GPIO_DIR_INPUT;
// gpio_cfg.FunSel = GPIO_Dx;
// gpio_cfg.Int = NOT_INT;
// gpio_cfg.Pull = GPIO_PULLDOWN;
// for (int i = 0; i < GPIO_MAX; i++) {
// gpio_cfg.Pin = i;
// if (i == 18 || i == 19) // Default for uart0
// {
// } else if (i == 33 || i == 34) {
// xc_gpio_pull_config(i, GPIO_PULLDOWN);
// } else if (i == 35) {
// gpio_cfg.Pull = GPIO_PULLDOWN;
// xc_gpio_init(&gpio_cfg);
// } else if (i == 20 || i == 21) {
// // Pins required when using an external 32k crystal
// if (xc_clock_lfclk_src_get() != CLOCK_LFCLK_SRC_XTAL) {
// xc_gpio_init(&gpio_cfg);
// }
// } else {
// xc_gpio_init(&gpio_cfg);
// }
// }
// }
void xc_pwr_gpio_lightsleep_wake_config(uint8_t pin, uint8_t edge_it)
{
GPIO_InitCfg_t gpio_cfg = {0};
gpio_cfg.Mux = GPIO_Mux0;
gpio_cfg.Dir = GPIO_DIR_INPUT;
gpio_cfg.FunSel = GPIO_Dx;
if (edge_it == RIS_EDGE_INT) {
gpio_cfg.Int = RIS_EDGE_INT;
gpio_cfg.Pull = GPIO_PULLDOWN;
} else if (edge_it == FAIL_EDGE_INT) {
gpio_cfg.Int = FAIL_EDGE_INT;
gpio_cfg.Pull = GPIO_PULLUP;
}
gpio_cfg.Pin = pin;
xc_gpio_init(&gpio_cfg);
NVIC_EnableIRQ(GPIO_IRQn);
}
void xc_pwr_pwrkey_init(void)
{
cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE);
cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE);
rtc_pwrkey_ctrl0_set(0);
rtc_pwrkey_ctrl1_set(0);
rtc_pwrkey_ctrl2_set(0);
}
void xc_pwr_pwrkey_deepsleep_wake_config(uint8_t pin, uint8_t level)
{
GPIO_InitCfg_t gpio_cfg = {0};
uint32_t val;
uint32_t val_ctl;
gpio_cfg.Mux = GPIO_Mux0;
gpio_cfg.Dir = GPIO_DIR_INPUT;
gpio_cfg.FunSel = GPIO_Dx;
gpio_cfg.Int = NOT_INT;
if (level == DEEP_SLEEP_GPIO_WAKE_HIGH_LEVEL) {
gpio_cfg.Pull = GPIO_PULLDOWN;
val = rtc_pwrkey_ctrl0__powkey_edge__getf();
val &= ~(1 << pin);
rtc_pwrkey_ctrl0__powkey_edge__setf(val);
} else if (level == DEEP_SLEEP_GPIO_WAKE_LOW_LEVEL) {
gpio_cfg.Pull = GPIO_PULLUP;
val = rtc_pwrkey_ctrl0__powkey_edge__getf();
val |= (1 << pin);
rtc_pwrkey_ctrl0__powkey_edge__setf(val);
}
gpio_cfg.Pin = pin;
xc_gpio_init(&gpio_cfg);
val_ctl =rtc_pwrkey_ctrl1_get();
rtc_pwrkey_ctrl1__powkey_en__setf((1 << pin)|val_ctl);
rtc_pwrkey_ctrl2__powkey_inten__setf(ENABLE);
NVIC_EnableIRQ(RTC_IRQn);
}
void xc_pwr_pwrkey_write_pin(uint8_t pin, uint8_t level)
{
uint32_t val;
if(cpr_ctlapbclken_grctl__rtc_pclk_en__getf()==DISABLE){
cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE);
}
if(cprao_aon_clken_grctl__rtc_clk_en__getf()==DISABLE){
cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE);
}
if(pin < 32){
val = rtc_pwrkey_soft_ctrl0_get();
val = val | (1 << pin);
rtc_pwrkey_soft_ctrl0_set(val);
val = rtc_pwrkey_soft_ctrl1_get();
if(level == 0){
val &= ~(1<<pin);
}else{
val |= (1<<pin);
}
rtc_pwrkey_soft_ctrl1_set(val);
}else{
val = rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__getf();
val = val | (1 << (pin-32));
rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__setf(val);
val = rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__getf();
if(level == 0){
val &= ~(1<<(pin-32));
}else{
val |= (1<<(pin-32));
}
rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__setf(val);
}
}
void xc_pwr_pwrkey_toggle_pin(uint8_t pin)
{
uint32_t val;
if(cpr_ctlapbclken_grctl__rtc_pclk_en__getf()==DISABLE){
cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE);
}
if(cprao_aon_clken_grctl__rtc_clk_en__getf()==DISABLE){
cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE);
}
if(pin < 32){
val = rtc_pwrkey_soft_ctrl0_get();
val = val | (1 << pin);
rtc_pwrkey_soft_ctrl0_set(val);
val = rtc_pwrkey_soft_ctrl1_get();
if(val == 0){
val |= (1<<pin);
}else{
val &= ~(1<<pin);
}
rtc_pwrkey_soft_ctrl1_set(val);
}else{
val = rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__getf();
val = val | (1 << (pin-32));
rtc_pwrkey_ctrl3__aogpio_soft_out_en_h__setf(val);
val = rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__getf();
if(( val & 1<<(pin-32)) == 0){
val |= (1<<(pin-32));
}else{
val &= ~(1<<(pin-32));
}
rtc_pwrkey_ctrl3__aogpio_soft_out_value_h__setf(val);
}
}
void xc_pwr_dcdc_init(uint8_t vol_level)
{
if (vol_level > 7) {
vol_level = 7;
}
cprao_aon_dcdc_ctr_reg1__dcdc_ctrl__setf(vol_level);
}
void xc_pwr_dcdc_close()
{
// 0b100, 3.3v supply power
cprao_aon_reg1__bb_coreldo_dcdc_sw_soft__setf(0);
cprao_aon_reg1__bb_coreldo_dcdc_sw_softsel__setf(0);
cprao_aon_reg1__bb_coreldo_dcdc_sw_mux__setf(1);
cprao_aon_dcdc_ctr_reg0_set(1<<6);
}
void xc_pwr_dcdc_open()
{
cprao_aon_dcdc_ctr_reg0__dcdc_en_soft__setf(1);
cprao_aon_dcdc_ctr_reg0__dcdc_bg_en_soft__setf(1);
// 0b011, dcdc supply power
cprao_aon_reg1__bb_coreldo_dcdc_sw_softsel__setf(1);
cprao_aon_reg1__bb_coreldo_dcdc_sw_soft__setf(1);
for (volatile uint16_t dly = 0; dly < 600; dly++) ;
cprao_aon_reg1__bb_coreldo_dcdc_sw_mux__setf(0);
}
@@ -0,0 +1,226 @@
/*!
* \file xc_drv_pwr.h
*
* \brief The header of xc_drv_pwr.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC_DRV_PWR_H_
#define __XC_DRV_PWR_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define RST_READY_TIME 0x07
#define OSC32_STABLE_TIME 80
#define WAIT_BLE_EXIT_LOWpwr_TIME 20 // 15
#define PRE_WAKEUP_TIME \
(RST_READY_TIME + OSC32_STABLE_TIME + WAIT_BLE_EXIT_LOWpwr_TIME)
#define DEEP_SLEEP_MODE 0
#define LIGHT_SLEEP_MODE 1
#define DEEP_SLEEP_GPIO_WAKE_HIGH_LEVEL 0
#define DEEP_SLEEP_GPIO_WAKE_LOW_LEVEL 1
#define BLE_IRQn_WAKE (1 << BLE_IRQn)
#define GPIO_IRQn_WAKE (1 << GPIO_IRQn)
#define RTC_IRQn_WAKE (1 << RTC_IRQn)
#define TIMER0_IRQn_WAKE (1 << TIMER0_IRQn)
#define TIMER1_IRQn_WAKE (1 << TIMER1_IRQn)
#define TIMER2_IRQn_WAKE (1 << TIMER2_IRQn)
#define TIMER3_IRQn_WAKE (1 << TIMER3_IRQn)
#define TIMER_AO0_IRQn_WAKE (1 << TIMER_AO0_IRQn)
#define TIMER_AO1_IRQn_WAKE (1 << TIMER_AO1_IRQn)
#define pwr_GPIO_LightSleepConfig pwr_GPIO_SleepConfig
#define pwr_GPIO_DeepSleepConfig pwr_GPIO_SleepConfig
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
/* pwr Init structure definition */
typedef struct
{
uint32_t pwr_wake_it_src;
uint32_t pwr_sleep_mode;
} PWR_InitCfg_t;
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
static __inline void xc_pwr_wake_it_set(uint32_t Val)
{
cprao_slpctl_int_mask_set(0xFFFFFFFF & (~Val));
}
static __inline void xc_pwr_usb_off(void) { cpr_rf_reg5_set(0x1C); }
static __inline void xc_pwr_rc16m_off(void)
{
cpr_rf_reg0__rc_16m_disalbe__setf(ENABLE);
}
static __inline void xc_pwr_aotimer_src_set32k(void)
{
cprao_aon_reg1__timer_ao_sleep_clksw__setf(ENABLE);
}
static __inline void xc_pwr_aotimer_src_set32m(void)
{
cprao_aon_reg1__timer_ao_sleep_clksw__setf(DISABLE);
}
static __inline void xc_pwr_pd_lightsleep_set(void)
{
cprao_aon_slp_pd_mask_set(0x101);
}
static __inline void xc_pwr_pd_deepsleep_set(void)
{
cprao_aon_slp_pd_mask_set(0x0);
}
static __inline void xc_pwr_osc_off(void)
{
cprao_aon_slp_ctl_set(0x0);
}
static __inline void xc_pwr_modem_off(void)
{
cprao_aon_vdd_iso_en__vddmdm_en__setf(ENABLE);
cprao_aon_vdd_switch_en__vddmdm_en__setf(DISABLE);
}
static __inline void xc_pwr_modem_on(void)
{
cprao_aon_vdd_iso_en__vddmdm_en__setf(DISABLE);
cprao_aon_vdd_switch_en__vddmdm_en__setf(ENABLE);
}
__RAM_CODE static __inline void xc_pwr_rom_off(void)
{
cprao_aon_vdd_iso_en__vddrom_en__setf(ENABLE);
cprao_aon_vdd_switch_en__vddrom_en__setf(DISABLE);
}
__RAM_CODE static __inline void xc_pwr_rom_on(void)
{
cprao_aon_vdd_iso_en__vddrom_en__setf(DISABLE);
cprao_aon_vdd_switch_en__vddrom_en__setf(ENABLE);
}
static __inline void xc_pwr_rfdigital_off(void)
{
uint32_t val;
val = cprao_aon_coreldo_en_get();
val &= 0xFFFFFFFE;
cprao_aon_coreldo_en_set(val);
}
static __inline void xc_pwr_rfdigital_on(void)
{
uint32_t val;
val = cprao_aon_coreldo_en_get();
val |= 1 << 0;
cprao_aon_coreldo_en_set(val);
}
static __inline void xc_pwr_sleepsrc_mask_set(uint32_t val)
{
cpr_slp_src_mask_set(val);
}
static __inline void xc_pwr_opa_volr_off(void)
{
// OPA volr off
uint32_t val;
val = cpr_opa_ctrl_reg__volr__getf();
val |= 1 << 2;
cpr_opa_ctrl_reg__opa_ctrl__setf(val);
}
static __inline void xc_pwr_revddldo_off()
{
cprao_aon_reg4__bb_lpoldo_ibc__setf(4);
}
static __inline void xc_pwr_opa_tempsensor_off(void)
{
cpr_opa_ctrl_reg__en_temp_sensor__setf(DISABLE);
}
static __inline void xc_pwr_bor_on(void)
{
cprao_aon_bor_ctr_reg0__en_bor__setf(DISABLE);
}
static __inline void xc_pwr_bor_off(void)
{
cprao_aon_bor_ctr_reg0__en_bor__setf(DISABLE);
}
static __inline void xc_pwr_rc32k_calib_off() {}
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_pwr_sleep_init(PWR_InitCfg_t *pwr_cfg);
void xc_pwr_ao_timer_pclk32m_Set(void);
void xc_pwr_ao_timer_pclk32k_set(void);
void xc_pwr_gpio_sleep_config(void);
void pwr_cpu_sleep_init(void);
__RAM_CODE void xc_pwr_cpu_sleep_enter(void);
__RAM_CODE void xc_pwr_ble_sleep_enter(void);
// void xc_sleep_init(void);
// void xc_gpio_sleep_config(void);
__RAM_CODE void xc_deep_sleep(void);
__RAM_CODE void xc_sleep(void);
void xc_pwr_gpio_lightsleep_wake_config(uint8_t pin, uint8_t edge_it);
void xc_pwr_pwrkey_init(void);
void xc_pwr_pwrkey_deepsleep_wake_config(uint8_t pin, uint8_t level);
void pwr_gpio_sleep_wake_config(uint8_t sleep_mode, uint8_t pin, uint8_t it);
void xc_pwr_dcdc_init(uint8_t vol_level);
void xc_pwr_dcdc_close(void);
void xc_pwr_dcdc_open(void);
void xc_pwr_vol_set(void);
#ifdef __cplusplus
}
#endif
#endif /* __XC6xxx_HAL_pwr_H_ */
@@ -0,0 +1,172 @@
/*!
* \file xc_drv_qdec.c
*
* \brief Target xc qdec driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_qdec.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_qdec_init(Qdec_InitCfg_t *init_cfg)
{
xc_gpio_mux_ctl(GPIO_21, GPIO_Mux2);
xc_gpio_mux_ctl(GPIO_20, GPIO_Mux2);
// DEBUG("0_CTLAPBCLKEN_GRCTL: %08x\n", cpr_ctlapbclken_grctl_get());
cpr_ctlapbclken_grctl__qdec_pclk_en__setf(ENABLE);
// DEBUG("1_CTLAPBCLKEN_GRCTL: %08x\n", cpr_ctlapbclken_grctl_get());
cpr_rstctl_ctlapb_sw__qdec_rstn__setf(~ENABLE);
cpr_rstctl_ctlapb_sw__qdec_rstn__setf(~DISABLE);
DEBUG("0_QDEC_CLK_CTL: %08x\n", cpr_qdec_clk_ctl_get());
cpr_qdec_clk_ctl__qdec_clk_div__setf(0x07);
cpr_qdec_clk_ctl__qdec_clk_en__setf(ENABLE);
DEBUG("1_QDEC_CLK_CTL: %08x\n", cpr_qdec_clk_ctl_get());
if(ENABLE == init_cfg->auto_clr_en) {
qdec_ctl__auto_clr_en__setf(ENABLE);
} else {
qdec_ctl__auto_clr_en__setf(DISABLE);
}
if(ENABLE == init_cfg->single_sample_rst_en) {
qdec_ctl__single_sample_rst_en__setf(ENABLE);
} else {
qdec_ctl__single_sample_rst_en__setf(DISABLE);
}
if(ENABLE == init_cfg->db_filter_en) {
qdec_ctl__db_filter_en__setf(ENABLE);
} else {
qdec_ctl__db_filter_en__setf(DISABLE);
}
QDEC_CTL_REG = 0x40;
qdec_samp_ctl_pack(init_cfg->db_sample_div,
init_cfg->num_pts_sampled,
init_cfg->acc_sample_div);
qdec_int_msk_pack(ENABLE, ENABLE, ENABLE, DISABLE);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_qdec_enable(void)
{
qdec_ctl__qdec_en__setf(ENABLE);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_qdec_disable(void)
{
qdec_ctl__qdec_en__setf(DISABLE);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_qdec_start(void)
{
qdec_ctl__qdec_start__setf(ENABLE);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_qdec_stop(void)
{
qdec_ctl__qdec_start__setf(DISABLE);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void QDEC_Handler(void)
{
uint8_t qdec_int_mask = qdec_int_msk_get( );
uint8_t qdec_int = qdec_int_get( );
uint8_t qdec_int_sta = (qdec_int & qdec_int_mask);
qdec_int_set(qdec_int);
if(SINGLE_SAMPLE_MSK_BIT == (qdec_int_sta & SINGLE_SAMPLE_MSK_BIT)) {
DEBUG("__SINGLE_SAMPLE_INT__\n");
}
if(SAMPLE_END_MSK_BIT == (qdec_int_sta & SAMPLE_END_MSK_BIT)) {
DEBUG("__SAMPLE_END_INT__\n");
DEBUG("Sample: %04x\n", (uint16_t)qdec_acc_get( ));
DEBUG("DB: %02x\n", (uint8_t)qdec_db_get( ));
}
if(ACC_OF_MSK_BIT == (qdec_int_sta & ACC_OF_MSK_BIT)) {
DEBUG("__ACC_INT__\n");
}
if(DB_OF_MSK_BIT == (qdec_int_sta & DB_OF_MSK_BIT)) {
DEBUG("__DB_INT__\n");
}
}
@@ -0,0 +1,120 @@
/*!
* \file xc_drv_qdec.h
*
* \brief The header of xc_drv_qdec.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_QDEC_H_
#define _XC_DRV_QDEC_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum {
QDEC_DIVIDE_DIV_1 = 0,
QDEC_DIVIDE_DIV_2 = 1,
QDEC_DIVIDE_DIV_4 = 2,
QDEC_DIVIDE_DIV_8 = 3,
QDEC_DIVIDE_DIV_16 = 4,
QDEC_DIVIDE_DIV_32 = 5,
QDEC_DIVIDE_DIV_64 = 6,
QDEC_DIVIDE_DIV_128 = 7,
QDEC_DIVIDE_DIV_256 = 8,
QDEC_DIVIDE_DIV_512 = 9,
QDEC_DIVIDE_DIV_1024 = 10,
QDEC_DIVIDE_DIV_2048 = 11,
QDEC_DIVIDE_DIV_4096 = 12,
QDEC_DIVIDE_DIV_8192 = 13,
QDEC_DIVIDE_DIV_16384 = 14,
QDEC_DIVIDE_DIV_32768 = 15,
QDEC_DIVIDE_DIV_65536 = 16,
QDEC_DIVIDE_DIV_131072 = 17,
QDEC_DIVIDE_DIV_262144 = 18,
QDEC_DIVIDE_DIV_524288 = 19,
QDEC_DIVIDE_DIV_1048576 = 20
} eSampleDivide;
typedef enum {
QDEC_PTS_NUM_5 = 0,
QDEC_PTS_NUM_10 = 1,
QDEC_PTS_NUM_40 = 2,
QDEC_PTS_NUM_80 = 3,
QDEC_PTS_NUM_120 = 4,
QDEC_PTS_NUM_160 = 5,
QDEC_PTS_NUM_200 = 6,
QDEC_PTS_NUM_240 = 7,
QDEC_PTS_NUM_280 = 8,
QDEC_PTS_NUM_320 = 9,
QDEC_PTS_NUM_360 = 10,
QDEC_PTS_NUM_400 = 11
} ePtsNum;
typedef enum {
QDEC_DB_SAMP_DIV_1 = 0,
QDEC_DB_SAMP_DIV_2 = 1,
QDEC_DB_SAMP_DIV_4 = 2,
QDEC_DB_SAMP_DIV_8 = 3,
QDEC_DB_SAMP_DIV_16 = 4,
QDEC_DB_SAMP_DIV_32 = 5,
QDEC_DB_SAMP_DIV_64 = 6
} eDBSampDiv;
typedef struct
{
uint8_t auto_clr_en;
uint8_t single_sample_rst_en;
uint8_t db_filter_en;
eSampleDivide acc_sample_div;
ePtsNum num_pts_sampled;
eDBSampDiv db_sample_div;
} Qdec_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_qdec_init(Qdec_InitCfg_t *init_cfg);
void xc_qdec_enable(void);
void xc_qdec_disable(void);
void xc_qdec_start(void);
void xc_qdec_stop(void);
#endif // _XC_DRV_AOTIMER_H_
@@ -0,0 +1,213 @@
/*!
* \file xc_drv_rtc.c
*
* \brief Target xc aotimer driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static volatile uint8_t calibration_flag = 0;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
uint8_t AO_Timer_Callback(uint8_t calib_flag);
RTC_Intr_Cb_t RTC_Intr_cb = {
AO_Timer_Callback,
T1_CMR_Callback,
T2_CMR_Callback,
T3_CMR_Callback,
Sec_Callback,
Min_Callback,
Hour_Callback,
Day_Callback};
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_rtc_start(void) { rtc_icr__rtc__cnt_e__setf(RTC_ICR_CNTE_ENABLE); }
void xc_rtc_stop(void) { rtc_icr__rtc__cnt_e__setf(RTC_ICR_CNTE_DISABLE); }
static void xc_rtc_matchtime_set(RTC_InitCfg_t *rtc_cfg)
{
if (rtc_cfg->MatchTime.ch == RTC_MATCH_T1) {
rtc_cmr_one_pack(rtc_cfg->MatchTime.Week, rtc_cfg->MatchTime.Hour,
rtc_cfg->MatchTime.Min, rtc_cfg->MatchTime.Sec);
} else if (rtc_cfg->MatchTime.ch == RTC_MATCH_T2) {
rtc_cmr_two_pack(rtc_cfg->MatchTime.Week, rtc_cfg->MatchTime.Hour,
rtc_cfg->MatchTime.Min, rtc_cfg->MatchTime.Sec);
} else if (rtc_cfg->MatchTime.ch == RTC_MATCH_T3) {
rtc_cmr_three_pack(rtc_cfg->MatchTime.Week, rtc_cfg->MatchTime.Hour,
rtc_cfg->MatchTime.Min, rtc_cfg->MatchTime.Sec);
}
}
void xc_rtc_date_get(Rtc_DateTypeDef_t *Date) { __rtc_dateget(Date); }
void xc_rtc_init(RTC_InitCfg_t *rtc_cfg)
{
cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE);
cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE);
rtc_icr_set(DISABLE);
rtc_raw_limit__setf(xc_clock_lfclk_in_get());
rtc_datelimitSet(rtc_cfg);
rtc_dateSet(rtc_cfg);
if (rtc_cfg->MatchTimeEnable) {
xc_rtc_matchtime_set(rtc_cfg);
rtc_config_matchtimeit(rtc_cfg);
}
if (rtc_cfg->SecIT_Enable) {
rtc_config_secit(rtc_cfg);
}
if (rtc_cfg->MinIT_Enable) {
rtc_config_minit(rtc_cfg);
}
if (rtc_cfg->HourIT_Enable) {
rtc_config_hourit(rtc_cfg);
}
if (rtc_cfg->DayIT_Enable) {
rtc_config_dayit(rtc_cfg);
}
}
uint8_t AO_Timer_Callback(uint8_t calib_flag)
{
calib_flag = 1;
return calib_flag;
}
void RTC_Handler(void)
{
uint32_t val;
val = rtc_all_intr_ao_get();
if (val & RTC_AO_ALL_INTR_AO_TIMER_INTR_Msk) {
rtc_ao_timer_ctl__rtc_ao_timer_clr__setf(RTC_AO_TIMER_CTL_AO_TIMER_CLR_SET);
rtc_ao_timer_ctl__rtc_ao_timer_en__setf(RTC_AO_TIMER_CTL_AO_TIMER_EN_DISABLE);
calibration_flag = RTC_Intr_cb.AO_Timer_Callback(calibration_flag);
}
val = rtc_isr_eoi_get();
if (val) {
rtc_isr_eoi_set(val);
if ((val & RTC_ICR_T1E_Msk) == RTC_ICR_T1E_Msk){
RTC_Intr_cb.T1_CMR_Callback();
}
if ((val & RTC_ICR_T2E_Msk) == RTC_ICR_T2E_Msk){
RTC_Intr_cb.T2_CMR_Callback();
}
if ((val & RTC_ICR_T3E_Msk) == RTC_ICR_T3E_Msk){
RTC_Intr_cb.T3_CMR_Callback();
}
if ((val & RTC_ICR_DaE_Msk) == RTC_ICR_DaE_Msk){
RTC_Intr_cb.Day_Callback();
}
if ((val & RTC_ICR_HoE_Msk) == RTC_ICR_HoE_Msk){
RTC_Intr_cb.Hour_Callback();
}
if ((val & RTC_ICR_MiE_Msk) == RTC_ICR_MiE_Msk){
RTC_Intr_cb.Min_Callback();
}
if ((val & RTC_ICR_SeE_Msk) == RTC_ICR_SeE_Msk){
RTC_Intr_cb.Sec_Callback();
}
}
}
__WEAK uint8_t T1_CMR_Callback(void) { return 0; }
__WEAK uint8_t T2_CMR_Callback(void) { return 0; }
__WEAK uint8_t T3_CMR_Callback(void) { return 0; }
__WEAK uint8_t Sec_Callback(void) { return 0; }
__WEAK uint8_t Min_Callback(void) { return 0; }
__WEAK uint8_t Hour_Callback(void) { return 0; }
__WEAK uint8_t Day_Callback(void) { return 0; }
/***********************************************************************************
***************************** RC32 Calibration
******************************
***********************************************************************************/
/**
* @brief RC32k_Count_Calib
* @details 鏍″噯 RC32K 瀹為檯璁℃暟鍊?
*
* @param RTC 瀵勫瓨鍣ㄧ储寮?
* @retval uint8_t
*/
uint8_t xc_rc32k_count_calib()
{
volatile int32_t hw_timeout = 10000;
uint32_t val;
float freq = 0.0;
rtc_ao_timer_ctl__rtc_ao_timer_value__setf(32);
rtc_ao_timer_ctl__rtc_freq_timer_en__setf(1);
while ((!(calibration_flag)) && (hw_timeout > 0)) {
__nop();
hw_timeout--;
}
if (hw_timeout < 0) {
return 1;
}
val = rtc_freq_32k_timer_val_get();
val *= (32000000.0f / xc_clock_hfclk_in_get());
rtc_ao_timer_ctl__rtc_ao_timer_en__setf(DISABLE);
rtc_ao_timer_ctl__rtc_ao_timer_clr__setf(ENABLE);
freq = (float)(15625.0f / (float)val) * 32768.0f;
DEBUG("Calib freq: %u\n", (uint32_t)freq);
rtc_raw_limit__setf((uint32_t)freq);
return 0;
}
@@ -0,0 +1,262 @@
/*!
* \file xc_drv_rtc.h
*
* \brief The header of xc_drv_rtc.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_RTC_H_
#define _XC_DRV_RTC_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
#include <stdbool.h>
#include <stdio.h>
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define RTC_ICR_DAE_ENABLE (1UL)
#define RTC_ICR_DAE_DISABLE (0UL)
#define RTC_ICR_HOE_ENABLE (1UL)
#define RTC_ICR_HOE_DISABLE (0UL)
#define RTC_ICR_MIE_ENABLE (1UL)
#define RTC_ICR_MIE_DISABLE (0UL)
#define RTC_ICR_SEE_ENABLE (1UL)
#define RTC_ICR_SEE_DISABLE (0UL)
#define RTC_ICR_T2E_ENABLE (1UL)
#define RTC_ICR_T2E_DISABLE (0UL)
#define RTC_ICR_T1E_ENABLE (1UL)
#define RTC_ICR_T1E_DISABLE (0UL)
#define RTC_ICR_T3E_ENABLE (1UL)
#define RTC_ICR_T3E_DISABLE (0UL)
#define RTC_ICR_MASK_ALL_ENABLE (1UL)
#define RTC_ICR_MASK_ALL_DISABLE (0UL)
#define RTC_ICR_CNTE_ENABLE (1UL)
#define RTC_ICR_CNTE_DISABLE (0UL)
#define RTC_AO_TIMER_CTL_AO_TIMER_CLR_SET (1UL)
#define RTC_AO_TIMER_CTL_AO_TIMER_CLR_RESET (0UL)
#define RTC_AO_TIMER_CTL_AO_TIMER_EN_ENABLE (1UL)
#define RTC_AO_TIMER_CTL_AO_TIMER_EN_DISABLE (0UL)
#define RTC_ICR_T1E_Msk (0x1UL << 5UL) /*!< Bit mask of T1E field. */
#define RTC_ICR_T2E_Msk (0x1UL << 4UL) /*!< Bit mask of T2E field. */
#define RTC_ICR_T3E_Msk (0x1UL << 6UL) /*!< Bit mask of T3E field. */
#define RTC_ICR_DaE_Msk (0x1UL << 0UL) /*!< Bit mask of DaE field. */
#define RTC_ICR_HoE_Msk (0x1UL << 1UL) /*!< Bit mask of HoE field. */
#define RTC_ICR_MiE_Msk (0x1UL << 2UL) /*!< Bit mask of MiE field. */
#define RTC_ICR_SeE_Msk (0x1UL << 3UL) /*!< Bit mask of SeE field. */
#define RTC_AO_ALL_INTR_AO_TIMER_INTR_Msk (0x1UL << 5UL) /*!< Bit mask of AO_TIMER_INTR field. */
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
RTC_MATCH_SUNDAY = (0x01 << 0), /*Interrupt from TIME1 event. */
RTC_MATCH_MONDAY = (0x01 << 1), /*Interrupt from TIME2 event. */
RTC_MATCH_TUESDAY = (0x01 << 2), /*Interrupt from TIME3 event. */
RTC_MATCH_WEDNESDAY = (0x01 << 3), /*Interrupt from SEC event. */
RTC_MATCH_THURSDAY = (0x01 << 4), /*Interrupt from MIN event. */
RTC_MATCH_FRIDAY = (0x01 << 5), /*Interrupt from HOUR event. */
RTC_MATCH_SATURDAY = (0x01 << 6) /*Interrupt from DAY event. */
} RTC_MatchWeek_TypeDef_t;
typedef enum
{
RTC_MATCH_T1 = (0x01 << 5), /**< MATCH_TIME_1 ch. */
RTC_MATCH_T2 = (0x01 << 4), /**< MATCH_TIME_2 ch */
RTC_MATCH_T3 = (0x01 << 6), /**< MATCH_TIME_3 ch */
} RTC_MatchTimeCh_TypeDef_t;
typedef struct
{
uint8_t Sec;
uint8_t Min;
uint8_t Hour;
uint8_t Week;
uint16_t Day;
} Rtc_DateTypeDef_t;
typedef struct
{
uint8_t HourLimit;
uint8_t MinLimit;
uint8_t SecLimit;
} Rtc_DateLimitTypeDef_t;
typedef struct
{
uint8_t ch;
uint8_t Sec;
uint8_t Min;
uint8_t Hour;
uint8_t Week;
} Rtc_MatchTimeTypeDef_t;
typedef struct
{
Rtc_DateTypeDef_t Date;
Rtc_DateLimitTypeDef_t DateLimit;
Rtc_MatchTimeTypeDef_t MatchTime;
bool MatchTimeEnable;
bool SecIT_Enable;
bool MinIT_Enable;
bool HourIT_Enable;
bool DayIT_Enable;
} RTC_InitCfg_t;
typedef struct RTC_Intr_Cb_s
{
uint8_t (*AO_Timer_Callback)(uint8_t calib_flag);
uint8_t (*T1_CMR_Callback)(void);
uint8_t (*T2_CMR_Callback)(void);
uint8_t (*T3_CMR_Callback)(void);
uint8_t (*Sec_Callback)(void);
uint8_t (*Min_Callback)(void);
uint8_t (*Hour_Callback)(void);
uint8_t (*Day_Callback)(void);
} RTC_Intr_Cb_t;
extern Rtc_DateTypeDef_t Date;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
static __inline void __rtc_dateget(Rtc_DateTypeDef_t *Date)
{
Date->Sec = rtc_ccvr__rtc_ccvr_sec__getf();
Date->Min = rtc_ccvr__rtc_ccvr_min__getf();
Date->Hour = rtc_ccvr__rtc_ccvr_hour__getf();
Date->Day = rtc_ccvr__rtc_ccvr_day__getf();
Date->Week = rtc_wvr__getf();
}
static __inline void rtc_datelimitSet(RTC_InitCfg_t *rtc_cfg)
{
rtc_hour_limit__setf(rtc_cfg->DateLimit.HourLimit);
rtc_minute_limit__setf(rtc_cfg->DateLimit.MinLimit);
rtc_second_limit__setf(rtc_cfg->DateLimit.SecLimit);
}
static __inline void rtc_dateSet(RTC_InitCfg_t *rtc_cfg)
{
rtc_clr__rtc_clr_day__setf(rtc_cfg->Date.Day);
rtc_clr__rtc_clr_hour__setf(rtc_cfg->Date.Hour);
rtc_clr__rtc_clr_min__setf(rtc_cfg->Date.Min);
rtc_clr__rtc_clr_sec__setf(rtc_cfg->Date.Sec);
rtc_wlr__setf(rtc_cfg->Date.Week);
}
static __inline void rtc_config_matchtimeit(RTC_InitCfg_t *rtc_cfg)
{
if (rtc_cfg->MatchTime.ch == RTC_MATCH_T1) {
if (rtc_cfg->MatchTimeEnable) {
rtc_icr__rtc_t1e__setf(1);
} else {
rtc_icr__rtc_t1e__setf(0);
}
} else if (rtc_cfg->MatchTime.ch == RTC_MATCH_T2) {
if (rtc_cfg->MatchTimeEnable) {
rtc_icr__rtc_t2e__setf(1);
} else {
rtc_icr__rtc_t2e__setf(0);
}
} else if (rtc_cfg->MatchTime.ch == RTC_MATCH_T3) {
if (rtc_cfg->MatchTimeEnable) {
rtc_icr__rtc_t3e__setf(1);
} else {
rtc_icr__rtc_t3e__setf(1);
}
}
}
static __inline void rtc_config_secit(RTC_InitCfg_t *rtc_cfg)
{
if (rtc_cfg->SecIT_Enable) {
rtc_icr__rtc__se_e__setf(1);
} else {
rtc_icr__rtc__se_e__setf(0);
}
}
static __inline void rtc_config_minit(RTC_InitCfg_t *rtc_cfg)
{
if (rtc_cfg->SecIT_Enable) {
rtc_icr__rtc__mi_e__setf(1);
} else {
rtc_icr__rtc__mi_e__setf(0);
}
}
static __inline void rtc_config_hourit(RTC_InitCfg_t *rtc_cfg)
{
if (rtc_cfg->SecIT_Enable) {
rtc_icr__rtc__ho_e__setf(1);
} else {
rtc_icr__rtc__ho_e__setf(0);
}
}
static __inline void rtc_config_dayit(RTC_InitCfg_t *rtc_cfg)
{
if (rtc_cfg->SecIT_Enable) {
rtc_icr__rtc__da_e__setf(1);
} else {
rtc_icr__rtc__da_e__setf(0);
}
}
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_rtc_init(RTC_InitCfg_t *rtc_cfg);
void xc_rtc_start(void);
void xc_rtc_stop(void);
void xc_rtc_date_get(Rtc_DateTypeDef_t *Date);
uint8_t AO_Timer_Callback(uint8_t calib_flag);
uint8_t T1_CMR_Callback(void);
uint8_t T2_CMR_Callback(void);
uint8_t T3_CMR_Callback(void);
uint8_t Sec_Callback(void);
uint8_t Min_Callback(void);
uint8_t Hour_Callback(void);
uint8_t Day_Callback(void);
void rtc_intr_callback(uint64_t intr_sta);
#endif // _XC_DRV_RTC_H_
@@ -0,0 +1,662 @@
/*!
* \file xc6xxx_hal_spi.c
*
* \brief Target xc6xxx hal spi implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
#include "xc_drv_fmc_spi.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
typedef struct
{
bool SPI_DMA_IT_Enable_Flag[3];
uint8_t SPI_Mode[3];
} SPI_CtrlBlock_Typedef;
SPI_CtrlBlock_Typedef m_spi_cb;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
eXC_RESULT xc_spi_write_bytes(uint8_t reg_idx, uint8_t *txdata, uint16_t len);
eXC_RESULT xc_spi_read_bytes(uint8_t reg_idx, uint8_t *rxdata, uint16_t len);
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_spi_init(uint8_t reg_idx, SPI_InitCfg_t *init_cfg)
{
#if (USE_XIP == 0)
if (SPI0_IDX == reg_idx) {
cpr_rstctl_subrst_sw__ssi0_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__ssi0_rstn__setf(RSTCTL_DISABLE);
cpr_ctlapbclken_grctl__ssi0_pclk_en__setf(ENABLE);
cpr_ssi0_mclk_ctl__ssi_mclk_div__setf(0);
cpr_ssi0_mclk_ctl__ssi_mclk_en__setf(1);
cpr_ssi_ctrl__ssi0_protocol__setf(SSI_CTRL0_FRF_MOTOROLA);
}
#endif
if (SPI1_IDX == reg_idx) {
cpr_rstctl_subrst_sw__ssi1_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__ssi1_rstn__setf(RSTCTL_DISABLE);
cpr_ssi1_mclk_ctl__ssi_mclk_div__setf(0);
cpr_ssi1_mclk_ctl__ssi_mclk_en__setf(1);
cpr_ctlapbclken_grctl__ssi1_pclk_en__setf(ENABLE);
if (init_cfg->Mode == SPI_MODE_MASTER) {
cpr_ssi_ctrl__ssi1_master_en__setf(ENABLE);
} else if (init_cfg->Mode == SPI_MODE_SLAVE) {
cpr_ssi_ctrl__ssi1_master_en__setf(DISABLE);
}
cpr_ssi_ctrl__ssi1_protocol__setf(SSI_CTRL0_FRF_MOTOROLA);
} else if (SPI2_IDX == reg_idx) {
cpr_rstctl_subrst_sw__ssi2_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__ssi2_rstn__setf(RSTCTL_DISABLE);
cpr_ssi1_mclk_ctl__ssi2_mclk_div__setf(0);
cpr_ssi1_mclk_ctl__ssi2_mclk_en__setf(1);
cpr_ctlapbclken_grctl__ssi2_pclk_en__setf(ENABLE);
cpr_ssi_ctrl__ssi2_protocol__setf(SSI_CTRL0_FRF_MOTOROLA);
}
spi_en_set(reg_idx, DISABLE);
// sste is automatically set to 1 when spi slave is initialized.
// therefor, manually clear this bit to 0 here.
spi_ctrl0__ssi_sste__setf(reg_idx, DISABLE);
spi_ctrl0__ssi_tmod__setf(reg_idx, init_cfg->Direction);
spi_ctrl0__ssi_scpol__setf(reg_idx, init_cfg->CLKPolarity);
spi_ctrl0__ssi_scpha__setf(reg_idx, init_cfg->CLKPhase);
spi_ctrl0__ssi_dfs__setf(reg_idx, init_cfg->DataSize);
spi_ie_set(reg_idx, DISABLE);
spi_se_set(reg_idx, ENABLE);
spi_baud__ssi_sckdv__setf(reg_idx, init_cfg->BaudRatePrescaler);
spi_txftl__ssi_tft__setf(reg_idx, SSI_TXFTL_FIFO_1);
spi_rxftl__ssi_rft__setf(reg_idx, SSI_RXFTL_FIFO_1);
}
static void xc_spi_enable(uint8_t reg_idx, uint8_t dfs)
{
spi_en__ssi_sen__setf(reg_idx, DISABLE);
spi_dmas_set(reg_idx, DISABLE);
spi_ctrl0__ssi_dfs__setf(reg_idx, dfs);
spi_en__ssi_sen__setf(reg_idx, ENABLE);
}
static void xc_spi_disable(uint8_t reg_idx) { spi_en__ssi_sen__setf(reg_idx, DISABLE); }
void xc_spi_rxftl_fifo_set(uint8_t reg_idx, uint8_t val)
{
spi_rxftl__ssi_rft__setf(reg_idx, val);
}
void xc_spi_txftl_fifo_set(uint8_t reg_idx, uint8_t val)
{
spi_txftl__ssi_tft__setf(reg_idx, val);
}
void xc_spi_enable_it(uint8_t reg_idx, uint8_t val) { spi_ie_set(reg_idx, val); }
void xc_spi_disable_it(uint8_t reg_idx, uint8_t val) { spi_ie_set(reg_idx, val); }
void xc_spi_flash_power_down(uint8_t reg_idx)
{
uint8_t txbuff[2] = {0};
txbuff[1] = CMD_PWRDWN;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_8BIT);
xc_spi_write_bytes(reg_idx, txbuff, sizeof(txbuff));
xc_spi_disable(reg_idx);
}
void xc_spi_flash_wake_up(uint8_t reg_idx)
{
uint8_t txbuff[2] = {0};
txbuff[1] = CMD_RELEASE_PWRDWN;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_8BIT);
xc_spi_write_bytes(reg_idx, txbuff, sizeof(txbuff));
xc_spi_disable(reg_idx);
}
static uint8_t xc_spi_flash_wait_busy(uint8_t reg_idx)
{
uint8_t cmd[2] = {0};
uint8_t sta[2] = {0xff, 0xff};
cmd[0] = CMD_READ_STATUS;
cmd[1] = 0xff;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_read_bytes(reg_idx, sta, sizeof(sta));
xc_spi_disable(reg_idx);
return (sta[1] & 0x01);
}
static void xc_spi_flash_write_enable(uint8_t reg_idx)
{
uint8_t txbuff[2] = {0};
txbuff[1] = CMD_WRITE_ENABLE;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_8BIT);
xc_spi_write_bytes(reg_idx, txbuff, sizeof(txbuff));
xc_spi_disable(reg_idx);
}
eXC_RESULT xc_spi_flash_erase_sector(uint8_t reg_idx, uint32_t Dst_Addr)
{
uint8_t cmd[4];
while (xc_spi_flash_wait_busy(reg_idx))
;
xc_spi_flash_write_enable(reg_idx);
while (xc_spi_flash_wait_busy(reg_idx))
;
cmd[0] = CMD_SECTOR_ERASE;
cmd[1] = Dst_Addr >> 16;
cmd[2] = Dst_Addr >> 8;
cmd[3] = Dst_Addr;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_disable(reg_idx);
while (xc_spi_flash_wait_busy(reg_idx))
;
return XR_OK;
}
#if (USE_INTEGRATED_FlASH == USE_PUYA_FlASH)
void xc_spi_flash_erase_page(uint8_t reg_idx, uint32_t Dst_Addr)
{
uint8_t cmd[4];
while (xc_spi_flash_wait_busy(reg_idx))
;
xc_spi_flash_write_enable(reg_idx);
while (xc_spi_flash_wait_busy(reg_idx))
;
cmd[0] = CMD_PAGE_ERASE;
cmd[1] = Dst_Addr >> 16;
cmd[2] = Dst_Addr >> 8;
cmd[3] = Dst_Addr;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_disable(reg_idx);
while (xc_spi_flash_wait_busy(reg_idx))
;
}
#endif
void xc_spi_flash_write_page(uint8_t reg_idx, uint32_t WriteAddr, uint8_t *pBuffer)
{
uint32_t addr = WriteAddr;
uint8_t cmd[16 + 4] = {0};
for (uint8_t i = 0; i < 16; i++) {
while (xc_spi_flash_wait_busy(reg_idx))
;
xc_spi_flash_write_enable(reg_idx);
while (xc_spi_flash_wait_busy(reg_idx))
;
cmd[0] = CMD_PAGE_PROGRAM;
cmd[1] = addr >> 16;
cmd[2] = addr >> 8;
cmd[3] = addr;
memcpy(&cmd[4], pBuffer + i * 16, 16);
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
addr += 16;
}
while (xc_spi_flash_wait_busy(reg_idx))
;
xc_spi_disable(reg_idx);
}
void xc_spi_flash_read_page(uint8_t reg_idx, uint32_t ReadAddr, uint8_t *pBuffer)
{
uint8_t cmd[16 + 4] = {0};
uint8_t mid[16 + 4] = {0};
uint16_t rx_idx = 0;
uint32_t addr = ReadAddr;
for (uint8_t i = 0; i < 16; i++) {
cmd[0] = CMD_READ_DATA;
cmd[1] = addr >> 16;
cmd[2] = addr >> 8;
cmd[3] = addr;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_read_bytes(reg_idx, mid, sizeof(cmd));
memcpy(&pBuffer[rx_idx], mid + 4, 16);
addr += 16;
rx_idx += 16;
}
xc_spi_disable(reg_idx);
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
* @return[out]
*
****************************************************************************************
*/
eXC_RESULT xc_spi_flash_write(uint8_t reg_idx, uint32_t writeAddr, uint8_t *buff,
uint16_t size)
{
uint32_t cur_addr = writeAddr;
uint32_t end_addr = writeAddr + size;
uint16_t wt_len = 0;
// The current page number occupied by this data storage
uint16_t CurSectorNum = 0;
uint16_t CurPageNum = 0;
// The position occupied by this address on the current page
uint32_t CurStartPsr = 0;
uint32_t mid = 0;
xc_spi_flash_rdid(reg_idx ,(uint8_t*)&mid);
if(mid != GD_FlASH_RDID){
uint8_t temp_buff[FLASH_PAGE_SIZE];
while (cur_addr != end_addr) {
/* code */
CurPageNum = CUR_PAGE_NUM(cur_addr);
CurStartPsr = CUR_START_PSR(cur_addr);
xc_spi_flash_read_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE, temp_buff);
xc_spi_flash_erase_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE);
if (CurStartPsr) {
memcpy(&temp_buff[CurStartPsr], buff + wt_len,
(FLASH_PAGE_SIZE - CurStartPsr) > size - wt_len // 当前扇区剩余的空间是否满足写长度
? size - wt_len
: (FLASH_PAGE_SIZE - CurStartPsr));
wt_len += wt_len + ((FLASH_PAGE_SIZE - CurStartPsr) > size - wt_len
? size - wt_len
: (FLASH_PAGE_SIZE - CurStartPsr));
cur_addr += wt_len;
} else {
memcpy(temp_buff, buff + wt_len,
size - wt_len > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE
: size - wt_len);
cur_addr += (size - wt_len > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE
: size - wt_len);
wt_len += (size - wt_len > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE
: size - wt_len);
}
xc_spi_flash_write_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE, temp_buff);
}
}else if(mid == GD_FlASH_RDID){
uint8_t temp_buff[FLASH_SECTOR_SIZE];
while (cur_addr != end_addr) {
/* code */
CurSectorNum = CUR_SECTOR_NUM(cur_addr);
CurStartPsr = CUR_START_PSR(cur_addr);
for(int i=0;i<FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE;i++){
xc_spi_flash_read_page(reg_idx, CurSectorNum * FLASH_SECTOR_SIZE + i* FLASH_PAGE_SIZE, temp_buff+i*FLASH_PAGE_SIZE);
}
xc_spi_flash_erase_sector(reg_idx ,CurSectorNum * FLASH_SECTOR_SIZE);
if (CurStartPsr) {
memcpy(&temp_buff[CurStartPsr], buff + wt_len,
(FLASH_SECTOR_SIZE - CurStartPsr) > size - wt_len // 当前扇区剩余的空间是否满足写长度
? size - wt_len
: (FLASH_SECTOR_SIZE - CurStartPsr));
wt_len += wt_len + ((FLASH_SECTOR_SIZE - CurStartPsr) > size - wt_len
? size - wt_len
: (FLASH_SECTOR_SIZE - CurStartPsr));
cur_addr += wt_len;
} else {
memcpy(temp_buff, buff + wt_len,
size - wt_len > FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE
: size - wt_len);
cur_addr += (size - wt_len > FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE
: size - wt_len);
wt_len += (size - wt_len > FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE
: size - wt_len);
}
for(int i=0;i<FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE;i++){
xc_spi_flash_write_page(reg_idx, CurSectorNum * FLASH_SECTOR_SIZE + i* FLASH_PAGE_SIZE, temp_buff+i*FLASH_PAGE_SIZE);
}
}
}
return XR_OK;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
* @return[out]
*
****************************************************************************************
*/
eXC_RESULT xc_spi_flash_read(uint8_t reg_idx, uint32_t readAddr, uint8_t *buff,
uint16_t len)
{
eXC_RESULT ret = XR_OK;
// The page number to be occupied by the data written this time
uint16_t ReqPageCnt = 0;
// The current page number occupied by this data storage
uint16_t CurPageNum = 0;
// The position occupied by this address on the current page
uint16_t CurStartPsr = 0;
// The next page number that may be occupied by this data storage
uint16_t NextPageNum = 0;
// The end address of the next page that may be occupied by this data
// storage
uint16_t NextStopPsr = 0;
uint8_t temp_buff[FLASH_PAGE_SIZE] = {0};
if (len <= FLASH_PAGE_SIZE) {
CurPageNum = CUR_PAGE_NUM(readAddr);
CurStartPsr = CUR_START_PSR(readAddr);
if ((len + CurStartPsr) > FLASH_PAGE_SIZE)
ReqPageCnt = 2;
else
ReqPageCnt = 1;
if (ReqPageCnt == 1) // Note that only one page is read here
{
xc_spi_flash_read_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE,
temp_buff);
memcpy(buff, &temp_buff[CurStartPsr], len);
} else if (ReqPageCnt == 2) {
NextPageNum = CurPageNum + 1;
NextStopPsr = len + CurStartPsr - FLASH_PAGE_SIZE;
// First page read
xc_spi_flash_read_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE,
temp_buff);
memcpy(buff, &temp_buff[CurStartPsr], len - NextStopPsr);
// second page read
uint16_t HaveCopyNum = len - NextStopPsr;
xc_spi_flash_read_page(reg_idx, NextPageNum * FLASH_PAGE_SIZE,
temp_buff);
memcpy(buff + HaveCopyNum, temp_buff, NextStopPsr);
}
} else {
CurPageNum = CUR_PAGE_NUM(readAddr);
CurStartPsr = CUR_START_PSR(readAddr);
NextPageNum = CurPageNum + 1;
uint16_t buff_idx = 0;
uint16_t pre_len = NextPageNum * FLASH_PAGE_SIZE - readAddr;
uint32_t pre_addr = CurPageNum * FLASH_PAGE_SIZE;
xc_spi_flash_read_page(reg_idx, pre_addr, temp_buff);
memcpy(buff, &temp_buff[CurStartPsr], pre_len);
buff_idx += pre_len;
pre_addr = NextPageNum * FLASH_PAGE_SIZE;
while (buff_idx < len) {
if ((len - buff_idx) >= FLASH_PAGE_SIZE) {
xc_spi_flash_read_page(reg_idx, pre_addr, temp_buff);
memcpy(&buff[buff_idx], temp_buff, FLASH_PAGE_SIZE);
buff_idx += FLASH_PAGE_SIZE;
pre_addr += FLASH_PAGE_SIZE;
} else {
xc_spi_flash_read_page(reg_idx, pre_addr, temp_buff);
memcpy(&buff[buff_idx], temp_buff, len - buff_idx);
buff_idx += (len - buff_idx);
pre_addr += (len - buff_idx);
}
}
}
return ret;
}
void xc_spi_flash_read_128bit_uid(uint8_t reg_idx, uint8_t *buff)
{
while (xc_spi_flash_wait_busy(reg_idx)) {
DEBUG("line=%d,status=%d\n", __LINE__, xc_spi_flash_wait_busy(reg_idx));
};
uint8_t cmd[21] = {0};
uint8_t id[21] = {0};
cmd[0] = CMD_RUID;
cmd[1] = 0x00;
cmd[2] = 0x00;
cmd[3] = 0x00;
cmd[4] = 0x00;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_read_bytes(reg_idx, id, sizeof(id));
xc_spi_disable(reg_idx);
memcpy(buff, &id[5], 16);
}
eXC_RESULT xc_spi_flash_rdid(uint8_t reg_idx, uint8_t *buff)
{
while (xc_spi_flash_wait_busy(reg_idx)) {
DEBUG("line=%d,status=%d\n", __LINE__, xc_spi_flash_wait_busy(reg_idx));
};
uint8_t cmd[4] = {0};
uint8_t id[4] = {0};
cmd[0] = CMD_RDID;
cmd[1] = 0xff;
cmd[2] = 0xff;
cmd[3] = 0xff;
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_read_bytes(reg_idx, id, sizeof(id));
xc_spi_disable(reg_idx);
memcpy(buff, &id[1], 3);
return XR_OK;
}
/*---------------------------------- SPI1 Master & Slave API
* ---------------------------------------*/
/**
****************************************************************************************
* @brief Only Master & Slave
*
* @param[in]
* @param[in]
****************************************************************************************
*/
static void xc_spi_datasize_set(uint8_t reg_idx, uint8_t dfs)
{
spi_en_set(reg_idx, DISABLE);
spi_ctrl0__ssi_dfs__setf(reg_idx, dfs);
spi_en_set(reg_idx, ENABLE);
}
/**
****************************************************************************************
* @brief Only applicable Master & Slave communication
*
* @param[in]
* @param[in]
****************************************************************************************
*/
eXC_RESULT xc_spi_write_bytes(uint8_t reg_idx, uint8_t *txdata, uint16_t len)
{
if (len == 0)
return XR_ERROR;
uint16_t n;
uint8_t remain = len % 2;
uint16_t cnt = len / 2;
uint16_t mid_data[128 + 1] = {0};
uint16_t i = 0;
while (spi_sts__ssi_tfe__getf(reg_idx) == RESET) {
i++;
if (i >= SPI_WAIT_TIMEOUT) {
//h
// DEBUG("func=%s,line=%d,timeout\n", __func__, __LINE__);
return XR_TIMEOUT;
}
}
if (cnt != 0) {
for (n = 0; n < cnt; n++) {
mid_data[n] = ((txdata[n * 2] << 8) | txdata[n * 2 + 1]);
}
}
if (remain != 0) {
for (n = 0; n < remain; n++) {
mid_data[cnt] |= (txdata[cnt * 2 + n] << (16 - 8 * n));
}
}
if (cnt != 0) {
if (remain != 0)
cnt = cnt + 1;
for (n = 0; n < cnt; n++)
spi_data_set(reg_idx, mid_data[n]);
} else {
spi_data_set(reg_idx, mid_data[0]);
}
while ((spi_sts__ssi_rfne__getf(reg_idx) == RESET) ||
(spi_sts__ssi_tfe__getf(reg_idx) == RESET)) {
i++;
if (i >= SPI_WAIT_TIMEOUT) {
// DEBUG("func=%s,line=%d,timeout\n", __func__, __LINE__);
return XR_TIMEOUT;
}
}
return XR_OK;
}
/**
****************************************************************************************
* @brief Only applicable Master & Slave communication
*
* @param[in]
* @param[in]
****************************************************************************************
*/
eXC_RESULT xc_spi_read_bytes(uint8_t reg_idx, uint8_t *rxdata, uint16_t len)
{
if (len == 0)
return XR_ERROR;
uint16_t n;
uint8_t remain = len % 2;
uint16_t cnt = len / 2;
uint16_t mid_data = 0;
if (cnt != 0) {
for (n = 0; n < cnt; n++) {
mid_data = spi_data_get(reg_idx);
rxdata[n * 2] = mid_data >> 8;
rxdata[n * 2 + 1] = mid_data;
}
}
if (remain != 0) {
mid_data = spi_data_get(reg_idx);
for (n = 0; n < remain; n++) {
rxdata[cnt * 2 + n] = mid_data >> 8;
rxdata[cnt * 2 + 1 + n] = mid_data;
}
}
return XR_OK;
}
/**
****************************************************************************************
* @brief Only applicable Master & Slave communication
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_spi_write_and_read_data(uint8_t reg_idx, uint8_t *w_data, uint16_t w_size,
uint8_t *r_data, uint16_t r_size)
{
if (w_size != (spi_rxftl_get(reg_idx) + 1) * 2)
return;
xc_spi_datasize_set(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
xc_spi_write_bytes(reg_idx, w_data, w_size);
while (!(spi_is_get(reg_idx) == SSI_IS_RXFIS_SET))
;
xc_spi_read_bytes(reg_idx, r_data, r_size);
xc_spi_disable(reg_idx);
}
@@ -0,0 +1,174 @@
/*!
* \file xc_drv_aotimer.h
*
* \brief The header of xc_drv_aotimer.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_SPI_H_
#define _XC_DRV_SPI_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define SPI_WAIT_TIMEOUT 65535
// temporary macros -- alex revised
#define SSI_CTRL0_FRF_MOTOROLA (0x1UL)
#define SSI_CTRL0_FRF_TI (0x0UL)
/* SPI_Mode SPI Mode */
#define SPI_MODE_SLAVE (0x00000000U)
#define SPI_MODE_MASTER (0x00000001U)
/* SPI_data_size */
#define SSI_CTRL0_DFS_LEN_16BIT ((uint16_t)0x0fUL)
#define SSI_CTRL0_DFS_LEN_8BIT ((uint16_t)0x07UL)
/* SPI_data_direction */
#define SSI_CTRL0_TMOD_WR (0x0UL)
#define SSI_CTRL0_TMOD_W (0x1UL)
#define SSI_CTRL0_TMOD_R (0x2UL)
/* SPI_BaudRate_Prescaler */
#define SSI_BAUD_DIV_2 (0x02UL)
#define SSI_BAUD_DIV_4 (0x04UL)
#define SSI_BAUD_DIV_6 (0x06UL)
#define SSI_BAUD_DIV_8 (0x08UL)
#define SSI_BAUD_DIV_10 (0x0aUL)
#define SSI_BAUD_DIV_12 (0x0cUL)
/* SPI_Clock_Polarity */
#define SSI_CTRL0_SCPOL_HIGH (0x1UL)
#define SSI_CTRL0_SCPOL_LOW (0x0UL)
/* SPI_Clock_Phase */
#define SSI_CTRL0_SCPHA_LEAD (0x0UL)
#define SSI_CTRL0_SCPHA_TRAIL (0x1UL)
/* SPI_MSB_transmission */
#define SPI_FirstBit_MSB ((uint16_t)0x0000)
#define SSI_TXFTL_FIFO_0 (0x00UL)
#define SSI_TXFTL_FIFO_1 (0x01UL)
#define SSI_TXFTL_FIFO_2 (0x02UL)
#define SSI_TXFTL_FIFO_3 (0x03UL)
#define SSI_TXFTL_FIFO_4 (0x04UL)
#define SSI_TXFTL_FIFO_5 (0x05UL)
#define SSI_TXFTL_FIFO_6 (0x06UL)
#define SSI_TXFTL_FIFO_7 (0x07UL)
#define SSI_RXFTL_FIFO_0 (0x00UL)
#define SSI_RXFTL_FIFO_1 (0x01UL)
#define SSI_RXFTL_FIFO_2 (0x02UL)
#define SSI_RXFTL_FIFO_3 (0x03UL)
#define SSI_RXFTL_FIFO_4 (0x04UL)
#define SSI_RXFTL_FIFO_5 (0x05UL)
#define SSI_RXFTL_FIFO_6 (0x06UL)
#define SSI_RXFTL_FIFO_7 (0x07UL)
#define SSI_IE_TXEIE_ENABLE (0x1UL << SSI_TXEIE_POS)
#define SSI_IE_TXEIE_DISABLE (0x0UL << SSI_TXEIE_POS)
#define SSI_IE_TXOIE_ENABLE (0x1UL << SSI_TXOIE_POS)
#define SSI_IE_TXOIE_DISABLE (0x0UL << SSI_TXOIE_POS)
#define SSI_IE_RXUIE_ENABLE (0x1UL << SSI_RXUIE_POS)
#define SSI_IE_RXUIE_DISABLE (0x0UL << SSI_RXUIE_POS)
#define SSI_IE_RXOIE_ENABLE (0x1UL << SSI_RXOIE_POS)
#define SSI_IE_RXOIE_DISABLE (0x0UL << SSI_RXOIE_POS)
#define SSI_IE_RXFIE_ENABLE (0x1UL << SSI_RXFIE_POS)
#define SSI_IE_RXFIE_DISABLE (0x0UL << SSI_RXFIE_POS)
#define SSI_IS_TXEIS_SET (0x1UL << SSI_TXEIS_POS)
#define SSI_IS_TXEIS_RESET (0x0UL << SSI_TXEIS_POS)
#define SSI_IS_TXOIS_SET (0x1UL << SSI_TXOIS_POS)
#define SSI_IS_TXOIS_RESET (0x0UL << SSI_TXOIS_POS)
#define SSI_IS_RXUIS_SET (0x1UL << SSI_RXUIS_POS)
#define SSI_IS_RXUIS_RESET (0x0UL << SSI_RXUIS_POS)
#define SSI_IS_RXOIS_SET (0x1UL << SSI_RXOIS_POS)
#define SSI_IS_RXOIS_RESET (0x0UL << SSI_RXOIS_POS)
#define SSI_IS_RXFIS_SET (0x1UL << SSI_RXFIS_POS)
#define SSI_IS_RXFIS_RESET (0x0UL << SSI_RXFIS_POS)
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef struct
{
uint16_t Mode;
uint32_t Direction;
uint32_t DataSize;
uint32_t CLKPolarity;
uint32_t CLKPhase;
uint32_t NSS;
uint32_t BaudRatePrescaler;
uint32_t FirstBit;
} SPI_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
typedef void (*timer_handler_callback)(void *context);
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_spi_init(uint8_t reg_idx, SPI_InitCfg_t *init_cfg);
void xc_spi_rxftl_fifo_set(uint8_t reg_idx, uint8_t val);
void xc_spi_txftl_fifo_set(uint8_t reg_idx, uint8_t val);
void xc_spi_enable_it(uint8_t reg_idx, uint8_t val);
void xc_spi_disable_it(uint8_t reg_idx, uint8_t val);
void xc_spi_flash_power_down(uint8_t reg_idx);
void xc_spi_flash_wake_up(uint8_t reg_idx);
uint8_t xc_spi_flash_wait_busy(uint8_t reg_idx);
eXC_RESULT xc_spi_flash_erase_sector(uint8_t reg_idx, uint32_t Dst_Addr);
void xc_spi_flash_erase_page(uint8_t reg_idx, uint32_t Dst_Addr);
void xc_spi_flash_write_page(uint8_t reg_idx, uint32_t WriteAddr,
uint8_t *pBuffer);
void xc_spi_flash_read_page(uint8_t reg_idx, uint32_t ReadAddr, uint8_t *pBuffer);
eXC_RESULT xc_spi_flash_write(uint8_t reg_idx, uint32_t writeAddr, uint8_t *buff,
uint16_t size);
eXC_RESULT xc_spi_flash_read(uint8_t reg_idx, uint32_t readAddr, uint8_t *buff,
uint16_t size);
void xc_spi_flash_read_128bit_uid(uint8_t reg_idx, uint8_t *buff);
eXC_RESULT xc_spi_flash_rdid(uint8_t reg_idx, uint8_t *buff);
void xc_spi_write_and_read_data(uint8_t reg_idx, uint8_t *w_data, uint16_t w_size,
uint8_t *r_data, uint16_t r_size);
#endif // _XC_DRV_AOTIMER_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,92 @@
/*!
* \file xc_drv_spi_dma.h
*
* \brief The header of xc_drv_spi_dma.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef __XC_DRV_SPI_DMA_H_
#define __XC_DRV_SPI_DMA_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define SPI1_BASE_OFFSET 0x1000
#define SPI2_BASE_OFFSET 0x1800
#define SSIx_DATA_OFFSET 0x60
#define FLASH_PAGE_SIZE 256
#define FLASH_SECTOR_SIZE 4096
#define CMD_READ_DATA (uint8_t)0x03
#define CMD_READ_STATUS (uint8_t)0x05
#define CMD_CHIP_ERASE (uint8_t)0xc7
#define CMD_WRITE_ENABLE (uint8_t)0x06
#define CMD_WRITE_DISABLE (uint8_t)0x04
#define CMD_PAGE_PROGRAM (uint8_t)0x02
#define CMD_BLOCK_ERASE (uint8_t)0xD8
#define CMD_SECTOR_ERASE (uint8_t)0x20
#define CMD_PAGE_ERASE (uint8_t)0x81
#define CMD_RELEASE_PWRDWN (uint8_t)0xAB
#define CMD_PWRDWN (uint8_t)0xB9
#define CMD_RUID (uint8_t)0x4B
#define CMD_RDID (uint8_t)0x9F
//#define CUR_PAGE_NUM(addr) (addr/FLASH_PAGE_SIZE)
//#define CUR_START_PSR(addr) (addr%FLASH_PAGE_SIZE)
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_spi_dma_deinit(uint8_t spi_idx);
void xc_spi_dma_read_data(uint8_t spi_idx, uint8_t *data, uint16_t size);
void xc_spi_dma_write_data(uint8_t spi_idx, uint8_t *data, uint16_t size);
void xc_spi_dma_write_and_read_data(uint8_t spi_idx,
uint8_t *w_data, uint16_t w_size,
uint8_t *r_data, uint16_t r_size);
void xc_spi_dma_read_and_write_data(uint8_t spi_idx,
uint8_t *w_data, uint16_t w_size,
uint8_t *r_data, uint16_t r_size);
void xc_spi_dma_flash_power_down(uint8_t spi_idx);
void xc_spi_dma_flash_wakeup(uint8_t spi_idx);
void xc_spi_dma_flash_wait_busy(uint8_t spi_idx);
void xc_spi_dma_flash_erase_sector(uint8_t spi_idx, uint32_t Dst_Addr);
void xc_spi_dma_flash_erase_page(uint8_t spi_idx, uint32_t Dst_Addr);
void xc_spi_dma_flash_write_page(uint8_t spi_idx, uint32_t WriteAddr, uint8_t *data, uint16_t size);
void xc_spi_dma_flash_read_page(uint8_t spi_idx, uint32_t ReadAddr, uint8_t *data, uint16_t size);
void xc_spi_dma_flash_rdid(uint8_t spi_idx, uint8_t *rdid);
void xc_spi_dma_flash_ruid(uint8_t spi_idx, uint8_t *ruid);
eXC_RESULT xc_spi_dma_flash_write(uint8_t spi_idx, uint32_t writeAddr, uint8_t *buff, uint16_t size);
eXC_RESULT xc_spi_dma_flash_read(uint8_t spi_idx, uint32_t readAddr, uint8_t *buff, uint16_t size);
#endif /* __XC_DRV_SPI_DMA_H_ */
@@ -0,0 +1,242 @@
/*!
* \file xc6xxx_sw_i2c.c
*
* \brief Target xc software i2c implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_sw_i2c.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define AT24C01 128
#define AT24C02 256
#define AT24C04 512
#define AT24C08 1024
#define AT24C16 2048
#define AT24C32 4096
#define AT24C64 8192
#define AT24C128 16384
#define AT24C256 32768
#define EE_PAGE_ADDR_UNIT 256
#define EE_PAGE_BYTE 8
#define EE_SIZE AT24C08
#define I2C_SLAVE_ADDR (0x50)
#define AT24XX_SR1_ADDR (0x50)
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void i2c_software_init(void)
{
GPIO_InitCfg_t gpio_cfg = {0};
gpio_cfg.FunSel = GPIO_Dx;
gpio_cfg.Dir = GPIO_DIR_OUTPUT;
gpio_cfg.Pull = GPIO_PULLDOWN;
gpio_cfg.Int = NOT_INT;
gpio_cfg.Pin = SCL_PIN;
xc_gpio_init(&gpio_cfg);
gpio_cfg.Pin = SDA_PIN;
xc_gpio_init(&gpio_cfg);
}
void i2c_start(void)
{
SDA_OUT_HIGH(SDA_PIN);
SCL_OUT_HIGH(SCL_PIN);
delay_us(2);
SDA_OUT_LOW(SDA_PIN); // START:when CLK is high,DATA change form high to low
delay_us(2);
SCL_OUT_LOW(SCL_PIN);
}
void i2c_stop(void)
{
SCL_OUT_LOW(SCL_PIN);
SDA_OUT_LOW(SDA_PIN); // STOP:when CLK is high DATA change form low to high
delay_us(2);
SCL_OUT_HIGH(SCL_PIN);
delay_us(2);
SDA_OUT_HIGH(SDA_PIN);
delay_us(2);
}
uint8_t i2c_wait_ack(void)
{
uint8_t ucErrTime = 0;
SDA_INPUT(SDA_PIN, GPIO_PULLUP);
delay_us(7);
SCL_OUT_HIGH(SCL_PIN);
delay_us(7);
while (SDA_INPUT_VAL(SDA_PIN)) {
ucErrTime++;
if (ucErrTime > 250) {
i2c_stop();
return 1;
}
}
SCL_OUT_LOW(SCL_PIN);
delay_us(2);
return 0;
}
void i2c_ack(void)
{
SCL_OUT_LOW(SCL_PIN);
SDA_OUT_LOW(SDA_PIN);
delay_us(2);
SCL_OUT_HIGH(SCL_PIN);
delay_us(2);
SCL_OUT_LOW(SCL_PIN);
}
void i2c_nack(void)
{
SCL_OUT_LOW(SCL_PIN);
SDA_OUT_HIGH(SDA_PIN);
delay_us(2);
SCL_OUT_HIGH(SCL_PIN);
delay_us(2);
SCL_OUT_LOW(SCL_PIN);
}
void i2c_send_byte(uint8_t txd)
{
uint8_t t;
SCL_OUT_LOW(SCL_PIN);
for (t = 0; t < 8; t++) {
if ((txd & 0x80) >> 7) {
SDA_OUT_HIGH(SDA_PIN);
} else {
SDA_OUT_LOW(SDA_PIN);
}
txd <<= 1;
delay_us(2);
SCL_OUT_HIGH(SCL_PIN);
delay_us(2);
SCL_OUT_LOW(SCL_PIN);
delay_us(2);
}
}
uint8_t i2c_read_byte(unsigned char ack)
{
unsigned char i, receive = 0;
SDA_INPUT(SDA_PIN, GPIO_PULLUP);
for (i = 0; i < 8; i++) {
SCL_OUT_LOW(SCL_PIN);
delay_us(5);
SCL_OUT_HIGH(SCL_PIN);
receive <<= 1;
if (SDA_INPUT_VAL(SDA_PIN)) {
receive++;
}
delay_us(5);
}
if (!ack)
i2c_nack();
else
i2c_ack();
return receive;
}
uint8_t at24cxx_read_byte(uint16_t addr)
{
uint8_t temp = 0;
i2c_start();
if (EE_SIZE > AT24C16) {
i2c_send_byte(0XA0);
i2c_wait_ack();
i2c_send_byte(addr >> 8);
i2c_wait_ack();
} else
i2c_send_byte(0XA0 + ((addr / 256) << 1));
i2c_wait_ack();
i2c_send_byte(addr % 256);
i2c_wait_ack();
i2c_start();
i2c_send_byte(0XA0 + ((addr / 256) << 1) + 1);
i2c_wait_ack();
temp = i2c_read_byte(0);
i2c_stop();
return temp;
}
void at24cxx_write_byte(uint16_t addr, uint8_t data)
{
i2c_start();
if (EE_SIZE > AT24C16) {
i2c_send_byte(0XA0);
i2c_wait_ack();
i2c_send_byte(addr >> 8);
} else {
i2c_send_byte(0XA0 + ((addr / 256) << 1));
}
i2c_wait_ack();
i2c_send_byte(addr % 256);
i2c_wait_ack();
i2c_send_byte(data);
i2c_wait_ack();
i2c_stop();
delay_ms(10);
}
void at24cxx_write_nbytes(uint16_t addr, uint8_t *buff, uint32_t num)
{
while (num--) {
at24cxx_write_byte(addr, *buff);
addr++;
buff++;
}
}
void at24cxx_read_nbytes(uint16_t addr, uint8_t *buff, uint32_t num)
{
while (num) {
*buff++ = at24cxx_read_byte(addr++);
num--;
}
}
@@ -0,0 +1,101 @@
/*!
* \file xc6xxx_sw_i2c.h
*
* \brief The header of xc6xxx_sw_i2c.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC_DRV_SW_I2C_H_
#define __XC_DRV_SW_I2C_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define SDA_OUT_HIGH(pin) \
{ \
xc_gpio_direction_config(pin, GPIO_DIR_OUTPUT); \
xc_gpio_write_pin(pin, GPIO_PIN_SET); \
}
#define SDA_OUT_LOW(pin) \
{ \
xc_gpio_direction_config(pin, GPIO_DIR_OUTPUT); \
xc_gpio_write_pin(pin, GPIO_PIN_RESET); \
}
#define SCL_OUT_HIGH(pin) \
{ \
xc_gpio_direction_config(pin, GPIO_DIR_OUTPUT); \
xc_gpio_write_pin(pin, GPIO_PIN_SET); \
}
#define SCL_OUT_LOW(pin) \
{ \
xc_gpio_direction_config(pin, GPIO_DIR_OUTPUT); \
xc_gpio_write_pin(pin, GPIO_PIN_RESET); \
}
#define SDA_INPUT(pin, pull) \
{ \
xc_gpio_direction_config(pin, GPIO_DIR_INPUT); \
xc_gpio_pull_config(pin, pull); \
}
#define SDA_INPUT_VAL(pin) xc_gpio_read_pin(pin)
#define SCL_PIN 2
#define SDA_PIN 3
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void i2c_start(void);
void i2c_stop(void);
void i2c_send_byte(uint8_t txd);
void i2c_ack(void);
uint8_t i2c_read_byte(unsigned char ack);
void i2c_nack(void);
uint8_t i2c_wait_ack(void);
void i2c_software_init(void);
uint8_t at24cxx_read_byte(uint16_t addr);
void at24cxx_write_byte(uint16_t addr, uint8_t data);
void at24cxx_write_nbytes(uint16_t addr, uint8_t *buff, uint32_t num);
void at24cxx_read_nbytes(uint16_t addr, uint8_t *buff, uint32_t num);
#endif /* __XC60xx_SW_I2C_H_ */
@@ -0,0 +1,68 @@
/*!
* \file xc_drv_systick.c
*
* \brief Target xinchip systick driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_systick.h"
#include "xc_drv_clock.h"
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void SysTick_Handler(void) { systick_callback(); }
void delay_us(uint32_t nus)
{
if (nus == 0)
return;
uint32_t unit = xc_systick_unit_get();
uint32_t temp;
SysTick->CTRL = 0x00; // 关闭计数器
SysTick->LOAD = unit * nus - unit + 1;
SysTick->VAL = 0;
SysTick->CTRL = 0x05;
do {
temp = SysTick->CTRL; // 读取当前倒计数值
} while ((temp & 0x01) && (!(temp & (1 << 16))));
}
void delay_ms(uint32_t nms)
{
if (nms == 0) {
return;
}
do {
delay_us(1000);
} while (--nms);
}
__WEAK void systick_callback(void) {}
@@ -0,0 +1,50 @@
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2024-05-10 09:47:53
* @LastEditors: sueRimn
* @LastEditTime: 2024-05-10 09:50:47
*/
/*!
* \file xc_drv_systick.h
*
* \brief The header of xc_drv_systick.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_SYSTICK_H_
#define _XC_DRV_SYSTICK_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void delay_us(uint32_t nus);
void delay_ms(uint32_t nms);
void systick_callback(void);
#endif /* _XC_DRV_SYSTICK_H_ */
@@ -0,0 +1,208 @@
/*!
* \file xc_drv_timer.c
*
* \brief Target xc timer driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_timer.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
timer_handler_callback timer_n_callback[4] = {timer0_callback, timer1_callback,
timer2_callback, timer3_callback};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_timer_init(uint8_t reg_idx, Timer_InitCfg_t *init_cfg)
{
if (TIMER0_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer0_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer0_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer0_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
} else if (TIMER1_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer1_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer1_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer1_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
} else if (TIMER2_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer2_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer2_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer2_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
} else if (TIMER3_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer3_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer3_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer3_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
}
cpr_lp_ctl__timer_sysclk_sel__setf(ENABLE);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_DISABLE);
timer_tcr__tms__setf(reg_idx, (uint8_t)init_cfg->timer_mode);
}
static uint32_t xc_timer_us_to_ticks(uint8_t reg_idx, uint32_t us)
{
uint32_t ticks;
uint8_t src_clk;
if (TIMER0_IDX == reg_idx) {
src_clk = cpr_timer0_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer0_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer0_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
} else if (TIMER1_IDX == reg_idx) {
src_clk = cpr_timer1_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer1_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer1_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
} else if (TIMER2_IDX == reg_idx) {
src_clk = cpr_timer2_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer2_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer2_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
} else if (TIMER3_IDX == reg_idx) {
src_clk = cpr_timer3_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer3_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer3_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
}
if (ticks < TIMER_MIN_TLC_VAL)
ticks = TIMER_MIN_TLC_VAL;
return ticks;
}
void xc_timer_set_value(uint8_t reg_idx, uint32_t us)
{
uint32_t ticks = xc_timer_us_to_ticks(reg_idx, us);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_DISABLE);
timer_tlc_set(reg_idx, ticks);
}
void xc_timer_start(uint8_t reg_idx)
{
NVIC_EnableIRQ((IRQn_Type)(TIMER0_IRQn + reg_idx));
timer_tcr__tim__setf(reg_idx, TIMER_TCR_TIM_DISABLE);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_ENABLE);
}
void xc_timer_start_noirq(uint8_t reg_idx)
{
NVIC_DisableIRQ((IRQn_Type)(TIMER0_IRQn + reg_idx));
timer_tcr__tim__setf(reg_idx, TIMER_TCR_TIM_DISABLE);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_ENABLE);
}
void xc_timer_stop(uint8_t reg_idx)
{
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_DISABLE);
}
void TIMER0_Handler(void)
{
(void)timer_tic_get(TIMER0_IDX);
if (timer_n_callback[0] != NULL)
timer_n_callback[0](NULL);
}
void TIMER1_Handler(void)
{
(void)timer_tic_get(TIMER1_IDX);
if (timer_n_callback[1] != NULL)
timer_n_callback[1](NULL);
}
void TIMER2_Handler(void)
{
(void)timer_tic_get(TIMER2_IDX);
if (timer_n_callback[2] != NULL)
timer_n_callback[2](NULL);
}
void TIMER3_Handler(void)
{
(void)timer_tic_get(TIMER3_IDX);
if (timer_n_callback[3] != NULL)
timer_n_callback[3](NULL);
}
__WEAK void timer0_callback(void *context) {}
__WEAK void timer1_callback(void *context) {}
__WEAK void timer2_callback(void *context) {}
__WEAK void timer3_callback(void *context) {}
@@ -0,0 +1,107 @@
/*!
* \file xc_drv_timer.h
*
* \brief The header of xc_drv_aotimer.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef _XC_DRV_TIMER_H_
#define _XC_DRV_TIMER_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define TIMER_MIN_TLC_VAL 0x04
#define TIMER_CLKSRC_32K_CAL(us) ( (CLOCK_RC_LFCLK_IN_32K / 1000)*us / 1000)
#define TIMER_CLKSRC_32K_DIV_CAL(us, div) (32000 /(2 * (div + 1)) /100 * us / 10000)
#define TIMER_CLKSRC_32M_DIV_CAL(us, div) (32000000 / (2 * (div + 1)) /100000 * us / 10)
#define TIMER_TCR_TIM_DISABLE (0x00UL)
#define TIMER_TCR_TIM_ENABLE (0x01UL)
#define TIMER_TCR_TES_ENABLE (0x01UL)
#define TIMER_TCR_TES_DISABLE (0x00UL)
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
TIMER_CLK_SRC_32M_DIV = 0, /* Timer CLK SRC 32MHz div. */
TIMER_CLK_SRC_32K_DIV = 1, /* Timer CLK SRC 32kHz div. */
TIMER_CLK_SRC_32K = 3, /* Timer CLK SRC 32kHz. */
} TIMER_SrcClkTypeDef;
typedef enum
{
TIMER_DIV_CLK_16MHzOr16K = 0, /* Timer ref clk 16 MHz or 16KHz */
TIMER_DIV_CLK_8MHzOr8K = 1, /* Timer ref clk 8 MHz or 8KHz */
TIMER_DIV_CLK_4MHzOr4K = 2, /* Timer ref clk 4 MHz or 4KHz.*/
TIMER_DIV_CLK_2MHzOr2K = 3, /* Timer ref clk 2 MHz or 2KHz.*/
TIMER_DIV_CLK_1MHzOr1K = 4, /* Timer ref clk 1 MHz or 1KHz.*/
TIMER_DIV_CLK_500KHzOr500 = 5, /* Timer ref clk 500 kHz or 500Hz.*/
TIMER_DIV_CLK_250KHzOr250 = 6, /* Timer ref clk 250 kHz or 250Hz.*/
TIMER_DIV_CLK_125KHzOr125 = 7, /* Timer ref clk 125 kHz or 125Hz.*/
TIMER_DIV_CLK_62500HzOr62_5 = 8, /* Timer ref clk 62500 Hz or 62.5Hz.*/
TIMER_DIV_CLK_32000Hz = 9 /* Timer ref clk 32000 Hz.*/
} Timer_DivClkTypeDef;
typedef enum
{
TIMER_MODE_SINGLE = 0,
TIMER_MODE_CYCLE = 1,
} Timer_ModeTypeDef;
typedef struct
{
TIMER_SrcClkTypeDef timer_src_clk; /* Timer src clk. */
Timer_DivClkTypeDef timer_div_clk; /* Timer div clk. */
Timer_ModeTypeDef timer_mode; /* Timer mode. */
uint32_t ticks; /* Timer ticks. */
} Timer_InitCfg_t;
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
typedef void (*timer_handler_callback)(void *context);
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_timer_init(uint8_t reg_idx, Timer_InitCfg_t *init_cfg);
void xc_timer_set_value(uint8_t reg_idx, uint32_t us);
void xc_timer_start(uint8_t reg_idx);
void xc_timer_stop(uint8_t reg_idx);
void timer0_callback(void *context);
void timer1_callback(void *context);
void timer2_callback(void *context);
void timer3_callback(void *context);
#endif // _XC_DRV_AOTIMER_H_
@@ -0,0 +1,199 @@
/*!
* \file xc6xxx_hal_uart.c
*
* \brief Target xc6xxx hal uart implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_uart.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
uint8_t __attribute__((aligned(4))) uart_txdmabuff[UART_BUFF_LEN];
uint8_t __attribute__((aligned(4))) uart_rxdmabuff[UART_BUFF_LEN];
UART_Block_t uart_ctl_block;
bool buffer_complet_flag = 0;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_uart_init(uint8_t reg_idx, UART_InitCfg_t *uart_cfg)
{
uint32_t val;
uint32_t uart_clk = 0x00;
uint32_t div, mul, clk_ctl, adj_div, m0_fclk_div;
m0_fclk_div = cpr_m0_fclk_ctl__m0_fclk_div__getf();
uart_clk = xc_clock_hfclk_in_get() * (m0_fclk_div + 1);
mul = (uart_cfg->BaudRate >> 20) & 0xFFFF;
div = (uart_cfg->BaudRate >> 4) & 0xFFFF;
adj_div = uart_clk / 1000000;
clk_ctl = (mul << 16) | (div * adj_div / 32);
if (reg_idx == UART0_IDX) {
cpr_rstctl_subrst_sw__uart0_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__uart0_rstn__setf(RSTCTL_DISABLE);
val = cpr_lp_ctl_get();
val &= ~(UART0_CLK_OFF_PROTECT_EN_BIT);
cpr_lp_ctl_set(val);
cpr_ctlapbclken_grctl__uart0_pclk_en__setf(ENABLE);
cpr_uart0_clk_grctl__uart0_clk_gr__setf(8);
cpr_uart0_clk_grctl__uart0_clk_gr_upd__setf(ENABLE);
cpr_uart0_clk_ctl_set(clk_ctl);
}
if (reg_idx == UART1_IDX) {
cpr_rstctl_subrst_sw__uart1_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__uart1_rstn__setf(RSTCTL_DISABLE);
val = cpr_lp_ctl_get();
val &= ~(UART1_CLK_OFF_PROTECT_EN_BIT);
cpr_lp_ctl_set(val);
cpr_ctlapbclken_grctl__uart1_pclk_en__setf(ENABLE);
cpr_uart1_clk_grctl__uart1_clk_gr__setf(8);
cpr_uart1_clk_grctl__uart1_clk_gr_upd__setf(ENABLE);
cpr_uart1_clk_ctl_set(clk_ctl);
}
if (reg_idx == UART2_IDX) {
cpr_rstctl_subrst_sw__uart2_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__uart2_rstn__setf(RSTCTL_DISABLE);
cpr_uart2_clk_grctl__uart2_pclk_en__setf(ENABLE);
cpr_uart2_clk_grctl__uart2_clk_gr__setf(8);
cpr_uart2_clk_grctl__uart2_clk_gr_upd__setf(ENABLE);
cpr_uart2_clk_ctl_set(clk_ctl);
}
uart_tcr__dlab__setf(reg_idx, UART_TCR_DLAB_DLLH_ENABLE);
uart_dll__dll__setf(reg_idx, (uart_cfg->BaudRate & 0xF));
uart_ier_set(reg_idx, 0);
uart_tcr__dlab__setf(reg_idx, UART_TCR_DLAB_DLLH_DISABLE);
while (uart_usr_get(reg_idx) == 1) {
};
uart_tcr__eps__setf(reg_idx, uart_cfg->Parity);
uart_tcr__stop__setf(reg_idx, uart_cfg->StopBits);
uart_tcr__cls__setf(reg_idx, uart_cfg->WordLength);
uart_mcr__afce__setf(reg_idx, uart_cfg->HardwareFlowControl);
uart_fcr_pack(reg_idx, UART_FCR_RCVR_TRIGGER_FIFO_2_1, UART_FCR_TX_EMPTY_TRIGGER_FIFO_2_1,
UART_FCR_XMIT_FIFO_RESET_CLEAR, UART_FCR_RCVR_FIFO_RESET_CLEAR, UART_FCR_FIFO_ENABLE_ENABLE);
}
void xc_uart_enable_rx_it(uint8_t reg_idx) { uart_ier__erdai__setf(reg_idx, UART_IER_ERDAI_ENABLE); }
void xc_uart_disable_rx_it(uint8_t reg_idx) { uart_ier__erdai__setf(reg_idx, UART_IER_ERDAI_DISABLE); }
void xc_uart_send_byte(uint8_t reg_idx, uint8_t byte)
{
while (1) {
if (uart_tsr__thre__getf(reg_idx) & UART_TSR_THRE_VALID) {
break;
}
}
uart_thr__thr__setf(reg_idx, byte);
}
void xc_uart_send_data(uint8_t reg_idx, uint8_t *data, uint16_t len)
{
for (int i = 0; i < len; i++) {
xc_uart_send_byte(reg_idx, data[i]);
}
}
void xc_uart_ctl_block_reset(void)
{
memset(&uart_ctl_block, 0, sizeof(uart_ctl_block));
uart_ctl_block.uart_receive_cb = NULL;
}
void xc_uart_register_receive_cb(uart_handler_callback uart_cb) { uart_ctl_block.uart_receive_cb = uart_cb; }
__WEAK void uart_user_handler(uint8_t reg_idx)
{
uint8_t rx_val;
uint32_t IIR, TSR;
IIR = uart_iir__iid__getf(reg_idx);
TSR = uart_tsr_get(reg_idx);
if (((IIR & IID_MASK) == UART_IIR_IID_BUSY)) {
uart_usr_get(reg_idx);
}
if (((IIR & IID_MASK) == UART_IIR_IID_ETSI)) {
DEBUG("line=%d, error handle \n", __LINE__);
}
if (((IIR & IID_MASK) == UART_IIR_IID_ERDAI)) {
TSR = uart_tsr_get(reg_idx);
while ((TSR & UART_TSR_DR_VALID) == UART_TSR_DR_VALID) {
rx_val = uart_rbr__rbr__getf(reg_idx);
TSR = uart_tsr_get(reg_idx);
if (uart_ctl_block.uart_receive_cb != NULL) {
uart_ctl_block.uart_receive_cb(&rx_val, 1);
}
}
}
if ((IIR & IID_MASK) == UART_IIR_IID_TO) {
TSR = uart_tsr_get(reg_idx);
while ((TSR & UART_TSR_DR_VALID) == UART_TSR_DR_VALID) {
rx_val = uart_rbr__rbr__getf(reg_idx);
TSR = uart_tsr_get(reg_idx);
if (uart_ctl_block.uart_receive_cb != NULL) {
uart_ctl_block.uart_receive_cb(&rx_val, 1);
}
}
}
}
void UART0_Handler(void) { uart_user_handler(UART0_IDX); }
void UART1_Handler(void) { uart_user_handler(UART1_IDX); }
void UART2_Handler(void) { uart_user_handler(UART2_IDX); }
@@ -0,0 +1,257 @@
/*!
* \file xc_drv_uart.h
*
* \brief The header of xc_drv_uart.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/** Define to Prevent Recursive Inclusion */
#ifndef __XC_UART_H__
#define __XC_UART_H__
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdio.h>
#include "ringbuffer.h"
#include "xc6xxx.h"
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef void (*uart_handler_callback)(uint8_t *buff, uint16_t len);
/**
* @brief UART interrupt ID enumeration
*/
typedef enum
{
UART_IT_Modem_Status = 0x00, /*!< modem status Interrupt */
UART_NO_Pending_INT = 0x01, /*!< no interrupt pending */
UART_IT_THR_Empty = 0x02, /*!< THR emptyInterrupt */
UART_IT_Received_Data_Available = 0x04, /*!< received data available Interrupt */
UART_IT_Receive_Line_Status = 0x06, /*!< receiver line status Interrupt */
UART_IT_Character_Timeout = 0x0C, /*!< character timeout Interrupt */
} UART_IT_TypeDef;
/**
* @brief UART Init Structure Definition
*/
typedef struct
{
uint32_t BaudRate;
uint16_t WordLength;
uint16_t StopBits;
uint16_t Parity;
uint16_t HardwareFlowControl;
} UART_InitCfg_t;
typedef struct
{
uart_handler_callback uart_receive_cb;
} UART_Block_t;
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
#define UART_IER_ERDA_ENABLE (0x1UL)
#define UART_IER_ERDA_DISABLE (0x0UL)
#define UART_IER_ETHEI_ENABLE (0x1UL)
#define UART_IER_ETHEI_DISABLE (0x0UL)
#define UART_IER_ETSI_ENABLE (0x1UL)
#define UART_IER_ETSI_DISABLE (0x0UL)
#define UART_IER_EMSI_ENABLE (0x1UL)
#define UART_IER_EMSI_DISABLE (0x0UL)
#define UART_IER_ETSI_ENABLE (0x1UL)
#define UART_IER_ETSI_DISABLE (0x0UL)
#define UART_IER_ETHSI_ENABLE (0x1UL)
#define UART_IER_ETHSI_DISABLE (0x0UL)
#define UART_IER_ERDAI_ENABLE (0x1UL)
#define UART_IER_ERDAI_DISABLE (0x0UL)
#define UART_IER_PTIME_ENABLE (0x1UL)
#define UART_IER_PTIME_DISABLE (0x0UL)
#define UART_IIR_IID_EMSI (0x0UL)
#define UART_IIR_IID_NO_IT (0x1UL)
#define UART_IIR_IID_ETHEI (0x02UL)
#define UART_IIR_IID_ERDAI (0x04UL)
#define UART_IIR_IID_ETSI (0x06UL)
#define UART_IIR_IID_BUSY (0x07UL)
#define UART_IIR_IID_TO (0xCUL)
#define UART_IIR_FS_ENABLE (0x3UL)
#define UART_IIR_FS_DISABLE (0x0UL)
#define UART_FCR_FIFO_ENABLE_ENABLE (0x1UL)
#define UART_FCR_FIFO_ENABLE_DISABLE (0x0UL)
#define UART_FCR_RCVR_FIFO_RESET_CLEAR (0x1UL)
#define UART_FCR_RCVR_FIFO_RESET_NOT_CLEAR (0x0UL)
#define UART_FCR_XMIT_FIFO_RESET_CLEAR (0x1UL)
#define UART_FCR_XMIT_FIFO_RESET_NOT_CLEAR (0x0UL)
#define UART_FCR_TX_EMPTY_TRIGGER_FIFO_EMPTY (0x0UL)
#define UART_FCR_TX_EMPTY_TRIGGER_FIFO_2_BYTE (0x1UL)
#define UART_FCR_TX_EMPTY_TRIGGER_FIFO_4_3 (0x2UL)
#define UART_FCR_TX_EMPTY_TRIGGER_FIFO_2_1 (0x3UL)
#define UART_FCR_RCVR_TRIGGER_FIFO_1_BYTE (0x0UL)
#define UART_FCR_RCVR_TRIGGER_FIFO_4_1 (0x1UL)
#define UART_FCR_RCVR_TRIGGER_FIFO_2_1 (0x2UL)
#define UART_FCR_RCVR_TRIGGER_FIFO_LESS_2_BYTE (0x3UL)
#define UART_TCR_CLS_Pos (0UL)
#define UART_TCR_CLS_Msk (0x3UL)
#define UART_TCR_CLS_5BITS (0x0UL)
#define UART_TCR_CLS_6BITS (0x1UL)
#define UART_TCR_CLS_7BITS (0x2UL)
#define UART_TCR_CLS_8BITS (0x3UL)
#define UART_TCR_STOP_Pos (2UL)
#define UART_TCR_STOP_Msk (0x1UL)
#define UART_TCR_STOP_1BITS (0x0UL)
#define UART_TCR_STOP_1_5BITS (0x1UL)
#define UART_TCR_STOP_2BITS (0x1UL)
#define UART_TCR_PEN_DISABLE (0x0UL)
#define UART_TCR_PENS_ENABLE (0x1UL)
#define UART_TCR_EPS_ODD (0x0UL)
#define UART_TCR_EPS_EVEN (0x1UL)
#define UART_TCR_BREAK_STOP (0x1UL)
#define UART_TCR_BREAK_RECOVER (0x0UL)
#define UART_TCR_DLAB_DLLH_ENABLE (0x1UL)
#define UART_TCR_DLAB_DLLH_DISABLE (0x0UL)
#define UART_MCR_RTS_Msk (0x1UL)
#define UART_MCR_RTS_OUT_HIGH (0x1UL)
#define UART_MCR_RTS_OUT_LOW (0x0UL)
#define UART_MCR_AFCE_ENABLE (0x1UL)
#define UART_MCR_AFCE_DISABLE (0x0UL)
#define UART_TSR_DR_VALID (0x1UL)
#define UART_TSR_DR_INVALID (0x0UL)
#define UART_TSR_OE_VALID (0x1UL)
#define UART_TSR_OE_INVALID (0x0UL)
#define UART_TSR_PE_Pos (2UL)
#define UART_TSR_PE_Msk (0x1UL)
#define UART_TSR_PE_VALID (0x1UL)
#define UART_TSR_PE_INVALID (0x0UL)
#define UART_TSR_FE_VALID (0x1UL)
#define UART_TSR_FE_INVALID (0x0UL)
#define UART_TSR_BI_VALID (0x1UL)
#define UART_TSR_BI_INVALID (0x0UL)
#define UART_TSR_THRE_VALID (0x1UL)
#define UART_TSR_THRE_INVALID (0x0UL)
#define UART_TSR_RX_FIFO_ERROR_VALID (0x1UL)
#define UART_TSR_RX_FIFO_ERROR_INVALID (0x0UL)
#define UART_MSR_DCTS_CHANGE (0x1UL)
#define UART_MSR_DCTS_NO_CHANGE (0x0UL)
#define UART_MSR_CTS_OUT_LOW (0x1UL)
#define UART_MSR_CTS_OUT_HIGH (0x0UL)
#define UART_USR_BUSY_BUSY (0x1UL)
#define UART_USR_BUSY_IDLE (0x0UL)
#define UART_NUM 3
#define UART_BUFF_LEN 64U
#define UART_DATA_5_BITS UART_TCR_CLS_5BITS
#define UART_DATA_6_BITS UART_TCR_CLS_6BITS
#define UART_DATA_7_BITS UART_TCR_CLS_7BITS
#define UART_DATA_8_BITS UART_TCR_CLS_8BITS
#define UART_STOP_1_BITS UART_TCR_STOP_1BITS
#define UART_STOP_1_5_BITS UART_TCR_STOP_1_5BITS
#define UART_STOP_2_BITS UART_TCR_STOP_2BITS
#define UART_HWFC_DISABLE UART_MCR_AFCE_DISABLE
#define UART_HWFC_ENABLE UART_MCR_AFCE_ENABLE
#define UART_PARITY_ENABLE UART_TCR_PENS_ENABLE
#define UART_PARITY_DISABLE UART_TCR_PEN_DISABLE
#define UART_PARITY_EVEN (UART_TCR_EPS_EVEN | UART_PARITY_ENABLE)
#define UART_PARITY_ODD (UART_TCR_EPS_ODD | UART_PARITY_ENABLE)
#define UART_BAUDRATE_2400 (0x0120271CUL)
#define UART_BAUDRATE_4800 (0x0240271CUL)
#define UART_BAUDRATE_9600 (0x0480271CUL)
#define UART_BAUDRATE_12800 (0x04802719UL)
#define UART_BAUDRATE_14400 (0x04802718UL)
#define UART_BAUDRATE_19200 (0x04802716UL)
#define UART_BAUDRATE_23040 (0x04802715UL)
#define UART_BAUDRATE_38400 (0x04802713UL)
#define UART_BAUDRATE_57600 (0x04802712UL)
#define UART_BAUDRATE_115200 (0x04802711UL)
#define UART_BAUDRATE_128000 (0x030007D3UL)
#define UART_BAUDRATE_230400 (0x09002711UL)
#define UART_BAUDRATE_256000 (0x060007D3UL)
#define UART_BAUDRATE_460800 (0x12002711UL)
#define UART_BAUDRATE_921600 (0x24002711UL)
#define UART_BAUDRATE_1M (0x00100011UL)
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern uint8_t __attribute__((aligned(4))) uart_txdmabuff[UART_BUFF_LEN];
extern uint8_t __attribute__((aligned(4))) uart_rxdmabuff[UART_BUFF_LEN];
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_uart_init(uint8_t reg_idx, UART_InitCfg_t *uart_cfg);
void xc_uart_enable_rx_it(uint8_t reg_idx);
void xc_uart_disable_rx_it(uint8_t reg_idx);
void xc_uart_send_byte(uint8_t reg_idx, uint8_t byte);
void xc_uart_send_data(uint8_t reg_idx, uint8_t *data, uint16_t len);
uint16_t xc_uart_receive_data(uint8_t reg_idx, uint8_t *data);
void xc_uart_register_receive_cb(uart_handler_callback uart_cb);
#endif /* __XC6xxx_HAL_UART_H__ */
@@ -0,0 +1,203 @@
/*!
* \file xc_drv_uart_dma.c
*
* \brief Target xinchip uart dma driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_uart_dma.h"
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
volatile bool uart0_tx_tfr_flag = true;
volatile bool uart1_tx_tfr_flag = true;
static volatile bool err_flag = false;
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void uart0_tx_callback(uint8_t eCode)
{
xc_dma_disable( );
uart0_tx_tfr_flag = true;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void uart1_tx_callback(uint8_t eCode)
{
xc_dma_disable( );
uart1_tx_tfr_flag = true;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void uartx_dma_tx_err(uint8_t eCode)
{
// -------
// This function is called by the IRQ handler.
// We use this function to deal with interrupts that the DMA
// driver is unable to cater for (these are application
// specific). All of the interrupts handled by this function
// are cleared by the DMA driver, so there's no need to clear here.
// -------
// Check the source of the interrupt
if(eCode == DMA_IRQ_ERR) {
// Just inform the application that this interrupt has occured.
err_flag = true;
}
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
uint8_t xc_uart_dma_tx_config(uint8_t uart_idx, eDMA_Ch_Num ch_num, uint16_t blockSize, uint8_t *tx_buff)
{
DMA_Chx_Cfg_t ch_cfg;
uint8_t errorCode = DMA_OK;
uint32_t uart_prf_addr = 0;
if(uart_idx == UART2_IDX) {
errorCode = DMA_EPERM;
return errorCode;
}
if(uart_idx == UART0_IDX) {
uart_prf_addr = XC_REG_UART_BASE_ADDR;
} else if(uart_idx == UART1_IDX) {
uart_prf_addr = XC_REG_UART_BASE_ADDR + uart_offset[uart_idx];
}
ch_cfg.sar = (uint32_t)tx_buff;
ch_cfg.dar = (uint32_t)uart_prf_addr;
ch_cfg.ctl_src_msize = DMA_MSIZE_1;//DMAC_MSIZE_4;//DMAC_MSIZE_1;
ch_cfg.ctl_dst_msize = DMA_MSIZE_1;//DMAC_MSIZE_4;//DMAC_MSIZE_1;
ch_cfg.ctl_sinc = DMA_ADDR_INCREMENT;
ch_cfg.ctl_dinc = DMA_ADDR_NOCHANGE;
ch_cfg.ctl_src_tr_width = DMA_TRANS_WIDTH_8;
ch_cfg.ctl_dst_tr_width = DMA_TRANS_WIDTH_8;
ch_cfg.ctl_tt_fc = DMA_MEM2PRF_DMA;
ch_cfg.ctl_block_ts = blockSize;
ch_cfg.cfg_hs_sel_src = DMA_HS_HARDWARE;
ch_cfg.cfg_hs_sel_dst = DMA_HS_HARDWARE;
ch_cfg.cfg_fifo_mode = DMA_FIFO_MODE_SINGLE;
if(uart_idx == UART0_IDX)
ch_cfg.cfg_dst_per = UART0_DMA_TX_HS_IF0;
else if(uart_idx == UART1_IDX)
ch_cfg.cfg_dst_per = UART1_DMA_TX_HS_IF1;
// ch_cfg.cfg_ch_prior = DMAC_PRIORITY_0;
// Now we can intialise the channel configuration structure for
// DMA channel 0 by loading the structure members with the
// contents of the DMAC's channel 0 registers.
errorCode = xc_dma_set_channel_config(ch_num, &ch_cfg);
if(errorCode != 0) {
DEBUG("\nERROR: Failed to initialise configuration\n");
}
xc_dma_set_listener(ch_num, uartx_dma_tx_err);
return errorCode;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_uart_dma_tx_init(uint8_t uart_idx, uint16_t tx_size, uint8_t *tx_buff)
{
xc_dma_init( );
uint8_t errorCode = xc_uart_dma_tx_config(uart_idx, DMA_CHANNEL1, tx_size, tx_buff);
if(errorCode != 0) {
DEBUG("\nERROR: Failed XC_UART_DMA_TX_CONFIG\n");
}
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
****************************************************************************************
*/
void xc_uart_dma_send(uint8_t uart_idx)
{
uint8_t errorCode;
xc_dma_enable( );
if(uart_idx == UART0_IDX) {
uart0_tx_tfr_flag = false;
errorCode = xc_dma_start_transfer(DMA_CHANNEL1, uart0_tx_callback);
} else if(uart_idx == UART1_IDX) {
uart1_tx_tfr_flag = false;
errorCode = xc_dma_start_transfer(DMA_CHANNEL1, uart1_tx_callback);
}
if(errorCode != 0) {
DEBUG("\nERROR: Failed Uart DMA_StartTransfer Tx\n");
}
}
@@ -0,0 +1,45 @@
/*!
* \file xc_drv_uart_dma.h
*
* \brief The header of xc_drv_uart_dma.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
#ifndef __XC_DRV_UART_DMA_H__
#define __XC_DRV_UART_DMA_H__
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_dma.h"
/*------------------------------------------------------------------------------------
Global Variables
-------------------------------------------------------------------------------------*/
extern volatile bool uart0_tx_tfr_flag;
extern volatile bool uart1_tx_tfr_flag;
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_uart_dma_tx_init(uint8_t uart_idx, uint16_t tx_size, uint8_t *tx_buff);
void xc_uart_dma_send(uint8_t uart_idx);
#endif /* __XC_DRV_UART_DMA_H__ */
@@ -0,0 +1,102 @@
/*!
* \file xc6xxx_hal_wdt.c
*
* \brief Target xc6xxx hal wdt implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*------------------------------------------------------------------------------------
INCLUDE HEADE FILES
--------------------------------------------------------------------------------------*/
#include "xc_drv_wdt.h"
#if (WDT_ON)
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
static uint8_t reload_val ;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_wdt_init(WDT_InitCfg_t *wdt_cfg)
{
cpr_ctlapbclken_grctl__wdt_pclk_en__setf(ENABLE);
cpr_rstctl_ctlapb_sw__wdt_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_ctlapb_sw__wdt_rstn__setf(RSTCTL_DISABLE);
/*
SYS_DISABLE | M0_ENABLE : SYS RST, for low-power reset or quick system reset;
SYS_ENABLE | M0_DISABLE: M0 RST, only for m0 reset;
SYS_DISABLE | M0_DISABLE: M0 RST, m0 reset and low-power reset;
*/
cpr_rstctl_wdtrst_mask_set(
(WDT_SYS_RSTN_MASK_DISABLE | WDT_M0_RSTN_MASK_ENABLE));
cpr_lp_ctl__wdt_pclk_sel__setf(wdt_cfg->PclkSel);
cpr_lp_ctl__wdt_tclk_en__setf(ENABLE);
wdt_cr__wdt_rmod__setf(wdt_cfg->WorkMode);
wdt_torr__wdt_top__setf(wdt_cfg->ReloadValue);
reload_val = wdt_cfg->ReloadValue;
}
void xc_wdt_start(void)
{
wdt_cr__wdt_rpl__setf(WDT_CR_RPL_4PCLK);
wdt_cr__wdt_en__setf(ENABLE);
wdt_crr__setf(WDT_CRR_CRR_ENABLE);
cpr_ctlapbclken_grctl__wdt_pclk_en__setf(DISABLE);
}
void xc_wdt_stop(void)
{
wdt_cr__wdt_en__setf(DISABLE);
}
void xc_wdt_refresh(void)
{
cpr_ctlapbclken_grctl__wdt_pclk_en__setf(ENABLE);
uint8_t val = wdt_icr_get();
wdt_torr__wdt_top__setf(val);
cpr_ctlapbclken_grctl__wdt_pclk_en__setf(DISABLE);
}
void xc_wdt_reload(void)
{
cpr_ctlapbclken_grctl__wdt_pclk_en__setf(ENABLE);
uint8_t val = wdt_icr_get();
wdt_torr__wdt_top__setf(reload_val);
wdt_crr__setf(WDT_CRR_CRR_ENABLE);
cpr_ctlapbclken_grctl__wdt_pclk_en__setf(DISABLE);
}
void WDT_Handler()
{
DEBUG("WDT_Handler\n");
xc_wdt_refresh();
}
#endif //(WDT_ON)
@@ -0,0 +1,287 @@
/*!
* \file xc6xxx_hal_wdt.h
*
* \brief The header of xc6xxx_hal_wdt.c
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __XC_DRV_WDT_H_
#define __XC_DRV_WDT_H_
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc6xxx.h"
#define WDT_SYS_RSTN_MASK_DISABLE (0x00)
#define WDT_SYS_RSTN_MASK_ENABLE (0x01)
#define WDT_M0_RSTN_MASK_ENABLE (0x02)
#define WDT_M0_RSTN_MASK_DISABLE (0x00)
#define WDT_CR_RPL_2PCLK (0UL)
#define WDT_CR_RPL_4PCLK (1UL)
#define WDT_CR_RPL_8PCLK (2UL)
#define WDT_CR_RPL_16PCLK (3UL)
#define WDT_CR_RPL_32PCLK (4UL)
#define WDT_CR_RPL_64PCLK (5UL)
#define WDT_CR_RPL_128PCLK (6UL)
#define WDT_CR_RPL_256PCLK (7UL)
#define WDT_CRR_CRR_ENABLE (0x76UL)
#define WDT_CLK_32K_RESET_MODE0_2048MS 0x00
#define WDT_CLK_32K_RESET_MODE0_4096MS 0x01
#define WDT_CLK_32K_RESET_MODE0_8192MS 0x02
#define WDT_CLK_32K_RESET_MODE0_16384MS 0x03
#define WDT_CLK_32K_RESET_MODE0_32768MS 0x04
#define WDT_CLK_32K_RESET_MODE0_65536MS 0x05
#define WDT_CLK_32K_RESET_MODE0_131072MS 0x06
#define WDT_CLK_32K_RESET_MODE0_262144MS 0x07
#define WDT_CLK_32K_RESET_MODE0_524288MS 0x08
#define WDT_CLK_32K_RESET_MODE0_1048576MS 0x09
#define WDT_CLK_32K_RESET_MODE0_2097152MS 0x0a
#define WDT_CLK_32K_RESET_MODE0_4194304MS 0x0b
#define WDT_CLK_32K_RESET_MODE0_8388608MS 0x0c
#define WDT_CLK_32K_RESET_MODE0_16777216MS 0x0d
#define WDT_CLK_32K_RESET_MODE0_33554432MS 0x0e
#define WDT_CLK_32K_RESET_MODE0_67108864MS 0x0f
#define WDT_CLK_16M_RESET_MODE0_8192US 0x00
#define WDT_CLK_16M_RESET_MODE0_16384US 0x01
#define WDT_CLK_16M_RESET_MODE0_32768US 0x02
#define WDT_CLK_16M_RESET_MODE0_65536US 0x03
#define WDT_CLK_16M_RESET_MODE0_131072US 0x04
#define WDT_CLK_16M_RESET_MODE0_262144US 0x05
#define WDT_CLK_16M_RESET_MODE0_524288US 0x06
#define WDT_CLK_16M_RESET_MODE0_1048576US 0x07
#define WDT_CLK_16M_RESET_MODE0_2097152US 0x08
#define WDT_CLK_16M_RESET_MODE0_4194304US 0x09
#define WDT_CLK_16M_RESET_MODE0_8388608US 0x0a
#define WDT_CLK_16M_RESET_MODE0_16777216US 0x0b
#define WDT_CLK_16M_RESET_MODE0_33554432US 0x0c
#define WDT_CLK_16M_RESET_MODE0_67108864US 0x0d
#define WDT_CLK_16M_RESET_MODE0_134217728US 0x0e
#define WDT_CLK_16M_RESET_MODE0_268435456US 0x0f
#define WDT_CLK_32M_RESET_MODE0_4096US 0x00
#define WDT_CLK_32M_RESET_MODE0_8192US 0x01
#define WDT_CLK_32M_RESET_MODE0_16384US 0x02
#define WDT_CLK_32M_RESET_MODE0_32768US 0x03
#define WDT_CLK_32M_RESET_MODE0_65536US 0x04
#define WDT_CLK_32M_RESET_MODE0_131072US 0x05
#define WDT_CLK_32M_RESET_MODE0_262144US 0x06
#define WDT_CLK_32M_RESET_MODE0_524288US 0x07
#define WDT_CLK_32M_RESET_MODE0_1048576US 0x08
#define WDT_CLK_32M_RESET_MODE0_2097152US 0x09
#define WDT_CLK_32M_RESET_MODE0_4194304US 0x0a
#define WDT_CLK_32M_RESET_MODE0_8388608US 0x0b
#define WDT_CLK_32M_RESET_MODE0_16777216US 0x0c
#define WDT_CLK_32M_RESET_MODE0_33554432US 0x0d
#define WDT_CLK_32M_RESET_MODE0_67108864US 0x0e
#define WDT_CLK_32M_RESET_MODE0_134217728US 0x0f
#define WDT_CLK_48M_RESET_MODE0_2731US 0x00
#define WDT_CLK_48M_RESET_MODE0_5461US 0x01
#define WDT_CLK_48M_RESET_MODE0_10923US 0x02
#define WDT_CLK_48M_RESET_MODE0_21845US 0x03
#define WDT_CLK_48M_RESET_MODE0_43691US 0x04
#define WDT_CLK_48M_RESET_MODE0_87381US 0x05
#define WDT_CLK_48M_RESET_MODE0_174763US 0x06
#define WDT_CLK_48M_RESET_MODE0_349525US 0x07
#define WDT_CLK_48M_RESET_MODE0_699051US 0x08
#define WDT_CLK_48M_RESET_MODE0_1398101US 0x09
#define WDT_CLK_48M_RESET_MODE0_2796203US 0x0a
#define WDT_CLK_48M_RESET_MODE0_5592405US 0x0b
#define WDT_CLK_48M_RESET_MODE0_11184811US 0x0c
#define WDT_CLK_48M_RESET_MODE0_22369621US 0x0d
#define WDT_CLK_48M_RESET_MODE0_44739243US 0x0e
#define WDT_CLK_48M_RESET_MODE0_89478485US 0x0f
#define WDT_CLK_64M_RESET_MDOE0_2048US 0x00
#define WDT_CLK_64M_RESET_MDOE0_4096US 0x01
#define WDT_CLK_64M_RESET_MDOE0_8192US 0x02
#define WDT_CLK_64M_RESET_MDOE0_16384US 0x03
#define WDT_CLK_64M_RESET_MDOE0_32768US 0x04
#define WDT_CLK_64M_RESET_MDOE0_65536US 0x05
#define WDT_CLK_64M_RESET_MDOE0_131072US 0x06
#define WDT_CLK_64M_RESET_MDOE0_262144US 0x07
#define WDT_CLK_64M_RESET_MDOE0_524288US 0x08
#define WDT_CLK_64M_RESET_MDOE0_1048576US 0x09
#define WDT_CLK_64M_RESET_MDOE0_2097152US 0x0a
#define WDT_CLK_64M_RESET_MDOE0_4194304US 0x0b
#define WDT_CLK_64M_RESET_MDOE0_8388608US 0x0c
#define WDT_CLK_64M_RESET_MDOE0_16777216US 0x0d
#define WDT_CLK_64M_RESET_MDOE0_33554432US 0x0e
#define WDT_CLK_64M_RESET_MDOE0_67108864US 0x0f
#define WDT_CLK_32K_RESET_MODE1_4096MS 0x00
#define WDT_CLK_32K_RESET_MODE1_8192MS 0x01
#define WDT_CLK_32K_RESET_MODE1_16384MS 0x02
#define WDT_CLK_32K_RESET_MODE1_32768MS 0x03
#define WDT_CLK_32K_RESET_MODE1_65536MS 0x04
#define WDT_CLK_32K_RESET_MODE1_131072MS 0x05
#define WDT_CLK_32K_RESET_MODE1_262144MS 0x06
#define WDT_CLK_32K_RESET_MODE1_524288MS 0x07
#define WDT_CLK_32K_RESET_MODE1_1048576MS 0x08
#define WDT_CLK_32K_RESET_MODE1_2097152MS 0x09
#define WDT_CLK_32K_RESET_MODE1_4194304MS 0x0a
#define WDT_CLK_32K_RESET_MODE1_8388608MS 0x0b
#define WDT_CLK_32K_RESET_MODE1_16777216MS 0x0c
#define WDT_CLK_32K_RESET_MODE1_33554432MS 0x0d
#define WDT_CLK_32K_RESET_MODE1_67108864MS 0x0e
#define WDT_CLK_32K_RESET_MODE1_134217728MS 0x0f
#define WDT_CLK_16M_RESET_MODE1_16384US 0x00
#define WDT_CLK_16M_RESET_MODE1_32768US 0x01
#define WDT_CLK_16M_RESET_MODE1_65536US 0x02
#define WDT_CLK_16M_RESET_MODE1_131072US 0x03
#define WDT_CLK_16M_RESET_MODE1_262144US 0x04
#define WDT_CLK_16M_RESET_MODE1_524288US 0x05
#define WDT_CLK_16M_RESET_MODE1_1048576US 0x06
#define WDT_CLK_16M_RESET_MODE1_2097152US 0x07
#define WDT_CLK_16M_RESET_MODE1_4194304US 0x08
#define WDT_CLK_16M_RESET_MODE1_8388608US 0x09
#define WDT_CLK_16M_RESET_MODE1_16777216US 0x0a
#define WDT_CLK_16M_RESET_MODE1_33554432US 0x0b
#define WDT_CLK_16M_RESET_MODE1_67108864US 0x0c
#define WDT_CLK_16M_RESET_MODE1_134217728US 0x0d
#define WDT_CLK_16M_RESET_MODE1_268435456US 0x0e
#define WDT_CLK_16M_RESET_MODE1_536870912US 0x0f
#define WDT_CLK_32M_RESET_MODE1_8192US 0x00
#define WDT_CLK_32M_RESET_MODE1_16384US 0x01
#define WDT_CLK_32M_RESET_MODE1_32768US 0x02
#define WDT_CLK_32M_RESET_MODE1_65536US 0x03
#define WDT_CLK_32M_RESET_MODE1_131072US 0x04
#define WDT_CLK_32M_RESET_MODE1_262144US 0x05
#define WDT_CLK_32M_RESET_MODE1_524288US 0x06
#define WDT_CLK_32M_RESET_MODE1_1048576US 0x07
#define WDT_CLK_32M_RESET_MODE1_2097152US 0x08
#define WDT_CLK_32M_RESET_MODE1_4194304US 0x09
#define WDT_CLK_32M_RESET_MODE1_8388608US 0x0a
#define WDT_CLK_32M_RESET_MODE1_16777216US 0x0b
#define WDT_CLK_32M_RESET_MODE1_33554432US 0x0c
#define WDT_CLK_32M_RESET_MODE1_67108864US 0x0d
#define WDT_CLK_32M_RESET_MODE1_134217728US 0x0e
#define WDT_CLK_32M_RESET_MODE1_268435456US 0x0f
#define WDT_CLK_48M_RESET_MODE1_5461US 0x00
#define WDT_CLK_48M_RESET_MODE1_10923US 0x01
#define WDT_CLK_48M_RESET_MODE1_21845US 0x02
#define WDT_CLK_48M_RESET_MODE1_43691US 0x03
#define WDT_CLK_48M_RESET_MODE1_87381US 0x04
#define WDT_CLK_48M_RESET_MODE1_174763US 0x05
#define WDT_CLK_48M_RESET_MODE1_349525US 0x06
#define WDT_CLK_48M_RESET_MODE1_699051US 0x07
#define WDT_CLK_48M_RESET_MODE1_1398101US 0x08
#define WDT_CLK_48M_RESET_MODE1_2796203US 0x09
#define WDT_CLK_48M_RESET_MODE1_5592405US 0x0a
#define WDT_CLK_48M_RESET_MODE1_11184811US 0x0b
#define WDT_CLK_48M_RESET_MODE1_22369621US 0x0c
#define WDT_CLK_48M_RESET_MODE1_44739243US 0x0d
#define WDT_CLK_48M_RESET_MODE1_89478485US 0x0e
#define WDT_CLK_48M_RESET_MODE1_178956971US 0x0f
#define WDT_CLK_64M_RESET_MODE1_4096US 0x00
#define WDT_CLK_64M_RESET_MODE1_8192US 0x01
#define WDT_CLK_64M_RESET_MODE1_16384US 0x02
#define WDT_CLK_64M_RESET_MODE1_32768US 0x03
#define WDT_CLK_64M_RESET_MODE1_65536US 0x04
#define WDT_CLK_64M_RESET_MODE1_131072US 0x05
#define WDT_CLK_64M_RESET_MODE1_262144US 0x06
#define WDT_CLK_64M_RESET_MODE1_524288US 0x07
#define WDT_CLK_64M_RESET_MODE1_1048576US 0x08
#define WDT_CLK_64M_RESET_MODE1_2097152US 0x09
#define WDT_CLK_64M_RESET_MODE1_4194304US 0x0a
#define WDT_CLK_64M_RESET_MODE1_8388608US 0x0b
#define WDT_CLK_64M_RESET_MODE1_16777216US 0x0c
#define WDT_CLK_64M_RESET_MODE1_33554432US 0x0d
#define WDT_CLK_64M_RESET_MODE1_67108864US 0x0e
#define WDT_CLK_64M_RESET_MODE1_134217728US 0x0f
/*------------------------------------------------------------------------------------
TypeDef
-------------------------------------------------------------------------------------*/
typedef enum
{
WDT_WORK_MODE0,
WDT_WORK_MODE1
} WDT_WorkModeTypeDef;
typedef enum
{
WDT_ReloadValue_0xFFFF = 0,
WDT_ReloadValue_0x1FFFF,
WDT_ReloadValue_0x3FFFF,
WDT_ReloadValue_0x7FFFF,
WDT_ReloadValue_0xFFFFF, // In xip mode with external 32k crystal
// oscillator, watchdog reset value can only
// start from here
WDT_ReloadValue_0x1FFFFF,
WDT_ReloadValue_0x3FFFFF,
WDT_ReloadValue_0x7FFFFF,
WDT_ReloadValue_0xFFFFFF,
WDT_ReloadValue_0x1FFFFFF,
WDT_ReloadValue_0x3FFFFFF,
WDT_ReloadValue_0x7FFFFFF,
WDT_ReloadValue_0xFFFFFFF,
WDT_ReloadValue_0x1FFFFFFF,
WDT_ReloadValue_0x3FFFFFFF,
WDT_ReloadValue_0x7FFFFFFF,
} WDT_ReloadValueTypeDef;
typedef enum
{
WDT_WORK_32M,
WDT_WORK_32K,
} WDT_WorkSrcTypeDef;
typedef struct
{
WDT_ReloadValueTypeDef ReloadValue;
WDT_WorkModeTypeDef WorkMode;
WDT_WorkSrcTypeDef PclkSel;
} WDT_InitCfg_t;
/*------------------------------------------------------------------------------------
Inline Functions
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Exported Functions
-------------------------------------------------------------------------------------*/
void xc_wdt_init(WDT_InitCfg_t *wdt_cfg);
void xc_wdt_start(void);
void xc_wdt_stop(void);
void xc_wdt_refresh(void);
void xc_wdt_reload(void);
#endif /* __XC6xxx_HAL_WDT_H_ */