Update the SmartFusion SoftConsole source code to be the same as the IAR and Keil versions.
parent
2aef3e3cfe
commit
eadd0048c4
File diff suppressed because it is too large
Load Diff
@ -1,306 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* (c) Copyright 2009 Actel Corporation. All rights reserved.
|
||||
*
|
||||
* SVN $Revision: 2905 $
|
||||
* SVN $Date: 2010-08-20 14:03:28 +0100 (Fri, 20 Aug 2010) $
|
||||
*/
|
||||
#include "mss_ace.h"
|
||||
#include "mss_ace_configurator.h"
|
||||
#include "../../drivers_config/mss_ace/ace_handles.h"
|
||||
#include "../../drivers_config/mss_ace/ace_config.h"
|
||||
|
||||
#include "../../CMSIS/a2fxxxm3.h"
|
||||
#include "../../CMSIS/mss_assert.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SSE_START 1uL
|
||||
#define SSE_STOP 0uL
|
||||
|
||||
#define NB_OF_ANALOG_BLOCKS 3u
|
||||
#define SEE_RAM_WORD_SIZE 512
|
||||
|
||||
#define TS_ENABLE_MASK 0x01u
|
||||
#define PPE_ENABLE_MASK 0x01u
|
||||
#define ADC_RESET_MASK 0x10u
|
||||
#define ADC_FIFO_CLR_MASK 0x04u
|
||||
#define PDMA_DATAOUT_CLR_MASK 0x04u
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
extern ace_procedure_desc_t g_sse_sequences_desc_table[ACE_NB_OF_SSE_PROCEDURES];
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
sse_sequence_handle_t
|
||||
ACE_get_sse_seq_handle
|
||||
(
|
||||
const uint8_t * p_sz_sequence_name
|
||||
)
|
||||
{
|
||||
uint16_t seq_idx;
|
||||
sse_sequence_handle_t handle = INVALID_SSE_SEQ_HANDLE;
|
||||
|
||||
for ( seq_idx = 0u; seq_idx < (uint32_t)ACE_NB_OF_SSE_PROCEDURES; ++seq_idx )
|
||||
{
|
||||
if ( g_sse_sequences_desc_table[seq_idx].p_sz_proc_name != 0 )
|
||||
{
|
||||
int32_t diff;
|
||||
diff = strncmp( (const char *)p_sz_sequence_name, (const char *)g_sse_sequences_desc_table[seq_idx].p_sz_proc_name, MAX_PROCEDURE_NAME_LENGTH );
|
||||
if ( 0 == diff )
|
||||
{
|
||||
/* channel name found. */
|
||||
handle = seq_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
static uint32_t volatile * const sse_pc_ctrl_lut[NB_OF_ANALOG_BLOCKS] =
|
||||
{
|
||||
&ACE->PC0_CTRL,
|
||||
&ACE->PC1_CTRL,
|
||||
&ACE->PC2_CTRL
|
||||
};
|
||||
|
||||
static uint32_t volatile * const sse_pc_lo_lut[NB_OF_ANALOG_BLOCKS] =
|
||||
{
|
||||
&ACE->PC0_LO,
|
||||
&ACE->PC1_LO,
|
||||
&ACE->PC2_LO
|
||||
};
|
||||
|
||||
static uint32_t volatile * const sse_pc_hi_lut[NB_OF_ANALOG_BLOCKS] =
|
||||
{
|
||||
&ACE->PC0_HI,
|
||||
&ACE->PC1_HI,
|
||||
&ACE->PC2_HI
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_load_sse
|
||||
(
|
||||
sse_sequence_handle_t sequence
|
||||
)
|
||||
{
|
||||
ASSERT( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES );
|
||||
|
||||
if ( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES )
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t offset;
|
||||
const uint16_t * p_ucode;
|
||||
|
||||
ASSERT( g_sse_sequences_desc_table[sequence].sse_pc_id < NB_OF_ANALOG_BLOCKS );
|
||||
|
||||
if ( g_sse_sequences_desc_table[sequence].sse_pc_id < NB_OF_ANALOG_BLOCKS )
|
||||
{
|
||||
/* Stop relevant program counter. */
|
||||
*sse_pc_ctrl_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = SSE_STOP;
|
||||
|
||||
/* Load microcode into SEE RAM.*/
|
||||
p_ucode = g_sse_sequences_desc_table[sequence].sse_ucode;
|
||||
offset = g_sse_sequences_desc_table[sequence].sse_load_offset;
|
||||
|
||||
for ( i = 0u; i < g_sse_sequences_desc_table[sequence].sse_ucode_length; ++i )
|
||||
{
|
||||
ACE->SSE_RAM_DATA[offset + i] = (uint32_t)*p_ucode;
|
||||
++p_ucode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_start_sse
|
||||
(
|
||||
sse_sequence_handle_t sequence
|
||||
)
|
||||
{
|
||||
ASSERT( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES );
|
||||
|
||||
if ( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES )
|
||||
{
|
||||
uint16_t pc;
|
||||
|
||||
ASSERT( g_sse_sequences_desc_table[sequence].sse_pc_id < NB_OF_ANALOG_BLOCKS );
|
||||
ASSERT( g_sse_sequences_desc_table[sequence].sse_load_offset < SEE_RAM_WORD_SIZE );
|
||||
|
||||
pc = g_sse_sequences_desc_table[sequence].sse_load_offset;
|
||||
|
||||
if ( pc < 256u )
|
||||
{
|
||||
*sse_pc_lo_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = pc;
|
||||
}
|
||||
else
|
||||
{
|
||||
*sse_pc_hi_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = pc - 256;
|
||||
}
|
||||
|
||||
*sse_pc_ctrl_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = SSE_START;
|
||||
|
||||
/* Enable Sample Sequencing Engine in case it was not done as part of
|
||||
* system boot. */
|
||||
ACE->SSE_TS_CTRL |= TS_ENABLE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_restart_sse
|
||||
(
|
||||
sse_sequence_handle_t sequence
|
||||
)
|
||||
{
|
||||
ASSERT( sequence < ACE_NB_OF_SSE_PROCEDURES );
|
||||
ASSERT( g_sse_sequences_desc_table[sequence].sse_pc_id < NB_OF_ANALOG_BLOCKS );
|
||||
ASSERT( g_sse_sequences_desc_table[sequence].sse_load_offset < SEE_RAM_WORD_SIZE );
|
||||
|
||||
if ( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES )
|
||||
{
|
||||
uint16_t pc;
|
||||
|
||||
pc = g_sse_sequences_desc_table[sequence].sse_loop_pc;
|
||||
|
||||
if ( pc < 256u )
|
||||
{
|
||||
*sse_pc_lo_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = pc;
|
||||
}
|
||||
else
|
||||
{
|
||||
*sse_pc_hi_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = pc - 256;
|
||||
}
|
||||
|
||||
*sse_pc_ctrl_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = SSE_START;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_stop_sse
|
||||
(
|
||||
sse_sequence_handle_t sequence
|
||||
)
|
||||
{
|
||||
ASSERT( sequence < ACE_NB_OF_SSE_PROCEDURES );
|
||||
|
||||
if ( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES )
|
||||
{
|
||||
/* Stop relevant program counter. */
|
||||
*sse_pc_ctrl_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = SSE_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_resume_sse
|
||||
(
|
||||
sse_sequence_handle_t sequence
|
||||
)
|
||||
{
|
||||
ASSERT( sequence < ACE_NB_OF_SSE_PROCEDURES );
|
||||
|
||||
if ( sequence < (sse_sequence_handle_t)ACE_NB_OF_SSE_PROCEDURES )
|
||||
{
|
||||
*sse_pc_ctrl_lut[g_sse_sequences_desc_table[sequence].sse_pc_id] = SSE_START;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_enable_sse_irq
|
||||
(
|
||||
sse_irq_id_t sse_irq_id
|
||||
)
|
||||
{
|
||||
ASSERT( sse_irq_id < NB_OF_SSE_FLAG_IRQS );
|
||||
|
||||
ACE->SSE_IRQ_EN |= 1uL << (uint32_t)sse_irq_id;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_disable_sse_irq
|
||||
(
|
||||
sse_irq_id_t sse_irq_id
|
||||
)
|
||||
{
|
||||
ASSERT( sse_irq_id < NB_OF_SSE_FLAG_IRQS );
|
||||
|
||||
ACE->SSE_IRQ_EN &= (uint32_t)~(1uL << (uint32_t)sse_irq_id);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_clear_sse_irq
|
||||
(
|
||||
sse_irq_id_t sse_irq_id
|
||||
)
|
||||
{
|
||||
ASSERT( sse_irq_id < NB_OF_SSE_FLAG_IRQS );
|
||||
|
||||
ACE->SSE_IRQ_CLR |= 1uL << (uint32_t)sse_irq_id;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
void ACE_clear_sample_pipeline(void)
|
||||
{
|
||||
uint32_t saved_sse_ctrl;
|
||||
uint32_t saved_ppe_ctrl;
|
||||
|
||||
/* Pause the Sample Sequencing Engine. */
|
||||
saved_sse_ctrl = ACE->SSE_TS_CTRL;
|
||||
ACE->SSE_TS_CTRL = ACE->SSE_TS_CTRL & ~((uint32_t)TS_ENABLE_MASK);
|
||||
|
||||
/* Pause the Post Processing Engine. */
|
||||
saved_ppe_ctrl = ACE->PPE_CTRL;
|
||||
ACE->PPE_CTRL = ACE->PPE_CTRL & ~((uint32_t)PPE_ENABLE_MASK);
|
||||
|
||||
/* Reset the ADCs */
|
||||
ACE->ADC0_MISC_CTRL |= ADC_RESET_MASK;
|
||||
ACE->ADC1_MISC_CTRL |= ADC_RESET_MASK;
|
||||
ACE->ADC2_MISC_CTRL |= ADC_RESET_MASK;
|
||||
|
||||
/* Clear ADC FIFOs */
|
||||
ACE->ADC0_FIFO_CTRL |= ADC_FIFO_CLR_MASK;
|
||||
ACE->ADC1_FIFO_CTRL |= ADC_FIFO_CLR_MASK;
|
||||
ACE->ADC2_FIFO_CTRL |= ADC_FIFO_CLR_MASK;
|
||||
|
||||
/* clear DMA FIFOs */
|
||||
ACE->PPE_PDMA_CTRL |= PDMA_DATAOUT_CLR_MASK;
|
||||
|
||||
/* Unpause the Post Processing Engine. */
|
||||
ACE->PPE_CTRL = saved_ppe_ctrl;
|
||||
|
||||
/* Unpause the Sample Sequencing Engine. */
|
||||
ACE->SSE_TS_CTRL = saved_sse_ctrl;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,467 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* (c) Copyright 2010 Actel Corporation. All rights reserved.
|
||||
*
|
||||
* This file contains the implementation of the functions used to dynamically
|
||||
* control the linear transforms applied by the ACE post processing engine to
|
||||
* the samples read from the SSE.
|
||||
*
|
||||
* SVN $Revision: 2908 $
|
||||
* SVN $Date: 2010-08-20 16:01:28 +0100 (Fri, 20 Aug 2010) $
|
||||
*/
|
||||
|
||||
#include "mss_ace.h"
|
||||
#include "mss_ace_configurator.h"
|
||||
#include "mtd_data.h"
|
||||
#include "envm_layout.h"
|
||||
#include "../../CMSIS/a2fxxxm3.h"
|
||||
#include "../../CMSIS/mss_assert.h"
|
||||
#include "../../drivers_config/mss_ace/ace_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The ACE_set_linear_transform() is only available when using ACE configuration
|
||||
* files generated by Libero 9.1 or later.
|
||||
*/
|
||||
#ifdef ACE_CFG_DATA_FORMAT_VERSION
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Masks ans shift values used to derive the ABPS ranges from the analog block
|
||||
* configuration.
|
||||
*/
|
||||
#define ABPS1_CFG_BITS_MASK (uint32_t)0x06
|
||||
#define ABPS1_CFG_BITS_SHIFT (uint32_t)1
|
||||
|
||||
#define ABPS2_CFG_BITS_MASK (uint32_t)0x60
|
||||
#define ABPS2_CFG_BITS_SHIFT (uint32_t)5
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* One Bit DAC definitions.
|
||||
*/
|
||||
#define OBD_CURRENT (uint32_t)1
|
||||
#define OBD_VOLTAGE (uint32_t)0
|
||||
|
||||
#define OBD_MODE_MASK (uint32_t)0x01
|
||||
#define OBD_CHOPPING_MASK (uint32_t)0x02
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Neutral factor and offset for m*x + c trnasform.
|
||||
*/
|
||||
#define NEUTRAL_M_FACTOR 0x4000
|
||||
#define NEUTRAL_C_OFFSET 0x0000
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Enumearation of the various input channel types. This is used to differentiate
|
||||
between channel types in order to extract the relevant factory calibration
|
||||
data(m1 and c1).
|
||||
*/
|
||||
typedef enum channel_type
|
||||
{
|
||||
ABPS1_CHAN = 0,
|
||||
ABPS2_CHAN,
|
||||
CMB_CHAN,
|
||||
TMB_CHAN,
|
||||
DIRECT_ADC_INPUT_CHAN,
|
||||
OBDOUT_CHAN,
|
||||
FLOATING_CHAN
|
||||
} cal_channel_type_t;
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
This data structure is used to store factory calibration data for a specific
|
||||
analog input.
|
||||
*/
|
||||
typedef struct __channel_calibration_t
|
||||
{
|
||||
uint16_t mext;
|
||||
uint16_t m1;
|
||||
uint16_t c1;
|
||||
} channel_calibration_t;
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Local functions
|
||||
*/
|
||||
int32_t extend_sign
|
||||
(
|
||||
uint16_t x
|
||||
);
|
||||
|
||||
uint32_t adjust_to_24bit_ace_format
|
||||
(
|
||||
int64_t signed48
|
||||
);
|
||||
|
||||
uint32_t adjust_to_16bit_ace_format
|
||||
(
|
||||
int64_t signed48
|
||||
);
|
||||
|
||||
void get_calibration
|
||||
(
|
||||
adc_channel_id_t channel_id,
|
||||
channel_calibration_t * p_calibration
|
||||
);
|
||||
|
||||
void write_transform_coefficients
|
||||
(
|
||||
ace_channel_handle_t channel_handle,
|
||||
uint32_t m,
|
||||
uint32_t c
|
||||
);
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
|
||||
*/
|
||||
extern const uint8_t g_ace_external_varef_used[ACE_NB_OF_ADC];
|
||||
|
||||
extern ace_channel_desc_t g_ace_channel_desc_table[ACE_NB_OF_INPUT_CHANNELS];
|
||||
|
||||
extern const ppe_transforms_desc_t g_ace_ppe_transforms_desc_table[ACE_NB_OF_INPUT_CHANNELS];
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Pointer to the manufacturing test data containing trimming information
|
||||
* generated during manufacturing.
|
||||
*/
|
||||
static const mtd_data_t * const p_mtd_data = (mtd_data_t *)MTD_ADDRESS;
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
See "mss_ace.h" for details of how to use this function.
|
||||
*/
|
||||
int16_t ACE_get_default_m_factor
|
||||
(
|
||||
ace_channel_handle_t channel_handle
|
||||
)
|
||||
{
|
||||
ASSERT( channel_handle < NB_OF_ACE_CHANNEL_HANDLES );
|
||||
|
||||
return g_ace_ppe_transforms_desc_table[channel_handle].m_ppe_offset;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
See "mss_ace.h" for details of how to use this function.
|
||||
*/
|
||||
int16_t ACE_get_default_c_offset
|
||||
(
|
||||
ace_channel_handle_t channel_handle
|
||||
)
|
||||
{
|
||||
ASSERT( channel_handle < NB_OF_ACE_CHANNEL_HANDLES );
|
||||
|
||||
return g_ace_ppe_transforms_desc_table[channel_handle].c_ppe_offset;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
See "mss_ace.h" for details of how to use this function.
|
||||
|
||||
m = m2 * m1 * mext
|
||||
c = (m2 * c1 * mext) + (c2 * mext)
|
||||
*/
|
||||
void ACE_set_linear_transform
|
||||
(
|
||||
ace_channel_handle_t channel_handle,
|
||||
int16_t m2,
|
||||
int16_t c2
|
||||
)
|
||||
{
|
||||
adc_channel_id_t channel_id;
|
||||
uint32_t m;
|
||||
uint32_t c;
|
||||
int32_t m32;
|
||||
int64_t m64;
|
||||
int32_t c32;
|
||||
int64_t c64_1;
|
||||
int64_t c64_2;
|
||||
uint16_t m1;
|
||||
uint16_t c1;
|
||||
uint16_t mext;
|
||||
|
||||
channel_calibration_t calibration;
|
||||
|
||||
ASSERT( channel_handle < NB_OF_ACE_CHANNEL_HANDLES );
|
||||
|
||||
if(channel_handle < NB_OF_ACE_CHANNEL_HANDLES)
|
||||
{
|
||||
channel_id = g_ace_channel_desc_table[channel_handle].signal_id;
|
||||
|
||||
get_calibration(channel_id, &calibration);
|
||||
|
||||
m1 = calibration.m1;
|
||||
c1 = calibration.c1;
|
||||
|
||||
mext = calibration.mext;
|
||||
|
||||
/*
|
||||
* m = m2 * m1 * mext
|
||||
*/
|
||||
m32 = extend_sign(m2) * extend_sign(m1);
|
||||
m64 = (int64_t)m32 * extend_sign(mext);
|
||||
|
||||
/* Convert 48-bit result to 32-bit ACE format result. */
|
||||
m = adjust_to_16bit_ace_format(m64);
|
||||
|
||||
/*
|
||||
* c = (m2 * c1 * mext) + (c2 * mext)
|
||||
*/
|
||||
c32 = extend_sign(m2) * extend_sign(c1);
|
||||
c64_1 = (int64_t)c32 * extend_sign(mext);
|
||||
|
||||
c64_2 = ((int64_t)(extend_sign(c2) * extend_sign(mext))) << 14;
|
||||
|
||||
c = adjust_to_24bit_ace_format(c64_1 + c64_2);
|
||||
|
||||
write_transform_coefficients(channel_handle, m, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Extend 16-bit signed number to 32-bit signed number.
|
||||
*/
|
||||
int32_t extend_sign
|
||||
(
|
||||
uint16_t x
|
||||
)
|
||||
{
|
||||
int32_t y;
|
||||
const uint32_t sign_bit_mask = 0x00008000u;
|
||||
|
||||
y = (x ^ sign_bit_mask) - sign_bit_mask;
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Take a 48-bit signed number, adjust it for saturation in the range -8 to
|
||||
+7.999, translate into 24-bit ACE format.
|
||||
*/
|
||||
uint32_t adjust_to_24bit_ace_format
|
||||
(
|
||||
int64_t signed48
|
||||
)
|
||||
{
|
||||
int32_t ace24_format;
|
||||
const int64_t MAX_POSITIVE = 0x00001FFFFFFFFFFFuLL; /* +7.9999 */
|
||||
const int64_t MIN_NEGATIVE = 0xFFFF200000000000uLL; /* -8 */
|
||||
|
||||
/* Check saturation. */
|
||||
if(signed48 > MAX_POSITIVE)
|
||||
{
|
||||
signed48 = MAX_POSITIVE;
|
||||
}
|
||||
else if(signed48 < MIN_NEGATIVE)
|
||||
{
|
||||
signed48 = MIN_NEGATIVE;
|
||||
}
|
||||
|
||||
/* Adjust to 24-bit ACE format. */
|
||||
ace24_format = (uint32_t)(signed48 >> 14);
|
||||
|
||||
return ace24_format;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Take a 48-bit signed number, adjust it for saturation in the range -8 to
|
||||
+7.999, translate into 16-bit ACE format.
|
||||
*/
|
||||
uint32_t adjust_to_16bit_ace_format
|
||||
(
|
||||
int64_t signed48
|
||||
)
|
||||
{
|
||||
int32_t ace24_format;
|
||||
const int64_t MAX_POSITIVE = 0x00001FFFFFFFFFFFuLL; /* +7.9999 */
|
||||
const int64_t MIN_NEGATIVE = 0xFFFF200000000000uLL; /* -8 */
|
||||
|
||||
/* Check saturation. */
|
||||
if(signed48 > MAX_POSITIVE)
|
||||
{
|
||||
signed48 = MAX_POSITIVE;
|
||||
}
|
||||
else if(signed48 < MIN_NEGATIVE)
|
||||
{
|
||||
signed48 = MIN_NEGATIVE;
|
||||
}
|
||||
|
||||
/* Adjust to 24-bit ACE format. */
|
||||
ace24_format = (uint32_t)(signed48 >> 20);
|
||||
|
||||
return ace24_format;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
|
||||
*/
|
||||
void get_calibration
|
||||
(
|
||||
adc_channel_id_t channel_id,
|
||||
channel_calibration_t * p_calibration
|
||||
)
|
||||
{
|
||||
const uint32_t channel_mask = 0x0000000F;
|
||||
const uint32_t CMB_MUX_SEL_MASK = 0x01;
|
||||
const uint32_t TMB_MUX_SEL_MASK = 0x01;
|
||||
|
||||
const cal_channel_type_t channel_type_lut[16] =
|
||||
{
|
||||
FLOATING_CHAN,
|
||||
ABPS1_CHAN,
|
||||
ABPS2_CHAN,
|
||||
CMB_CHAN,
|
||||
TMB_CHAN,
|
||||
ABPS1_CHAN,
|
||||
ABPS2_CHAN,
|
||||
CMB_CHAN,
|
||||
TMB_CHAN,
|
||||
DIRECT_ADC_INPUT_CHAN,
|
||||
DIRECT_ADC_INPUT_CHAN,
|
||||
DIRECT_ADC_INPUT_CHAN,
|
||||
DIRECT_ADC_INPUT_CHAN,
|
||||
FLOATING_CHAN,
|
||||
FLOATING_CHAN,
|
||||
OBDOUT_CHAN
|
||||
};
|
||||
|
||||
cal_channel_type_t channel_type;
|
||||
uint32_t channel_nb;
|
||||
uint32_t adc_nb;
|
||||
uint32_t range;
|
||||
uint32_t quad_id;
|
||||
mtd_calibration_mc_t const * p_mc_coeff = 0;
|
||||
|
||||
channel_nb = channel_id & channel_mask;
|
||||
channel_type = channel_type_lut[channel_nb];
|
||||
adc_nb = ((uint32_t)channel_id & 0x30u) >> 4u;
|
||||
|
||||
quad_id = adc_nb * 2;
|
||||
|
||||
if ( (channel_nb > 4) && (channel_nb < 9) ) { ++quad_id; }
|
||||
|
||||
switch ( channel_type )
|
||||
{
|
||||
case ABPS1_CHAN:
|
||||
range = (ACE->ACB_DATA[quad_id].b8 & ABPS1_CFG_BITS_MASK) >> ABPS1_CFG_BITS_SHIFT;
|
||||
p_mc_coeff = &p_mtd_data->abps_calibration[quad_id][0][range];
|
||||
break;
|
||||
|
||||
case ABPS2_CHAN:
|
||||
range = (ACE->ACB_DATA[quad_id].b8 & ABPS2_CFG_BITS_MASK) >> ABPS2_CFG_BITS_SHIFT;
|
||||
p_mc_coeff = &p_mtd_data->abps_calibration[quad_id][1][range];
|
||||
break;
|
||||
|
||||
case CMB_CHAN:
|
||||
{
|
||||
uint32_t cmb_mux_sel = (uint32_t)ACE->ACB_DATA[quad_id].b9 & CMB_MUX_SEL_MASK;
|
||||
if ( cmb_mux_sel == 0 )
|
||||
{ /* current monitor */
|
||||
p_mc_coeff = &p_mtd_data->cm_calibration[quad_id];
|
||||
}
|
||||
else
|
||||
{ /* direct input */
|
||||
p_mc_coeff = &p_mtd_data->quads_direct_input_cal[quad_id][0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TMB_CHAN:
|
||||
{
|
||||
uint32_t tmb_mux_sel = (uint32_t)ACE->ACB_DATA[quad_id].b10 & TMB_MUX_SEL_MASK;
|
||||
if ( tmb_mux_sel == 0 )
|
||||
{ /* temperature monitor */
|
||||
p_mc_coeff = &p_mtd_data->tm_calibration[quad_id];
|
||||
}
|
||||
else
|
||||
{ /* direct input */
|
||||
p_mc_coeff = &p_mtd_data->quads_direct_input_cal[quad_id][1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DIRECT_ADC_INPUT_CHAN:
|
||||
{
|
||||
const uint32_t channel_to_direct_in_lut[16]
|
||||
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0};
|
||||
uint32_t direct_in_id;
|
||||
|
||||
direct_in_id = channel_to_direct_in_lut[channel_id & channel_mask];
|
||||
p_mc_coeff = &p_mtd_data->adc_direct_input_cal[adc_nb][direct_in_id];
|
||||
}
|
||||
break;
|
||||
|
||||
case OBDOUT_CHAN:
|
||||
{
|
||||
uint32_t obd_mode = (uint32_t)ACE->ACB_DATA[quad_id].b6 & OBD_MODE_MASK;
|
||||
uint32_t chopping_option = (uint32_t)ACE->ACB_DATA[quad_id].b6 & OBD_CHOPPING_MASK;
|
||||
if (obd_mode > 0)
|
||||
{
|
||||
obd_mode = 1;
|
||||
}
|
||||
if (chopping_option > 0)
|
||||
{
|
||||
chopping_option = 1;
|
||||
}
|
||||
p_mc_coeff = &p_mtd_data->obd_calibration[adc_nb][obd_mode][chopping_option];
|
||||
}
|
||||
break;
|
||||
|
||||
case FLOATING_CHAN:
|
||||
default:
|
||||
/* Give neutral values is invalid channel. */
|
||||
p_calibration->m1 = NEUTRAL_M_FACTOR;
|
||||
p_calibration->c1 = NEUTRAL_C_OFFSET;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p_mc_coeff != 0)
|
||||
{
|
||||
p_calibration->m1 = p_mc_coeff->m;
|
||||
p_calibration->c1 = p_mc_coeff->c;
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Retrieve the value of the mext factor. This depends if external VAREF is
|
||||
used by the ADC sampling the analog input channel.
|
||||
*/
|
||||
if (g_ace_external_varef_used[adc_nb])
|
||||
{
|
||||
p_calibration->mext = p_mtd_data->global_settings.varef_m;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_calibration->mext = NEUTRAL_M_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
Write new m and c transform factors into the PPE RAM. The m and c factors
|
||||
should be in 32-bit ACE number format. The factors will be merged with
|
||||
relevant PE opcode into PPE RAM. The 32-bit factors are shifted right by one
|
||||
byte giving a 24-bit ACE number which is then merged with an 8-bit PPE opcode
|
||||
located in the most significant byte of the PPE RAM location.
|
||||
*/
|
||||
void write_transform_coefficients
|
||||
(
|
||||
ace_channel_handle_t channel_handle,
|
||||
uint32_t m,
|
||||
uint32_t c
|
||||
)
|
||||
{
|
||||
uint16_t m_ppe_offset;
|
||||
uint16_t c_ppe_offset;
|
||||
const uint32_t PPE_OPCODE_MASK = 0xFF000000u;
|
||||
|
||||
m_ppe_offset = g_ace_ppe_transforms_desc_table[channel_handle].m_ppe_offset;
|
||||
c_ppe_offset = g_ace_ppe_transforms_desc_table[channel_handle].c_ppe_offset;
|
||||
|
||||
ACE->PPE_RAM_DATA[m_ppe_offset]
|
||||
= (ACE->PPE_RAM_DATA[m_ppe_offset] & PPE_OPCODE_MASK) | (m >> 8u);
|
||||
|
||||
ACE->PPE_RAM_DATA[c_ppe_offset]
|
||||
= (ACE->PPE_RAM_DATA[c_ppe_offset] & PPE_OPCODE_MASK) | (c >> 8u);
|
||||
}
|
||||
|
||||
#endif /* ACE_CFG_DATA_FORMAT_VERSION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,413 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* (c) Copyright 2008 Actel Corporation. All rights reserved.
|
||||
*
|
||||
* SmartFusion microcontroller subsystem Peripheral DMA bare metal software
|
||||
* driver implementation.
|
||||
*
|
||||
* SVN $Revision: 2110 $
|
||||
* SVN $Date: 2010-02-05 15:24:19 +0000 (Fri, 05 Feb 2010) $
|
||||
*/
|
||||
#include "mss_pdma.h"
|
||||
#include "../../CMSIS/mss_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void DMA_IRQHandler( void );
|
||||
#else
|
||||
void DMA_IRQHandler( void );
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
Offset of the posted writes WRITE_ADJ bits in a PDMA channel's configuration
|
||||
register.
|
||||
*/
|
||||
#define CHANNEL_N_POSTED_WRITE_ADJUST_SHIFT 14
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
* Look-up table use to derice a channel's control register value from the
|
||||
* requested source/destination. This table is incexed on the pdma_src_dest_t
|
||||
* enumeration.
|
||||
*/
|
||||
#define CHANNEL_N_CTRL_PDMA_MASK (uint32_t)0x00000001
|
||||
#define CHANNEL_N_PERIPH_SELECT_SHIFT (uint32_t)23
|
||||
#define CHANNEL_N_DIRECTION_MASK (uint32_t)0x00000002
|
||||
|
||||
const uint32_t src_dest_to_ctrl_reg_lut[] =
|
||||
{
|
||||
CHANNEL_N_CTRL_PDMA_MASK, /* PDMA_FROM_UART_0 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)1 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_UART_0 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)2 << CHANNEL_N_PERIPH_SELECT_SHIFT), /* PDMA_FROM_UART_1 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)3 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_UART_1 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)4 << CHANNEL_N_PERIPH_SELECT_SHIFT), /* PDMA_FROM_SPI_0 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)5 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_SPI_0 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)6 << CHANNEL_N_PERIPH_SELECT_SHIFT), /* PDMA_FROM_SPI_1 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)7 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_SPI_1 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)8 << CHANNEL_N_PERIPH_SELECT_SHIFT), /* PDMA_FROM_FPGA_1 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)8 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_FPGA_1 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)9 << CHANNEL_N_PERIPH_SELECT_SHIFT), /* PDMA_FROM_FPGA_0 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)9 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_FPGA_0 */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)10 << CHANNEL_N_PERIPH_SELECT_SHIFT) | CHANNEL_N_DIRECTION_MASK, /* PDMA_TO_ACE */
|
||||
CHANNEL_N_CTRL_PDMA_MASK | ( (uint32_t)11 << CHANNEL_N_PERIPH_SELECT_SHIFT) /* PDMA_FROM_ACE */
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
#define PDMA_MASTER_ENABLE (uint32_t)0x04
|
||||
#define PDMA_SOFT_RESET (uint32_t)0x20
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
*
|
||||
*/
|
||||
#define NB_OF_PDMA_CHANNELS 8
|
||||
|
||||
#define NEXT_CHANNEL_A 0U
|
||||
#define NEXT_CHANNEL_B 1U
|
||||
|
||||
#define CHANNEL_STOPPED 0U
|
||||
#define CHANNEL_STARTED 1U
|
||||
|
||||
static uint8_t g_pdma_next_channel[NB_OF_PDMA_CHANNELS];
|
||||
static uint8_t g_pdma_started_a[NB_OF_PDMA_CHANNELS];
|
||||
static uint8_t g_pdma_started_b[NB_OF_PDMA_CHANNELS];
|
||||
static pdma_channel_isr_t g_pdma_isr_table[NB_OF_PDMA_CHANNELS];
|
||||
static const uint16_t g_pdma_status_mask[NB_OF_PDMA_CHANNELS] =
|
||||
{
|
||||
(uint16_t)0x0003, /* PDMA_CHANNEL_0 */
|
||||
(uint16_t)0x000C, /* PDMA_CHANNEL_1 */
|
||||
(uint16_t)0x0030, /* PDMA_CHANNEL_2 */
|
||||
(uint16_t)0x00C0, /* PDMA_CHANNEL_3 */
|
||||
(uint16_t)0x0300, /* PDMA_CHANNEL_4 */
|
||||
(uint16_t)0x0C00, /* PDMA_CHANNEL_5 */
|
||||
(uint16_t)0x3000, /* PDMA_CHANNEL_6 */
|
||||
(uint16_t)0xC000, /* PDMA_CHANNEL_7 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
void PDMA_init( void )
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
/* Enable PDMA master access to comms matrix. */
|
||||
SYSREG->AHB_MATRIX_CR |= PDMA_MASTER_ENABLE;
|
||||
|
||||
/* Reset PDMA block. */
|
||||
SYSREG->SOFT_RST_CR |= PDMA_SOFT_RESET;
|
||||
|
||||
/* Clear any previously pended MSS PDMA interrupt */
|
||||
NVIC_ClearPendingIRQ( DMA_IRQn );
|
||||
|
||||
/* Take PDMA controller out of reset*/
|
||||
SYSREG->SOFT_RST_CR &= ~PDMA_SOFT_RESET;
|
||||
|
||||
/* Initialize channels state information. */
|
||||
for ( i = 0; i < NB_OF_PDMA_CHANNELS; ++i )
|
||||
{
|
||||
g_pdma_next_channel[i] = NEXT_CHANNEL_A;
|
||||
g_pdma_started_a[i] = CHANNEL_STOPPED;
|
||||
g_pdma_started_b[i] = CHANNEL_STOPPED;
|
||||
g_pdma_isr_table[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
#define CHANNEL_RESET_MASK (uint32_t)0x00000020
|
||||
|
||||
void PDMA_configure
|
||||
(
|
||||
pdma_channel_id_t channel_id,
|
||||
pdma_src_dest_t src_dest,
|
||||
uint32_t channel_cfg,
|
||||
uint8_t write_adjust
|
||||
)
|
||||
{
|
||||
/* Reset the channel. */
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CHANNEL_RESET_MASK;
|
||||
PDMA->CHANNEL[channel_id].CRTL &= ~CHANNEL_RESET_MASK;
|
||||
|
||||
/* Configure PDMA channel's data source and destination. */
|
||||
if ( src_dest != PDMA_MEM_TO_MEM )
|
||||
{
|
||||
PDMA->CHANNEL[channel_id].CRTL |= src_dest_to_ctrl_reg_lut[src_dest];
|
||||
}
|
||||
|
||||
/* Configure PDMA channel trnasfer size, priority, source and destination address increment. */
|
||||
PDMA->CHANNEL[channel_id].CRTL |= channel_cfg;
|
||||
|
||||
/* Posted write adjust. */
|
||||
PDMA->CHANNEL[channel_id].CRTL |= ((uint32_t)write_adjust << CHANNEL_N_POSTED_WRITE_ADJUST_SHIFT);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
#define PAUSE_MASK (uint32_t)0x00000010
|
||||
|
||||
#define BUFFER_B_SELECT_MASK (uint32_t)0x00000004
|
||||
|
||||
#define CLEAR_PORT_A_DONE_MASK (uint32_t)0x00000080
|
||||
#define CLEAR_PORT_B_DONE_MASK (uint32_t)0x00000100
|
||||
|
||||
#define PORT_A_COMPLETE_MASK (uint32_t)0x00000001
|
||||
#define PORT_B_COMPLETE_MASK (uint32_t)0x00000002
|
||||
|
||||
void PDMA_start
|
||||
(
|
||||
pdma_channel_id_t channel_id,
|
||||
uint32_t src_addr,
|
||||
uint32_t dest_addr,
|
||||
uint16_t transfer_count
|
||||
)
|
||||
{
|
||||
/* Pause transfer. */
|
||||
PDMA->CHANNEL[channel_id].CRTL |= PAUSE_MASK;
|
||||
|
||||
/* Clear complete transfers. */
|
||||
if ( PDMA->CHANNEL[channel_id].STATUS & PORT_A_COMPLETE_MASK )
|
||||
{
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CLEAR_PORT_A_DONE_MASK;
|
||||
g_pdma_started_a[channel_id] = CHANNEL_STOPPED;
|
||||
}
|
||||
if ( PDMA->CHANNEL[channel_id].STATUS & PORT_B_COMPLETE_MASK )
|
||||
{
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CLEAR_PORT_B_DONE_MASK;
|
||||
g_pdma_started_b[channel_id] = CHANNEL_STOPPED;
|
||||
}
|
||||
|
||||
/* Load source, destination and transfer count. */
|
||||
if ( PDMA->CHANNEL[channel_id].STATUS & BUFFER_B_SELECT_MASK )
|
||||
{
|
||||
g_pdma_next_channel[channel_id] = NEXT_CHANNEL_A;
|
||||
g_pdma_started_b[channel_id] = CHANNEL_STARTED;
|
||||
|
||||
PDMA->CHANNEL[channel_id].BUFFER_B_SRC_ADDR = src_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_B_DEST_ADDR = dest_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_B_TRANSFER_COUNT = transfer_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pdma_next_channel[channel_id] = NEXT_CHANNEL_B;
|
||||
g_pdma_started_a[channel_id] = CHANNEL_STARTED;
|
||||
|
||||
PDMA->CHANNEL[channel_id].BUFFER_A_SRC_ADDR = src_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_A_DEST_ADDR = dest_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_A_TRANSFER_COUNT = transfer_count;
|
||||
}
|
||||
|
||||
/* Start transfer */
|
||||
PDMA->CHANNEL[channel_id].CRTL &= ~PAUSE_MASK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
void PDMA_load_next_buffer
|
||||
(
|
||||
pdma_channel_id_t channel_id,
|
||||
uint32_t src_addr,
|
||||
uint32_t dest_addr,
|
||||
uint16_t transfer_count
|
||||
)
|
||||
{
|
||||
if ( NEXT_CHANNEL_A == g_pdma_next_channel[channel_id] )
|
||||
{
|
||||
/* Wait for channel A current transfer completion. */
|
||||
if ( CHANNEL_STARTED == g_pdma_started_a[channel_id] )
|
||||
{
|
||||
uint32_t completed;
|
||||
uint32_t channel_mask;
|
||||
channel_mask = (uint32_t)1 << ((uint32_t)channel_id * 2U);
|
||||
do {
|
||||
completed = PDMA->BUFFER_STATUS & channel_mask;
|
||||
} while( !completed );
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CLEAR_PORT_A_DONE_MASK;
|
||||
}
|
||||
/* Load source, destination and transfer count. */
|
||||
PDMA->CHANNEL[channel_id].BUFFER_A_SRC_ADDR = src_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_A_DEST_ADDR = dest_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_A_TRANSFER_COUNT = transfer_count;
|
||||
|
||||
/* Update channel state information. */
|
||||
g_pdma_next_channel[channel_id] = NEXT_CHANNEL_B;
|
||||
g_pdma_started_a[channel_id] = CHANNEL_STARTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for channel B current transfer completion. */
|
||||
if ( CHANNEL_STARTED == g_pdma_started_b[channel_id] )
|
||||
{
|
||||
uint32_t completed;
|
||||
uint32_t channel_mask;
|
||||
channel_mask = (uint32_t)1 << (((uint32_t)channel_id * 2U) + 1U);
|
||||
do {
|
||||
completed = PDMA->BUFFER_STATUS & channel_mask;
|
||||
} while( !completed );
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CLEAR_PORT_B_DONE_MASK;
|
||||
}
|
||||
/* Load source, destination and transfer count. */
|
||||
PDMA->CHANNEL[channel_id].BUFFER_B_SRC_ADDR = src_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_B_DEST_ADDR = dest_addr;
|
||||
PDMA->CHANNEL[channel_id].BUFFER_B_TRANSFER_COUNT = transfer_count;
|
||||
|
||||
/* Update channel state information. */
|
||||
g_pdma_next_channel[channel_id] = NEXT_CHANNEL_A;
|
||||
g_pdma_started_b[channel_id] = CHANNEL_STARTED;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
uint32_t PDMA_status
|
||||
(
|
||||
pdma_channel_id_t channel_id
|
||||
)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
status = PDMA->CHANNEL[channel_id].STATUS & (PORT_A_COMPLETE_MASK | PORT_B_COMPLETE_MASK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
*
|
||||
*/
|
||||
#define CHANNEL_0_STATUS_BITS_MASK (uint16_t)0x0003
|
||||
#define CHANNEL_1_STATUS_BITS_MASK (uint16_t)0x000C
|
||||
#define CHANNEL_2_STATUS_BITS_MASK (uint16_t)0x0030
|
||||
#define CHANNEL_3_STATUS_BITS_MASK (uint16_t)0x00C0
|
||||
#define CHANNEL_4_STATUS_BITS_MASK (uint16_t)0x0300
|
||||
#define CHANNEL_5_STATUS_BITS_MASK (uint16_t)0x0C00
|
||||
#define CHANNEL_6_STATUS_BITS_MASK (uint16_t)0x3000
|
||||
#define CHANNEL_7_STATUS_BITS_MASK (uint16_t)0xC000
|
||||
|
||||
static pdma_channel_id_t get_channel_id_from_status
|
||||
(
|
||||
uint16_t status
|
||||
)
|
||||
{
|
||||
pdma_channel_id_t channel_id = PDMA_CHANNEL_0;
|
||||
|
||||
if ( status & CHANNEL_0_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_0;
|
||||
}
|
||||
else if ( status & CHANNEL_1_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_1;
|
||||
}
|
||||
else if ( status & CHANNEL_2_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_2;
|
||||
}
|
||||
else if ( status & CHANNEL_3_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_3;
|
||||
}
|
||||
else if ( status & CHANNEL_4_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_4;
|
||||
}
|
||||
else if ( status & CHANNEL_5_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_5;
|
||||
}
|
||||
else if ( status & CHANNEL_6_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_6;
|
||||
}
|
||||
else if ( status & CHANNEL_7_STATUS_BITS_MASK )
|
||||
{
|
||||
channel_id = PDMA_CHANNEL_7;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
return channel_id;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
*
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void DMA_IRQHandler( void )
|
||||
#else
|
||||
void DMA_IRQHandler( void )
|
||||
#endif
|
||||
{
|
||||
uint16_t status;
|
||||
pdma_channel_id_t channel_id;
|
||||
|
||||
status = (uint16_t)PDMA->BUFFER_STATUS;
|
||||
|
||||
do {
|
||||
channel_id = get_channel_id_from_status( status );
|
||||
status &= (uint16_t)~g_pdma_status_mask[channel_id];
|
||||
if ( 0 != g_pdma_isr_table[channel_id])
|
||||
{
|
||||
g_pdma_isr_table[channel_id]();
|
||||
}
|
||||
} while ( 0U != status );
|
||||
|
||||
NVIC_ClearPendingIRQ( DMA_IRQn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
void PDMA_set_irq_handler
|
||||
(
|
||||
pdma_channel_id_t channel_id,
|
||||
pdma_channel_isr_t handler
|
||||
)
|
||||
{
|
||||
/* Save address of handler function in PDMA driver ISR lookup table. */
|
||||
g_pdma_isr_table[channel_id] = handler;
|
||||
|
||||
/* Enable PDMA channel's interrupt. */
|
||||
PDMA->CHANNEL[channel_id].CRTL |= PDMA_IRQ_ENABLE_MASK;
|
||||
|
||||
/* Enable PDMA interrupt in Cortex-M3 NVIC. */
|
||||
NVIC_EnableIRQ( DMA_IRQn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
void PDMA_enable_irq( pdma_channel_id_t channel_id )
|
||||
{
|
||||
PDMA->CHANNEL[channel_id].CRTL |= PDMA_IRQ_ENABLE_MASK;
|
||||
NVIC_EnableIRQ( DMA_IRQn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_pdma.h for description of this function.
|
||||
*/
|
||||
void PDMA_clear_irq
|
||||
(
|
||||
pdma_channel_id_t channel_id
|
||||
)
|
||||
{
|
||||
/* Clear interrupt in PDMA controller. */
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CLEAR_PORT_A_DONE_MASK;
|
||||
PDMA->CHANNEL[channel_id].CRTL |= CLEAR_PORT_B_DONE_MASK;
|
||||
|
||||
/* Clear interrupt in Cortex-M3 NVIC. */
|
||||
NVIC_ClearPendingIRQ( DMA_IRQn );
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,610 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* (c) Copyright 2008 Actel Corporation. All rights reserved.
|
||||
*
|
||||
* SmartFusion microcontroller subsystem SPI bare metal software driver
|
||||
* implementation.
|
||||
*
|
||||
* SVN $Revision: 2176 $
|
||||
* SVN $Date: 2010-02-15 21:04:22 +0000 (Mon, 15 Feb 2010) $
|
||||
*/
|
||||
#include "mss_spi.h"
|
||||
#include "../../CMSIS/mss_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
MSS SPI can operate as master or slave.
|
||||
*/
|
||||
#define MSS_SPI_MODE_SLAVE (uint32_t)0
|
||||
#define MSS_SPI_MODE_MASTER (uint32_t)1
|
||||
|
||||
/***************************************************************************//**
|
||||
* Mask of transfer protocol and SPO, SPH bits within control register.
|
||||
*/
|
||||
#define PROTOCOL_MODE_MASK (uint32_t)0x030000C0
|
||||
|
||||
/***************************************************************************//**
|
||||
* Mask of theframe count bits within the SPI control register.
|
||||
*/
|
||||
#define TXRXDFCOUNT_MASK (uint32_t)0x00FFFF00
|
||||
#define TXRXDFCOUNT_SHIFT (uint32_t)8
|
||||
|
||||
/***************************************************************************//**
|
||||
* SPI hardware FIFO depth.
|
||||
*/
|
||||
#define RX_FIFO_SIZE 4u
|
||||
|
||||
/***************************************************************************//**
|
||||
Marker used to detect that the configuration has not been selected for a
|
||||
specific slave when operating as a master.
|
||||
*/
|
||||
#define NOT_CONFIGURED 0xFFFFFFFF
|
||||
|
||||
/***************************************************************************//**
|
||||
* SPI instance data structures for SPI0 and SPI1. A pointer to these data
|
||||
* structures must be used as first parameter to any of the SPI driver functions
|
||||
* to identify the SPI hardware block that will perform the requested operation.
|
||||
*/
|
||||
mss_spi_instance_t g_mss_spi0;
|
||||
mss_spi_instance_t g_mss_spi1;
|
||||
|
||||
/***************************************************************************//**
|
||||
SPI0 interrupt service routine
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void SPI0_IRQHandler( void );
|
||||
#else
|
||||
void SPI0_IRQHandler( void );
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
SPI1 interrupt service routine
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void SPI1_IRQHandler( void );
|
||||
#else
|
||||
void SPI1_IRQHandler( void );
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_init()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_init
|
||||
(
|
||||
mss_spi_instance_t * this_spi
|
||||
)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
if (this_spi == &g_mss_spi0)
|
||||
{
|
||||
this_spi->hw_reg = SPI0;
|
||||
this_spi->hw_reg_bit = SPI0_BITBAND;
|
||||
this_spi->irqn = SPI0_IRQn;
|
||||
|
||||
/* reset SPI0 */
|
||||
SYSREG->SOFT_RST_CR |= SYSREG_SPI0_SOFTRESET_MASK;
|
||||
/* Clear any previously pended SPI0 interrupt */
|
||||
NVIC_ClearPendingIRQ( SPI0_IRQn );
|
||||
/* Take SPI0 out of reset. */
|
||||
SYSREG->SOFT_RST_CR &= ~SYSREG_SPI0_SOFTRESET_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_spi->hw_reg = SPI1;
|
||||
this_spi->hw_reg_bit = SPI1_BITBAND;
|
||||
this_spi->irqn = SPI1_IRQn;
|
||||
|
||||
/* reset SPI1 */
|
||||
SYSREG->SOFT_RST_CR |= SYSREG_SPI1_SOFTRESET_MASK;
|
||||
/* Clear any previously pended SPI1 interrupt */
|
||||
NVIC_ClearPendingIRQ( SPI1_IRQn );
|
||||
/* Take SPI1 out of reset. */
|
||||
SYSREG->SOFT_RST_CR &= ~SYSREG_SPI1_SOFTRESET_MASK;
|
||||
}
|
||||
|
||||
this_spi->frame_rx_handler = 0U;
|
||||
this_spi->slave_tx_frame = 0U;
|
||||
|
||||
this_spi->block_rx_handler = 0U;
|
||||
|
||||
this_spi->slave_tx_buffer = 0U;
|
||||
this_spi->slave_tx_size = 0U;
|
||||
this_spi->slave_tx_idx = 0U;
|
||||
|
||||
for ( i = 0u; i < (uint16_t)MSS_SPI_MAX_NB_OF_SLAVES; ++i )
|
||||
{
|
||||
this_spi->slaves_cfg[i].ctrl_reg = NOT_CONFIGURED;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_configure_slave_mode()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_configure_slave_mode
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
mss_spi_protocol_mode_t protocol_mode,
|
||||
mss_spi_pclk_div_t clk_rate,
|
||||
uint8_t frame_bit_length
|
||||
)
|
||||
{
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
ASSERT( frame_bit_length <= 32 );
|
||||
|
||||
/* Set the mode. */
|
||||
this_spi->hw_reg_bit->CTRL_MASTER = MSS_SPI_MODE_SLAVE;
|
||||
|
||||
/* Set the clock rate. */
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 0U;
|
||||
this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~PROTOCOL_MODE_MASK) | (uint32_t)protocol_mode;
|
||||
this_spi->hw_reg->CLK_GEN = (uint32_t)clk_rate;
|
||||
|
||||
/* Set default frame size to byte size and number of data frames to 1. */
|
||||
this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | ((uint32_t)1 << TXRXDFCOUNT_SHIFT);
|
||||
this_spi->hw_reg->TXRXDF_SIZE = frame_bit_length;
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 1U;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_configure_master_mode()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_configure_master_mode
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
mss_spi_slave_t slave,
|
||||
mss_spi_protocol_mode_t protocol_mode,
|
||||
mss_spi_pclk_div_t clk_rate,
|
||||
uint8_t frame_bit_length
|
||||
)
|
||||
{
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
ASSERT( slave < MSS_SPI_MAX_NB_OF_SLAVES );
|
||||
ASSERT( frame_bit_length <= 32 );
|
||||
|
||||
/* Set the mode. */
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 0U;
|
||||
this_spi->hw_reg_bit->CTRL_MASTER = MSS_SPI_MODE_MASTER;
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 1U;
|
||||
|
||||
/*
|
||||
* Keep track of the required register configuration for this slave. These
|
||||
* values will be used by the MSS_SPI_set_slave_select() function to configure
|
||||
* the master to match the slave being selected.
|
||||
*/
|
||||
if ( slave < MSS_SPI_MAX_NB_OF_SLAVES )
|
||||
{
|
||||
this_spi->slaves_cfg[slave].ctrl_reg = 0x00000002uL | (uint32_t)protocol_mode | ((uint32_t)1 << TXRXDFCOUNT_SHIFT);
|
||||
this_spi->slaves_cfg[slave].txrxdf_size_reg = frame_bit_length;
|
||||
this_spi->slaves_cfg[slave].clk_gen = (uint8_t)clk_rate;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_set_slave_select()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_set_slave_select
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
mss_spi_slave_t slave
|
||||
)
|
||||
{
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI master. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );
|
||||
ASSERT( this_spi->slaves_cfg[slave].ctrl_reg != NOT_CONFIGURED );
|
||||
|
||||
/* Set the clock rate. */
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 0U;
|
||||
this_spi->hw_reg->CONTROL = this_spi->slaves_cfg[slave].ctrl_reg;
|
||||
this_spi->hw_reg->CLK_GEN = this_spi->slaves_cfg[slave].clk_gen;
|
||||
this_spi->hw_reg->TXRXDF_SIZE = this_spi->slaves_cfg[slave].txrxdf_size_reg;
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 1U;
|
||||
|
||||
/* Set slave select */
|
||||
this_spi->hw_reg->SLAVE_SELECT |= ((uint32_t)1 << (uint32_t)slave);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_clear_slave_select()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_clear_slave_select
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
mss_spi_slave_t slave
|
||||
)
|
||||
{
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI master. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );
|
||||
|
||||
this_spi->hw_reg->SLAVE_SELECT &= ~((uint32_t)1 << (uint32_t)slave);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_transfer_frame()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
uint32_t MSS_SPI_transfer_frame
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
uint32_t tx_bits
|
||||
)
|
||||
{
|
||||
volatile uint32_t dummy;
|
||||
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI master. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );
|
||||
|
||||
/* Flush Rx FIFO. */
|
||||
while ( this_spi->hw_reg_bit->STATUS_RX_RDY == 1U )
|
||||
{
|
||||
dummy = this_spi->hw_reg->RX_DATA;
|
||||
dummy = dummy; /* Prevent Lint warning. */
|
||||
}
|
||||
|
||||
/* Send frame. */
|
||||
this_spi->hw_reg->TX_DATA = tx_bits;
|
||||
|
||||
/* Wait for frame Tx to complete. */
|
||||
while ( this_spi->hw_reg_bit->STATUS_TX_DONE == 0U )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/* Read received frame. */
|
||||
/* Wait for Rx complete. */
|
||||
while ( this_spi->hw_reg_bit->STATUS_RX_RDY == 0U )
|
||||
{
|
||||
;
|
||||
}
|
||||
/* Return Rx data. */
|
||||
return( this_spi->hw_reg->RX_DATA );
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_transfer_block()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_transfer_block
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
const uint8_t * cmd_buffer,
|
||||
uint16_t cmd_byte_size,
|
||||
uint8_t * rd_buffer,
|
||||
uint16_t rd_byte_size
|
||||
)
|
||||
{
|
||||
uint16_t transfer_idx = 0U;
|
||||
uint16_t tx_idx;
|
||||
uint16_t rx_idx;
|
||||
uint32_t frame_count;
|
||||
volatile uint32_t rx_raw;
|
||||
uint16_t transit = 0U;
|
||||
|
||||
uint16_t transfer_size; /* Total number of bytes transfered. */
|
||||
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI master. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_MASTER );
|
||||
|
||||
/* Compute number of bytes to transfer. */
|
||||
transfer_size = cmd_byte_size + rd_byte_size;
|
||||
|
||||
/* Adjust to 1 byte transfer to cater for DMA transfers. */
|
||||
if ( transfer_size == 0U )
|
||||
{
|
||||
frame_count = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_count = transfer_size;
|
||||
}
|
||||
|
||||
/* Set frame size to 8 bits and the frame count to the tansfer size. */
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 0U;
|
||||
this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | ( (frame_count << TXRXDFCOUNT_SHIFT) & TXRXDFCOUNT_MASK);
|
||||
this_spi->hw_reg->TXRXDF_SIZE = 8U;
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 1U;
|
||||
|
||||
/* Flush the receive FIFO. */
|
||||
while ( !this_spi->hw_reg_bit->STATUS_RX_FIFO_EMPTY )
|
||||
{
|
||||
rx_raw = this_spi->hw_reg->RX_DATA;
|
||||
}
|
||||
|
||||
tx_idx = 0u;
|
||||
rx_idx = 0u;
|
||||
if ( tx_idx < cmd_byte_size )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = cmd_buffer[tx_idx];
|
||||
++tx_idx;
|
||||
++transit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( tx_idx < transfer_size )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = 0x00U;
|
||||
++tx_idx;
|
||||
++transit;
|
||||
}
|
||||
}
|
||||
/* Perform the remainder of the transfer by sending a byte every time a byte
|
||||
* has been received. This should ensure that no Rx overflow can happen in
|
||||
* case of an interrupt occurs during this function. */
|
||||
while ( transfer_idx < transfer_size )
|
||||
{
|
||||
if ( !this_spi->hw_reg_bit->STATUS_RX_FIFO_EMPTY )
|
||||
{
|
||||
/* Process received byte. */
|
||||
rx_raw = this_spi->hw_reg->RX_DATA;
|
||||
if ( transfer_idx >= cmd_byte_size )
|
||||
{
|
||||
if ( rx_idx < rd_byte_size )
|
||||
{
|
||||
rd_buffer[rx_idx] = (uint8_t)rx_raw;
|
||||
}
|
||||
++rx_idx;
|
||||
}
|
||||
++transfer_idx;
|
||||
--transit;
|
||||
}
|
||||
|
||||
if ( !this_spi->hw_reg_bit->STATUS_TX_FIFO_FULL )
|
||||
{
|
||||
if (transit < RX_FIFO_SIZE)
|
||||
{
|
||||
/* Send another byte. */
|
||||
if ( tx_idx < cmd_byte_size )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = cmd_buffer[tx_idx];
|
||||
++tx_idx;
|
||||
++transit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( tx_idx < transfer_size )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = 0x00U;
|
||||
++tx_idx;
|
||||
++transit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_set_frame_rx_handler()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_set_frame_rx_handler
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
mss_spi_frame_rx_handler_t rx_handler
|
||||
)
|
||||
{
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI slave. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_SLAVE );
|
||||
|
||||
/* Disable block Rx handler as they are mutually exclusive. */
|
||||
this_spi->block_rx_handler = 0U;
|
||||
|
||||
/* Keep a copy of the pointer to the rx hnadler function. */
|
||||
this_spi->frame_rx_handler = rx_handler;
|
||||
|
||||
/* Enable Rx interrupt. */
|
||||
this_spi->hw_reg_bit->CTRL_RX_INT_EN = 1U;
|
||||
NVIC_EnableIRQ( this_spi->irqn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_set_slave_tx_frame()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_set_slave_tx_frame
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
uint32_t frame_value
|
||||
)
|
||||
{
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI slave. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_SLAVE );
|
||||
|
||||
/* Disable slave block tx buffer as it is mutually exclusive with frame
|
||||
* level handling. */
|
||||
this_spi->slave_tx_buffer = 0U;
|
||||
this_spi->slave_tx_size = 0U;
|
||||
this_spi->slave_tx_idx = 0U;
|
||||
|
||||
/* Keep a copy of the slave tx frame value. */
|
||||
this_spi->slave_tx_frame = frame_value;
|
||||
|
||||
/* Load frame into Tx data register. */
|
||||
this_spi->hw_reg->TX_DATA = this_spi->slave_tx_frame;
|
||||
|
||||
/* Enable Tx Done interrupt in order to reload the slave Tx frame after each
|
||||
* time it has been sent. */
|
||||
this_spi->hw_reg_bit->CTRL_TX_INT_EN = 1U;
|
||||
NVIC_EnableIRQ( this_spi->irqn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* MSS_SPI_set_slave_block_buffers()
|
||||
* See "mss_spi.h" for details of how to use this function.
|
||||
*/
|
||||
void MSS_SPI_set_slave_block_buffers
|
||||
(
|
||||
mss_spi_instance_t * this_spi,
|
||||
const uint8_t * tx_buffer,
|
||||
uint32_t tx_buff_size,
|
||||
uint8_t * rx_buffer,
|
||||
uint32_t rx_buff_size,
|
||||
mss_spi_block_rx_handler_t block_rx_handler
|
||||
)
|
||||
{
|
||||
uint32_t frame_count;
|
||||
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
/* This function is only intended to be used with an SPI slave. */
|
||||
ASSERT( this_spi->hw_reg_bit->CTRL_MASTER == MSS_SPI_MODE_SLAVE );
|
||||
|
||||
/* Disable Rx frame handler as it is mutually exclusive with block rx handler. */
|
||||
this_spi->frame_rx_handler = 0U;
|
||||
|
||||
/* Keep a copy of the pointer to the block rx handler function. */
|
||||
this_spi->block_rx_handler = block_rx_handler;
|
||||
|
||||
this_spi->slave_rx_buffer = rx_buffer;
|
||||
this_spi->slave_rx_size = rx_buff_size;
|
||||
this_spi->slave_rx_idx = 0U;
|
||||
|
||||
/**/
|
||||
this_spi->slave_tx_buffer = tx_buffer;
|
||||
this_spi->slave_tx_size = tx_buff_size;
|
||||
this_spi->slave_tx_idx = 0U;
|
||||
|
||||
frame_count = rx_buff_size;
|
||||
|
||||
/**/
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 0U;
|
||||
this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | (frame_count << TXRXDFCOUNT_SHIFT);
|
||||
this_spi->hw_reg->TXRXDF_SIZE = 8U;
|
||||
this_spi->hw_reg_bit->CTRL_ENABLE = 1U;
|
||||
|
||||
/* Load the transmit FIFO. */
|
||||
while ( !(this_spi->hw_reg_bit->STATUS_TX_FIFO_FULL) && ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx];
|
||||
++this_spi->slave_tx_idx;
|
||||
}
|
||||
|
||||
/* Enable Rx interrupt. */
|
||||
this_spi->hw_reg_bit->CTRL_RX_INT_EN = 1U;
|
||||
NVIC_EnableIRQ( this_spi->irqn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* SPI interrupt service routine.
|
||||
*/
|
||||
static void mss_spi_isr
|
||||
(
|
||||
mss_spi_instance_t * this_spi
|
||||
)
|
||||
{
|
||||
uint32_t rx_frame;
|
||||
|
||||
ASSERT( (this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1) );
|
||||
|
||||
if ( this_spi->hw_reg_bit->MIS_RX_RDY )
|
||||
{
|
||||
while( !this_spi->hw_reg_bit->STATUS_RX_FIFO_EMPTY )
|
||||
{
|
||||
rx_frame = this_spi->hw_reg->RX_DATA;
|
||||
if ( this_spi->frame_rx_handler != 0U )
|
||||
{
|
||||
/* Single frame handling mode. */
|
||||
this_spi->frame_rx_handler( rx_frame );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( this_spi->block_rx_handler != 0U )
|
||||
{
|
||||
/* Block handling mode. */
|
||||
if ( this_spi->slave_rx_idx < this_spi->slave_rx_size )
|
||||
{
|
||||
this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
|
||||
++this_spi->slave_rx_idx;
|
||||
if ( this_spi->slave_rx_idx == this_spi->slave_rx_size )
|
||||
{
|
||||
(*this_spi->block_rx_handler)( this_spi->slave_rx_buffer, this_spi->slave_rx_size );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Feed transmit FIFO. */
|
||||
if ( !(this_spi->hw_reg_bit->STATUS_TX_FIFO_FULL) && ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx];
|
||||
++this_spi->slave_tx_idx;
|
||||
}
|
||||
}
|
||||
this_spi->hw_reg_bit->INT_CLEAR_RX_RDY = 1U;
|
||||
}
|
||||
|
||||
if ( this_spi->hw_reg_bit->MIS_TX_DONE )
|
||||
{
|
||||
if ( this_spi->slave_tx_buffer != 0U )
|
||||
{
|
||||
this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx];
|
||||
++this_spi->slave_tx_idx;
|
||||
if ( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
|
||||
{
|
||||
this_spi->slave_tx_idx = 0U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reload slave tx frame into Tx data register. */
|
||||
this_spi->hw_reg->TX_DATA = this_spi->slave_tx_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* SPIO interrupt service routine.
|
||||
* Please note that the name of this ISR is defined as part of the SmartFusion
|
||||
* CMSIS startup code.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void SPI0_IRQHandler( void )
|
||||
#else
|
||||
void SPI0_IRQHandler( void )
|
||||
#endif
|
||||
{
|
||||
mss_spi_isr( &g_mss_spi0 );
|
||||
NVIC_ClearPendingIRQ( SPI0_IRQn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* SPI1 interrupt service routine.
|
||||
* Please note that the name of this ISR is defined as part of the SmartFusion
|
||||
* CMSIS startup code.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void SPI1_IRQHandler( void )
|
||||
#else
|
||||
void SPI1_IRQHandler( void )
|
||||
#endif
|
||||
{
|
||||
mss_spi_isr( &g_mss_spi1 );
|
||||
NVIC_ClearPendingIRQ( SPI1_IRQn );
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,458 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* (c) Copyright 2007 Actel Corporation. All rights reserved.
|
||||
*
|
||||
* SmartFusion Microcontroller Subsystem UART bare metal software driver
|
||||
* implementation.
|
||||
*
|
||||
* SVN $Revision: 1898 $
|
||||
* SVN $Date: 2009-12-21 17:27:57 +0000 (Mon, 21 Dec 2009) $
|
||||
*/
|
||||
#include "mss_uart.h"
|
||||
#include "../../CMSIS/mss_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* defines
|
||||
*/
|
||||
#define TX_READY 0x01U
|
||||
#define TX_COMPLETE 0U
|
||||
|
||||
#define TX_FIFO_SIZE 16U
|
||||
|
||||
#define FCR_TRIG_LEVEL_MASK 0xC0U
|
||||
|
||||
#define IIRF_MASK 0x0FU
|
||||
|
||||
/*******************************************************************************
|
||||
* Possible values for Interrupt Identification Register Field.
|
||||
*/
|
||||
#define IIRF_MODEM_STATUS 0x00U
|
||||
#define IIRF_THRE 0x02U
|
||||
#define IIRF_RX_DATA 0x04U
|
||||
#define IIRF_RX_LINE_STATUS 0x06U
|
||||
#define IIRF_DATA_TIMEOUT 0x0CU
|
||||
|
||||
/*******************************************************************************
|
||||
* Cortex-M3 interrupt handler functions implemented as part of the MSS UART
|
||||
* driver.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void UART0_IRQHandler( void );
|
||||
#else
|
||||
void UART0_IRQHandler( void );
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void UART1_IRQHandler( void );
|
||||
#else
|
||||
void UART1_IRQHandler( void );
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Local functions.
|
||||
*/
|
||||
static void MSS_UART_isr( mss_uart_instance_t * this_uart );
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
*/
|
||||
mss_uart_instance_t g_mss_uart0;
|
||||
mss_uart_instance_t g_mss_uart1;
|
||||
|
||||
/***************************************************************************//**
|
||||
* UART_init.
|
||||
* Initialises the UART with default configuration.
|
||||
*/
|
||||
void
|
||||
MSS_UART_init
|
||||
(
|
||||
mss_uart_instance_t* this_uart,
|
||||
uint32_t baud_rate,
|
||||
uint8_t line_config
|
||||
)
|
||||
{
|
||||
uint16_t baud_value;
|
||||
uint32_t pclk_freq;
|
||||
|
||||
/* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
|
||||
* mss_uart_instance_t instances used to identfy UART0 and UART1. */
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
/* Force the value of the CMSIS global variables holding the various system
|
||||
* clock frequencies to be updated. */
|
||||
SystemCoreClockUpdate();
|
||||
|
||||
if ( this_uart == &g_mss_uart0 )
|
||||
{
|
||||
this_uart->hw_reg = UART0;
|
||||
this_uart->hw_reg_bit = UART0_BITBAND;
|
||||
this_uart->irqn = UART0_IRQn;
|
||||
|
||||
pclk_freq = g_FrequencyPCLK0;
|
||||
|
||||
/* reset UART0 */
|
||||
SYSREG->SOFT_RST_CR |= SYSREG_UART0_SOFTRESET_MASK;
|
||||
/* Clear any previously pended UART0 interrupt */
|
||||
NVIC_ClearPendingIRQ( UART0_IRQn );
|
||||
/* Take UART0 out of reset. */
|
||||
SYSREG->SOFT_RST_CR &= ~SYSREG_UART0_SOFTRESET_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_uart->hw_reg = UART1;
|
||||
this_uart->hw_reg_bit = UART1_BITBAND;
|
||||
this_uart->irqn = UART1_IRQn;
|
||||
|
||||
pclk_freq = g_FrequencyPCLK1;
|
||||
|
||||
/* Reset UART1 */
|
||||
SYSREG->SOFT_RST_CR |= SYSREG_UART1_SOFTRESET_MASK;
|
||||
/* Clear any previously pended UART1 interrupt */
|
||||
NVIC_ClearPendingIRQ( UART1_IRQn );
|
||||
/* Take UART1 out of reset. */
|
||||
SYSREG->SOFT_RST_CR &= ~SYSREG_UART1_SOFTRESET_MASK;
|
||||
}
|
||||
|
||||
/* disable interrupts */
|
||||
this_uart->hw_reg->IER = 0U;
|
||||
|
||||
/*
|
||||
* Compute baud value based on requested baud rate and PCLK frequency.
|
||||
* The baud value is computed using the following equation:
|
||||
* baud_value = PCLK_Frequency / (baud_rate * 16)
|
||||
* The baud value is rounded up or down depending on what would be the remainder
|
||||
* of the divide by 16 operation.
|
||||
*/
|
||||
baud_value = (uint16_t)(pclk_freq / baud_rate);
|
||||
if ( baud_value & 0x00000008U )
|
||||
{
|
||||
/* remainder above 0.5 */
|
||||
baud_value = (baud_value >> 4U) + 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* remainder below 0.5 */
|
||||
baud_value = (baud_value >> 4U);
|
||||
}
|
||||
|
||||
/* set divisor latch */
|
||||
this_uart->hw_reg_bit->LCR_DLAB = (uint32_t)1;
|
||||
|
||||
/* msb of baud value */
|
||||
this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8);
|
||||
/* lsb of baud value */
|
||||
this_uart->hw_reg->DLR = (uint8_t)baud_value;
|
||||
|
||||
/* reset divisor latch */
|
||||
this_uart->hw_reg_bit->LCR_DLAB = (uint32_t)0;
|
||||
|
||||
/* set the line control register (bit length, stop bits, parity) */
|
||||
this_uart->hw_reg->LCR = line_config;
|
||||
|
||||
/* FIFO configuration */
|
||||
this_uart->hw_reg->FCR = (uint8_t)MSS_UART_FIFO_SINGLE_BYTE;
|
||||
|
||||
/* disable loopback */
|
||||
this_uart->hw_reg_bit->MCR_LOOP = (uint32_t)0;
|
||||
|
||||
/* Instance setup */
|
||||
this_uart->tx_buff_size = TX_COMPLETE;
|
||||
this_uart->tx_buffer = (const uint8_t *)0;
|
||||
this_uart->tx_idx = 0U;
|
||||
|
||||
this_uart->rx_handler = (mss_uart_rx_handler_t)0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
void
|
||||
MSS_UART_polled_tx
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
const uint8_t * pbuff,
|
||||
uint32_t tx_size
|
||||
)
|
||||
{
|
||||
uint32_t char_idx;
|
||||
uint32_t status;
|
||||
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
for ( char_idx = 0U; char_idx < tx_size; char_idx++ )
|
||||
{
|
||||
/* Wait for UART to become ready to transmit. */
|
||||
do {
|
||||
status = this_uart->hw_reg_bit->LSR_THRE;
|
||||
} while ( (status & TX_READY) == 0U );
|
||||
/* Send next character in the buffer. */
|
||||
this_uart->hw_reg->THR = pbuff[char_idx];
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
void
|
||||
MSS_UART_polled_tx_string
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
const uint8_t * p_sz_string
|
||||
)
|
||||
{
|
||||
uint32_t char_idx;
|
||||
uint32_t status;
|
||||
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
char_idx = 0U;
|
||||
|
||||
while ( p_sz_string[char_idx] != 0U )
|
||||
{
|
||||
/* Wait for UART to become ready to transmit. */
|
||||
do {
|
||||
status = this_uart->hw_reg_bit->LSR_THRE;
|
||||
} while ( (status & TX_READY) == 0U);
|
||||
/* Send next character in the buffer. */
|
||||
this_uart->hw_reg->THR = p_sz_string[char_idx];
|
||||
++char_idx;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
void
|
||||
MSS_UART_irq_tx
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
const uint8_t * pbuff,
|
||||
uint32_t tx_size
|
||||
)
|
||||
{
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
if ( tx_size > 0U )
|
||||
{
|
||||
/*Initialise the transmit info for the UART instance with the arguments.*/
|
||||
this_uart->tx_buffer = pbuff;
|
||||
this_uart->tx_buff_size = tx_size;
|
||||
this_uart->tx_idx = (uint16_t)0;
|
||||
|
||||
/* enables TX interrupt */
|
||||
this_uart->hw_reg_bit->IER_ETBEI = (uint32_t)1;
|
||||
|
||||
/* Enable UART instance interrupt in Cortex-M3 NVIC. */
|
||||
NVIC_EnableIRQ( this_uart->irqn );
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
int8_t
|
||||
MSS_UART_tx_complete
|
||||
(
|
||||
mss_uart_instance_t * this_uart
|
||||
)
|
||||
{
|
||||
int8_t ret_value = 0;
|
||||
uint32_t transmit_empty = this_uart->hw_reg_bit->LSR_TEMT;
|
||||
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
if ( ( TX_COMPLETE == this_uart->tx_buff_size ) && transmit_empty )
|
||||
{
|
||||
ret_value = 1;
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
size_t
|
||||
MSS_UART_get_rx
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
uint8_t * rx_buff,
|
||||
size_t buff_size
|
||||
)
|
||||
{
|
||||
size_t rx_size = 0U;
|
||||
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
while (( this_uart->hw_reg_bit->LSR_DR != 0U) && ( rx_size < buff_size ) )
|
||||
{
|
||||
rx_buff[rx_size] = this_uart->hw_reg->RBR;
|
||||
++rx_size;
|
||||
}
|
||||
|
||||
return rx_size;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Interrupt service routine triggered by the Transmitter Holding Register
|
||||
* Empty (THRE) interrupt or Received Data Available (RDA).
|
||||
* On THRE irq this routine will transmit the data from the transmit buffer.
|
||||
* When all bytes are transmitted, this routine disables the THRE interrupt
|
||||
* and resets the transmit counter.
|
||||
* On RDA irq this routine will call the user's receive handler routine previously
|
||||
* registered with the UART driver through a call to UART_set_rx_handler().
|
||||
*/
|
||||
static void
|
||||
MSS_UART_isr
|
||||
(
|
||||
mss_uart_instance_t * this_uart
|
||||
)
|
||||
{
|
||||
uint8_t iirf;
|
||||
uint32_t tx_empty;
|
||||
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
iirf = this_uart->hw_reg->IIR & IIRF_MASK;
|
||||
|
||||
switch ( iirf )
|
||||
{
|
||||
case IIRF_MODEM_STATUS:
|
||||
break;
|
||||
|
||||
case IIRF_THRE: /* Transmitter Holding Register Empty */
|
||||
tx_empty = this_uart->hw_reg_bit->LSR_TEMT;
|
||||
|
||||
if ( tx_empty )
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t fill_size = TX_FIFO_SIZE;
|
||||
uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
|
||||
if ( tx_remain < TX_FIFO_SIZE )
|
||||
{
|
||||
fill_size = tx_remain;
|
||||
}
|
||||
/* Fill up FIFO */
|
||||
for ( i = 0U; i < fill_size; ++i )
|
||||
{
|
||||
this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
|
||||
++this_uart->tx_idx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
|
||||
++this_uart->tx_idx;
|
||||
}
|
||||
|
||||
if ( this_uart->tx_idx == this_uart->tx_buff_size )
|
||||
{
|
||||
this_uart->tx_buff_size = TX_COMPLETE;
|
||||
/* disables TX interrupt */
|
||||
this_uart->hw_reg_bit->IER_ETBEI = 0U;
|
||||
}
|
||||
break;
|
||||
|
||||
case IIRF_RX_DATA: /* Received Data Available */
|
||||
case IIRF_DATA_TIMEOUT:
|
||||
if (this_uart->rx_handler != 0)
|
||||
{
|
||||
(*(this_uart->rx_handler))();
|
||||
}
|
||||
break;
|
||||
|
||||
case IIRF_RX_LINE_STATUS:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Disable other interrupts */
|
||||
this_uart->hw_reg_bit->IER_ELSI = 0U;
|
||||
this_uart->hw_reg_bit->IER_EDSSI = 0U;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
void
|
||||
MSS_UART_set_rx_handler
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
mss_uart_rx_handler_t handler,
|
||||
mss_uart_rx_trig_level_t trigger_level
|
||||
)
|
||||
{
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
this_uart->rx_handler = handler;
|
||||
|
||||
/* Set the receive interrupt trigger level. */
|
||||
this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR & (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) | (uint8_t)trigger_level;
|
||||
|
||||
/* Enable receive interrupt. */
|
||||
this_uart->hw_reg_bit->IER_ERBFI = 1U;
|
||||
|
||||
/* Enable UART instance interrupt in Cortex-M3 NVIC. */
|
||||
NVIC_EnableIRQ( this_uart->irqn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* See mss_uart.h for details of how to use this function.
|
||||
*/
|
||||
void
|
||||
MSS_UART_set_loopback
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
mss_uart_loopback_t loopback
|
||||
)
|
||||
{
|
||||
ASSERT( (this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1) );
|
||||
|
||||
if ( loopback == MSS_UART_LOOPBACK_OFF )
|
||||
{
|
||||
this_uart->hw_reg_bit->MCR_LOOP = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_uart->hw_reg_bit->MCR_LOOP = 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* UART0 interrupt service routine.
|
||||
* UART0_IRQHandler is included within the Cortex-M3 vector table as part of the
|
||||
* Fusion 2 CMSIS.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void UART0_IRQHandler( void )
|
||||
#else
|
||||
void UART0_IRQHandler( void )
|
||||
#endif
|
||||
{
|
||||
MSS_UART_isr( &g_mss_uart0 );
|
||||
NVIC_ClearPendingIRQ( UART0_IRQn );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* UART1 interrupt service routine.
|
||||
* UART2_IRQHandler is included within the Cortex-M3 vector table as part of the
|
||||
* Fusion 2 CMSIS.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
__attribute__((__interrupt__)) void UART1_IRQHandler( void )
|
||||
#else
|
||||
void UART1_IRQHandler( void )
|
||||
#endif
|
||||
{
|
||||
MSS_UART_isr( &g_mss_uart1 );
|
||||
NVIC_ClearPendingIRQ( UART1_IRQn );
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,626 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* (c) Copyright 2007 Actel Corporation. All rights reserved.
|
||||
*
|
||||
* SmartFusion Microcontroller Subsystem UART bare metal software driver public API.
|
||||
*
|
||||
* SVN $Revision: 1942 $
|
||||
* SVN $Date: 2009-12-22 17:48:07 +0000 (Tue, 22 Dec 2009) $
|
||||
*/
|
||||
/*=========================================================================*//**
|
||||
@mainpage SmartFusion MSS UART Bare Metal Driver.
|
||||
|
||||
@section intro_sec Introduction
|
||||
The SmartFusion MicroController Subsystem (MSS) includes two UART peripherals
|
||||
for serial communications.
|
||||
This driver provides a set of functions for controlling the MSS UARTs as part
|
||||
of a bare metal system where no operating system is available. These drivers
|
||||
can be adapted for use as part of an operating system but the implementation
|
||||
of the adaptation layer between this driver and the operating system's driver
|
||||
model is outside the scope of this driver.
|
||||
|
||||
@section hw_dependencies Hardware Flow Dependencies
|
||||
The configuration of all features of the MSS UARTs is covered by this driver
|
||||
with the exception of the SmartFusion IOMUX configuration. SmartFusion allows
|
||||
multiple non-concurrent uses of some external pins through IOMUX configuration.
|
||||
This feature allows optimization of external pin usage by assigning external
|
||||
pins for use by either the microcontroller subsystem or the FPGA fabric. The
|
||||
MSS UARTs serial signals are routed through IOMUXes to the SmartFusion device
|
||||
external pins. These IOMUXes are configured automatically by the MSS
|
||||
configurator tool in the hardware flow correctly when the MSS UARTs are enabled
|
||||
in that tool. You must ensure that the MSS UARTs are enabled by the MSS
|
||||
configurator tool in the hardware flow; otherwise the serial inputs and outputs
|
||||
will not be connected to the chip's external pins. For more information on
|
||||
IOMUX, refer to the IOMUX section of the SmartFusion Datasheet.
|
||||
The base address, register addresses and interrupt number assignment for the MSS
|
||||
UART blocks are defined as constants in the SmartFusion CMSIS-PAL You must ensure
|
||||
that the SmartFusion CMSIS-PAL is either included in the software tool chain used
|
||||
to build your project or is included in your project.
|
||||
|
||||
|
||||
@section theory_op Theory of Operation
|
||||
The MSS UART driver uses the SmartFusion "Cortex Microcontroler Software
|
||||
Interface Standard - Peripheral Access Layer" (CMSIS-PAL) to access hadware
|
||||
registers. You must ensure that the SmartFusion CMSIS-PAL is either included
|
||||
in the software toolchain used to build your project or is included in your
|
||||
project. The most up to date SmartFusion CMSIS-PAL files can be obtained using
|
||||
the Actel Firmware Catalog.
|
||||
|
||||
The MSS UART driver functions are logically grouped into three groups:
|
||||
- Initialization functions
|
||||
- Polled transmit and receive functions
|
||||
- Interrupt driven transmit and receive functions
|
||||
|
||||
The MSS UART driver is initialized through a call to the UART_init() function.
|
||||
This function takes the UART's configuration as parameters. The UART_init()
|
||||
function must be called before any other UART driver functions can be called.
|
||||
The first parameter of the UART_init() function is a pointer to one of two
|
||||
global data structures used to store state information for each UART driver.
|
||||
A pointer to these data structures is also used as first parameter to any of
|
||||
the driver functions to identify which UART will be used by the called
|
||||
function. The name of these two data structures are g_mss_uart0 and
|
||||
g_mss_uart1. Therefore any call to a MSS UART function should be of the form
|
||||
UART_function_name( &g_mss_uart0, ... ) or UART_function_name( &g_mss_uart1, ... ).
|
||||
The two SmartFusion MSS UARTs can also be configured to loop back to each
|
||||
other using the MSS_set_loopback() function for debugging purposes.
|
||||
|
||||
Polled operations where the processor constantly poll the UART registers state
|
||||
in order to control data transmit or data receive is performed using functions:
|
||||
- MSS_UART_polled_tx()
|
||||
- MSS_UART_get_rx()
|
||||
|
||||
Interrupt driven operations where the processor sets up transmit or receive
|
||||
then returns to performing some other operation until an interrupts occurs
|
||||
indicating that its attention is required is performed using functions:
|
||||
- MSS_UART_irq_tx()
|
||||
- MSS_UART_tx_complete()
|
||||
- MSS_UART_set_rx_handler()
|
||||
- MSS_UART_get_rx()
|
||||
Interrupt driven transmit is initiated by a call to MSS_UART_irq_tx() specifying
|
||||
the block of data to transmit. The processor can then perform some other
|
||||
operation and later inquire whether transmit has completed by calling the
|
||||
MSS_UART_tx_complete() function.
|
||||
Interrupt driven receive is performed by first registering a receive handler
|
||||
function that will be called by the driver whenever receive data is available.
|
||||
This receive handler function in turns calls the MSS_UART_get_rx() function to
|
||||
actually read the received data.
|
||||
|
||||
*//*=========================================================================*/
|
||||
#ifndef __MSS_UART_H_
|
||||
#define __MSS_UART_H_ 1
|
||||
|
||||
#include "../../CMSIS/a2fxxxm3.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
Baud rates.
|
||||
The following definitions are used to specify standard baud rates as a
|
||||
parameter to the MSS_UART_init() function.
|
||||
*/
|
||||
#define MSS_UART_110_BAUD 110
|
||||
#define MSS_UART_300_BAUD 300
|
||||
#define MSS_UART_1200_BAUD 1200
|
||||
#define MSS_UART_2400_BAUD 2400
|
||||
#define MSS_UART_4800_BAUD 4800
|
||||
#define MSS_UART_9600_BAUD 9600
|
||||
#define MSS_UART_19200_BAUD 19200
|
||||
#define MSS_UART_38400_BAUD 38400
|
||||
#define MSS_UART_57600_BAUD 57600
|
||||
#define MSS_UART_115200_BAUD 115200
|
||||
#define MSS_UART_230400_BAUD 230400
|
||||
#define MSS_UART_460800_BAUD 460800
|
||||
#define MSS_UART_921600_BAUD 921600
|
||||
|
||||
/***************************************************************************//**
|
||||
Data bits length values.
|
||||
|
||||
The following defines are used to build the value of the MSS_UART_init()
|
||||
function line_config parameter.
|
||||
*/
|
||||
#define MSS_UART_DATA_5_BITS 0x00
|
||||
#define MSS_UART_DATA_6_BITS 0x01
|
||||
#define MSS_UART_DATA_7_BITS 0x02
|
||||
#define MSS_UART_DATA_8_BITS 0x03
|
||||
|
||||
/***************************************************************************//**
|
||||
Parity values
|
||||
The following defines are used to build the value of the MSS_UART_init()
|
||||
function line_config parameter.
|
||||
*/
|
||||
#define MSS_UART_NO_PARITY 0x00
|
||||
#define MSS_UART_ODD_PARITY 0x08
|
||||
#define MSS_UART_EVEN_PARITY 0x18
|
||||
#define MSS_UART_STICK_PARITY_0 0x38
|
||||
#define MSS_UART_STICK_PARITY_1 0x28
|
||||
|
||||
/***************************************************************************//**
|
||||
Stop bit values
|
||||
The following defines are used to build the value of the MSS_UART_init()
|
||||
function line_config parameter.
|
||||
*/
|
||||
#define MSS_UART_ONE_STOP_BIT 0x00
|
||||
#define MSS_UART_ONEHALF_STOP_BIT 0x04
|
||||
#define MSS_UART_TWO_STOP_BITS 0x04
|
||||
|
||||
/***************************************************************************//**
|
||||
FIFO trigger sizes
|
||||
This enumeration specifies the number of bytes that must be received before a
|
||||
receive interrupt is generated. This enumeration provides the allowed values for
|
||||
the MSS_UART_set_rx_handler() function trigger_level parameter.
|
||||
*/
|
||||
typedef enum __mss_uart_rx_trig_level_t {
|
||||
MSS_UART_FIFO_SINGLE_BYTE = 0x00,
|
||||
MSS_UART_FIFO_FOUR_BYTES = 0x40,
|
||||
MSS_UART_FIFO_EIGHT_BYTES = 0x80,
|
||||
MSS_UART_FIFO_FOURTEEN_BYTES = 0xC0
|
||||
} mss_uart_rx_trig_level_t;
|
||||
|
||||
/***************************************************************************//**
|
||||
Loopback.
|
||||
This enumeration is used as parameter to function MSS_UART_set_loopback(). It
|
||||
specifies the loopback configuration of the UARTs. Using MSS_UART_LOOPBACK_ON
|
||||
as parameter to function MSS_UART_set_loopback() will set up the UART to locally
|
||||
loopback its Tx and Rx lines.
|
||||
*/
|
||||
typedef enum __mss_uart_loopback_t {
|
||||
MSS_UART_LOOPBACK_OFF = 0,
|
||||
MSS_UART_LOOPBACK_ON = 1
|
||||
} mss_uart_loopback_t;
|
||||
|
||||
/***************************************************************************//**
|
||||
Receive handler prototype.
|
||||
This typedef specifies the prototype of functions that can be registered with
|
||||
this driver as receive handler functions.
|
||||
*/
|
||||
typedef void (*mss_uart_rx_handler_t)(void);
|
||||
|
||||
/***************************************************************************//**
|
||||
mss_uart_instance_t.
|
||||
|
||||
There is one instance of this structure for each instance of the Microcontroller
|
||||
Subsystem's UARTs. Instances of this structure are used to identify a specific
|
||||
UART. A pointer to an instance of the mss_uart_instance_t structure is passed
|
||||
as the first parameter to MSS UART driver functions to identify which UART
|
||||
should perform the requested operation.
|
||||
*/
|
||||
typedef struct {
|
||||
/* CMSIS related defines identifying the UART hardware. */
|
||||
UART_TypeDef * hw_reg; /*!< Pointer to UART registers. */
|
||||
UART_BitBand_TypeDef * hw_reg_bit; /*!< Pointer to UART registers bit band area. */
|
||||
IRQn_Type irqn; /*!< UART's Cortex-M3 NVIC interrupt number. */
|
||||
|
||||
/* transmit related info (used with interrupt driven trnasmit): */
|
||||
const uint8_t * tx_buffer; /*!< Pointer to transmit buffer. */
|
||||
uint32_t tx_buff_size; /*!< Transmit buffer size. */
|
||||
uint32_t tx_idx; /*!< Index within trnamit buffer of next byte to transmit.*/
|
||||
|
||||
/* receive interrupt handler:*/
|
||||
mss_uart_rx_handler_t rx_handler; /*!< Pointer to user registered received handler. */
|
||||
} mss_uart_instance_t;
|
||||
|
||||
/***************************************************************************//**
|
||||
This instance of mss_uart_instance_t holds all data related to the operations
|
||||
performed by UART0. A pointer to g_mss_uart0 is passed as the first parameter
|
||||
to MSS UART driver functions to indicate that UART0 should perform the requested
|
||||
operation.
|
||||
*/
|
||||
extern mss_uart_instance_t g_mss_uart0;
|
||||
|
||||
/***************************************************************************//**
|
||||
This instance of mss_uart_instance_t holds all data related to the operations
|
||||
performed by UART1. A pointer to g_mss_uart1 is passed as the first parameter
|
||||
to MSS UART driver functions to indicate that UART1 should perform the requested
|
||||
operation.
|
||||
*/
|
||||
extern mss_uart_instance_t g_mss_uart1;
|
||||
|
||||
/***************************************************************************//**
|
||||
The MSS_UART_init() function initializes and configures one of the SmartFusion
|
||||
MSS UARTs with the configuration passed as a parameter. The configuration
|
||||
parameters are the baud_rate which is used to generate the baud value and the
|
||||
line_config which is used to specify the line configuration (bit length, stop
|
||||
bits and parity).
|
||||
|
||||
Example:
|
||||
@code
|
||||
#include "mss_uart.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
MSS_UART_init
|
||||
(
|
||||
&g_mss_uart0,
|
||||
MSS_UART_57600_BAUD,
|
||||
MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT
|
||||
);
|
||||
return(0);
|
||||
}
|
||||
@endcode
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block to be initialized. There are two
|
||||
such data structures, g_mss_uart0 and g_mss_uart1, associated with MSS UART0
|
||||
and MSS UART1 respectively. This parameter must point to either the
|
||||
g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
|
||||
@param baud_rate
|
||||
The baud_rate parameter specifies the baud rate. It can be specified for
|
||||
common baud rates' using the following defines:
|
||||
- MSS_UART_110_BAUD
|
||||
- MSS_UART_300_BAUD
|
||||
- MSS_UART_1200_BAUD
|
||||
- MSS_UART_2400_BAUD
|
||||
- MSS_UART_4800_BAUD
|
||||
- MSS_UART_9600_BAUD
|
||||
- MSS_UART_19200_BAUD
|
||||
- MSS_UART_38400_BAUD
|
||||
- MSS_UART_57600_BAUD
|
||||
- MSS_UART_115200_BAUD
|
||||
- MSS_UART_230400_BAUD
|
||||
- MSS_UART_460800_BAUD
|
||||
- MSS_UART_921600_BAUD
|
||||
Alternatively, any non standard baud rate can be specified by simply passing
|
||||
the actual required baud rate as value for this parameter.
|
||||
|
||||
@param line_config
|
||||
The line_config parameter is the line configuration specifying the bit length,
|
||||
number of stop bits and parity settings. This is a logical OR of one of the
|
||||
following to specify the transmit/receive data bit length:
|
||||
- MSS_UART_DATA_5_BITS
|
||||
- MSS_UART_DATA_6_BITS,
|
||||
- MSS_UART_DATA_7_BITS
|
||||
- MSS_UART_DATA_8_BITS
|
||||
with one of the following to specify the parity setting:
|
||||
- MSS_UART_NO_PARITY
|
||||
- MSS_UART_EVEN_PARITY
|
||||
- MSS_UART_ODD_PARITY
|
||||
- MSS_UART_STICK_PARITY_0
|
||||
- MSS_UART_STICK_PARITY_1
|
||||
with one of the following to specify the number of stop bits:
|
||||
- MSS_UART_ONE_STOP_BIT
|
||||
- MSS_UART_ONEHALF_STOP_BIT
|
||||
- MSS_UART_TWO_STOP_BITS
|
||||
|
||||
@return
|
||||
This function does not return a value.
|
||||
*/
|
||||
void
|
||||
MSS_UART_init
|
||||
(
|
||||
mss_uart_instance_t* this_uart,
|
||||
uint32_t baud_rate,
|
||||
uint8_t line_config
|
||||
);
|
||||
|
||||
/***************************************************************************//**
|
||||
The function MSS_UART_polled_tx() is used to transmit data. It transfers the
|
||||
contents of the transmitter data buffer, passed as a function parameter, into
|
||||
the UART's hardware transmitter FIFO. It returns when the full content of the
|
||||
transmit data buffer has been transferred to the UART's transmit FIFO.
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@param pbuff
|
||||
The pbuff parameter is a pointer to a buffer containing the data to be
|
||||
transmitted.
|
||||
|
||||
@param tx_size
|
||||
The tx_size parameter specifies the size, in bytes, of the data to be
|
||||
transmitted.
|
||||
|
||||
@return This function does not return a value.
|
||||
*/
|
||||
void
|
||||
MSS_UART_polled_tx
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
const uint8_t * pbuff,
|
||||
uint32_t tx_size
|
||||
);
|
||||
|
||||
/***************************************************************************//**
|
||||
The function MSS_UART_polled_tx_string() is used to transmit a zero-terminated
|
||||
string. It transfers the text found starting at the address pointed to by
|
||||
p_sz_string into the UART's hardware transmitter FIFO. It returns when the
|
||||
complete string has been transferred to the UART's transmit FIFO.
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@param p_sz_string
|
||||
The p_sz_string parameter is a pointer to a buffer containing the
|
||||
zero-terminated string to be transmitted.
|
||||
|
||||
@return This function does not return a value.
|
||||
*/
|
||||
void
|
||||
MSS_UART_polled_tx_string
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
const uint8_t * p_sz_string
|
||||
);
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
The function MSS_UART_irq_tx() is used to initiate interrupt driven transmit. It
|
||||
returns immediately after making a note of the transmit buffer location and
|
||||
enabling transmit interrupts both at the UART and Cortex-M3 NVIC level.
|
||||
This function takes a pointer to a memory buffer containing the data to
|
||||
transmit as parameter. The memory buffer specified through this pointer
|
||||
should remain allocated and contain the data to transmit until the transmit
|
||||
completion has been detected through calls to function MSS_UART_tx_complete().
|
||||
NOTE: The MSS_UART_irq_tx() function also enables the Transmitter Holding
|
||||
Register Empty (THRE) interrupt and the UART instance interrupt in the
|
||||
Cortex-M3 NVIC as part of its implementation.
|
||||
|
||||
Example:
|
||||
@code
|
||||
#include "mss_uart.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t tx_buff[10] = "abcdefghi";
|
||||
MSS_UART_init( &g_mss_uart0, MSS_UART_57600_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
|
||||
MSS_UART_irq_tx( &g_mss_uart0, tx_buff, sizeof(tx_buff));
|
||||
while ( 0 == MSS_UART_tx_complete( &g_mss_uart0 ) )
|
||||
{
|
||||
;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@endcode
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@param pbuff
|
||||
The pbuff parameter is a pointer to a buffer containing the data to be
|
||||
transmitted.
|
||||
|
||||
@param tx_size
|
||||
The tx_size parameter specifies the size, in bytes, of the data to be
|
||||
transmitted.
|
||||
|
||||
@return
|
||||
This function does not return a value.
|
||||
*/
|
||||
void
|
||||
MSS_UART_irq_tx
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
const uint8_t * pbuff,
|
||||
uint32_t tx_size
|
||||
);
|
||||
|
||||
/***************************************************************************//**
|
||||
The MSS_UART_tx_complete() function is used to find out if interrupt driven
|
||||
transmit previously initiated through a call to MSS_UART_irq_tx() is complete.
|
||||
This is typically used to find out when it is safe to reuse or release the
|
||||
memory buffer holding transmit data.
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@return
|
||||
This function return a non-zero value if transmit has completed, otherwise
|
||||
it returns zero.
|
||||
|
||||
Example:
|
||||
See the MSS_UART_irq_tx() function for an example that uses the
|
||||
MSS_UART_tx_complete() function.
|
||||
*/
|
||||
int8_t
|
||||
MSS_UART_tx_complete
|
||||
(
|
||||
mss_uart_instance_t * this_uart
|
||||
);
|
||||
|
||||
/***************************************************************************//**
|
||||
The MSS_UART_get_rx() function is used to read the content of a UART's receive
|
||||
FIFO. It can be used in polled mode where it is called at regular interval
|
||||
to find out if any data has been received or in interrupt driven mode where
|
||||
it is called as part of a receive handler called by the driver as a result of
|
||||
data being received. This function is non-blocking and will return 0
|
||||
immediately if no data has been received.
|
||||
NOTE: In interrupt driven mode you should call the MSS_UART_get_rx() function
|
||||
as part of the receive handler function that you register with the MSS UART
|
||||
driver through a call to MSS_UART_set_rx_handler().
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@param rx_buff
|
||||
The rx_buff parameter is a pointer to a buffer where the received data will
|
||||
be copied.
|
||||
|
||||
@param buff_size
|
||||
The buff_size parameter specifies the size of the receive buffer in bytes.
|
||||
|
||||
@return
|
||||
This function return the number of bytes that were copied into the rx_buff
|
||||
buffer. It returns 0 if no data has been received.
|
||||
|
||||
Polled mode example:
|
||||
@code
|
||||
int main( void )
|
||||
{
|
||||
uint8_t rx_buff[RX_BUFF_SIZE];
|
||||
uint32_t rx_idx = 0;
|
||||
|
||||
MSS_UART_init( &g_mss_uart0, MSS_UART_57600_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
rx_size = MSS_UART_get_rx( &g_mss_uart0, rx_buff, sizeof(rx_buff) );
|
||||
if (rx_size > 0)
|
||||
{
|
||||
process_rx_data( rx_buff, rx_size );
|
||||
}
|
||||
task_a();
|
||||
task_b();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Interrupt driven example:
|
||||
@code
|
||||
int main( void )
|
||||
{
|
||||
MSS_UART_init( &g_mss_uart1, MSS_UART_57600_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
|
||||
MSS_UART_set_rx_handler( &g_mss_uart1, uart1_rx_handler, MSS_UART_FIFO_SINGLE_BYTE );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
task_a();
|
||||
task_b();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart1_rx_handler( void )
|
||||
{
|
||||
uint8_t rx_buff[RX_BUFF_SIZE];
|
||||
uint32_t rx_idx = 0;
|
||||
rx_size = MSS_UART_get_rx( &g_mss_uart1, rx_buff, sizeof(rx_buff) );
|
||||
process_rx_data( rx_buff, rx_size );
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
size_t
|
||||
MSS_UART_get_rx
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
uint8_t * rx_buff,
|
||||
size_t buff_size
|
||||
);
|
||||
|
||||
/***************************************************************************//**
|
||||
The MSS_UART_set_rx_handler() function is used to register a receive handler
|
||||
function which will be called by the driver when a UART Received Data Available
|
||||
(RDA) interrupt occurs. You must create and register the handler function to
|
||||
suit your application. The MSS_UART_set_rx_handler() function also enables the UART
|
||||
Received Data Available interrupt and the UART instance interrupt in the
|
||||
Cortex-M3 NVIC as part of its implementation.
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@param handler
|
||||
The handler parameter is a pointer to a receive handler function provided
|
||||
by your application which will be called as a result of a UART Received
|
||||
Data Available interrupt.
|
||||
|
||||
@param trigger_level
|
||||
The trigger_level parameter is the receive FIFO trigger level. This specifies
|
||||
the number of bytes that must be received before the UART triggers a Received
|
||||
Data Available interrupt.
|
||||
|
||||
@return
|
||||
This function does not return a value.
|
||||
|
||||
Example:
|
||||
@code
|
||||
#include "mss_uart.h"
|
||||
|
||||
#define RX_BUFF_SIZE 64
|
||||
|
||||
uint8_t g_rx_buff[RX_BUFF_SIZE];
|
||||
|
||||
void uart0_rx_handler( void )
|
||||
{
|
||||
MSS_UART_get_rx( &g_mss_uart, &g_rx_buff[g_rx_idx], sizeof(g_rx_buff) );
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
MSS_UART_init( &g_mss_uart0, MSS_UART_57600_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
|
||||
MSS_UART_set_rx_handler( &g_mss_uart0, uart0_rx_handler, MSS_UART_FIFO_SINGLE_BYTE );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
void
|
||||
MSS_UART_set_rx_handler
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
mss_uart_rx_handler_t handler,
|
||||
mss_uart_rx_trig_level_t trigger_level
|
||||
);
|
||||
|
||||
/***************************************************************************//**
|
||||
The MSS_UART_set_loopback() function is used to locally loopback the Tx and Rx
|
||||
lines of a UART.
|
||||
This is not to be confused with the loopback of UART0 to UART1 which can be
|
||||
achieved through the microcontroller subsystem's system registers
|
||||
|
||||
@param this_uart
|
||||
The this_uart parameter is a pointer to an mss_uart_instance_t structure
|
||||
identifying the MSS UART hardware block that will perform the requested
|
||||
function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
|
||||
associated with MSS UART0 and MSS UART1. This parameter must point to either
|
||||
the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
|
||||
driver.
|
||||
|
||||
@param loopback
|
||||
The loopback parameter indicates whether or not the UART's transmit and receive lines
|
||||
should be looped back. Allowed values are:
|
||||
- MSS_UART_LOOPBACK_ON
|
||||
- MSS_UART_LOOPBACK_OFF
|
||||
@return
|
||||
This function does not return a value.
|
||||
*/
|
||||
void
|
||||
MSS_UART_set_loopback
|
||||
(
|
||||
mss_uart_instance_t * this_uart,
|
||||
mss_uart_loopback_t loopback
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MSS_UART_H_ */
|
Loading…
Reference in New Issue