mirror of
https://github.com/elua/elua.git
synced 2025-01-25 01:02:54 +08:00
added timers support for STM32 (and enabled XMODEM) plus a few more minor changes
This commit is contained in:
parent
947379c750
commit
41641f657a
@ -35,7 +35,6 @@ pre {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
overflow: auto;
|
||||
float: left;
|
||||
}
|
||||
p.info {
|
||||
margin-left: 3em;
|
||||
|
@ -24,7 +24,7 @@ cdefs = cdefs + " -Dgcc"
|
||||
# Toolset data
|
||||
tools[ 'stm32' ] = {}
|
||||
tools[ 'stm32' ][ 'cccom' ] = "%s -mcpu=cortex-m3 -mthumb -mlittle-endian %s %s -ffunction-sections -fdata-sections -fno-strict-aliasing %s -Wall -c $SOURCE -o $TARGET" % ( toolset[ 'compile' ], opt, local_include, cdefs )
|
||||
tools[ 'stm32' ][ 'linkcom' ] = "%s -mcpu=cortex-m3 -mthumb -Wl,-T -Xlinker %s -u _start -Wl,-e,Reset_Handler -Wl,-static -Wl,--gc-sections -nostartfiles -nostdlib -Wl,-Map -Xlinker project.map -Wl,--allow-multiple-definition -o $TARGET $SOURCES -lc -lgcc -lm %s" % ( toolset[ 'compile' ], ldscript, local_libs )
|
||||
tools[ 'stm32' ][ 'linkcom' ] = "%s -mcpu=cortex-m3 -mthumb -Wl,-T -Xlinker %s -u _start -Wl,-e,Reset_Handler -Wl,-static -Wl,--gc-sections -nostartfiles -nostdlib -Wl,--allow-multiple-definition -o $TARGET $SOURCES -lc -lgcc -lm %s" % ( toolset[ 'compile' ], ldscript, local_libs )
|
||||
tools[ 'stm32' ][ 'ascom' ] = "%s -x assembler-with-cpp %s -mcpu=cortex-m3 -mthumb %s -Wall -c $SOURCE -o $TARGET" % ( toolset[ 'compile' ], local_include, cdefs )
|
||||
|
||||
# Programming function
|
||||
|
@ -29,16 +29,14 @@
|
||||
#include "stm32f10x_spi.h"
|
||||
#include "stm32f10x_systick.h"
|
||||
#include "stm32f10x_flash.h"
|
||||
|
||||
#include "stm32f10x_conf.h"
|
||||
#include "systick.h"
|
||||
|
||||
#define STM32_USE_PIO
|
||||
#define STM32_USE_USART
|
||||
|
||||
void exit(int ret)
|
||||
{
|
||||
while(1);
|
||||
}
|
||||
// Clock data
|
||||
// IMPORTANT: if you change these, make sure to modify RCC_Configuration() too!
|
||||
#define HCLK ( HSE_Value * 9 )
|
||||
#define PCLK1_DIV 2
|
||||
#define PCLK2_DIV 1
|
||||
|
||||
// ****************************************************************************
|
||||
// Platform initialization
|
||||
@ -49,10 +47,7 @@ static void NVIC_Configuration(void);
|
||||
|
||||
static void timers_init();
|
||||
static void uarts_init();
|
||||
static void spis_init();
|
||||
static void pios_init();
|
||||
static void pwms_init();
|
||||
static void eth_init();
|
||||
|
||||
int platform_init()
|
||||
{
|
||||
@ -65,29 +60,14 @@ int platform_init()
|
||||
// Enable SysTick timer.
|
||||
SysTick_Config();
|
||||
|
||||
#ifdef STM32_USE_PIO
|
||||
// Setup PIO
|
||||
pios_init();
|
||||
#endif
|
||||
|
||||
#ifdef STM32_USE_SPI
|
||||
// Setup SPIs
|
||||
//spis_init();
|
||||
#endif
|
||||
|
||||
#ifdef STM32_USE_USART
|
||||
// Setup UARTs
|
||||
uarts_init();
|
||||
#endif
|
||||
|
||||
|
||||
// Setup timers
|
||||
//timers_init();
|
||||
|
||||
// Setup PWMs
|
||||
//pwms_init();
|
||||
|
||||
// Setup ethernet (TCP/IP)
|
||||
//eth_init();
|
||||
timers_init();
|
||||
|
||||
cmn_platform_init();
|
||||
|
||||
@ -172,8 +152,6 @@ static void RCC_Configuration(void)
|
||||
*******************************************************************************/
|
||||
static void NVIC_Configuration(void)
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
|
||||
NVIC_DeInit();
|
||||
|
||||
#ifdef VECT_TAB_RAM
|
||||
@ -195,7 +173,6 @@ static void NVIC_Configuration(void)
|
||||
// PIO
|
||||
// This is pretty much common code to all STM32 devices.
|
||||
// todo: Needs updates to support different processor lines.
|
||||
#ifdef STM32_USE_PIO
|
||||
static GPIO_TypeDef * const pio_port[] = { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG };
|
||||
static const u32 pio_port_clk[] = { RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG };
|
||||
|
||||
@ -291,86 +268,17 @@ pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32_USE_SPI
|
||||
// ****************************************************************************
|
||||
// SPI
|
||||
// TODO: Just about everything.
|
||||
|
||||
static const u32 spi_base[] = { SSI0_BASE, SSI1_BASE };
|
||||
static const u32 spi_sysctl[] = { SYSCTL_PERIPH_SSI0, SYSCTL_PERIPH_SSI1 };
|
||||
static const u32 spi_gpio_base[] = { GPIO_PORTA_BASE | GPIO_PORTE_BASE };
|
||||
static const u8 spi_gpio_pins[] = { GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5,
|
||||
GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 };
|
||||
// SSIxClk SSIxFss SSIxRx SSIxTx
|
||||
static const u8 spi_gpio_clk_pin[] = { GPIO_PIN_2, GPIO_PIN_0 };
|
||||
#define SPIS_COUNT 1
|
||||
|
||||
static void spis_init()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for( i = 0; i < SPIS_COUNT; i ++ )
|
||||
{
|
||||
SysCtlPeripheralEnable(spi_sysctl[ i ]);
|
||||
}
|
||||
}
|
||||
|
||||
int platform_spi_exists( unsigned id )
|
||||
{
|
||||
return id < SPIS_COUNT;
|
||||
}
|
||||
|
||||
u32 platform_spi_setup( unsigned id, int mode, u32 clock, unsigned cpol, unsigned cpha, unsigned databits )
|
||||
{
|
||||
unsigned protocol;
|
||||
|
||||
if( cpol == 0 )
|
||||
protocol = cpha ? SSI_FRF_MOTO_MODE_1 : SSI_FRF_MOTO_MODE_0;
|
||||
else
|
||||
protocol = cpha ? SSI_FRF_MOTO_MODE_3 : SSI_FRF_MOTO_MODE_2;
|
||||
mode = mode == PLATFORM_SPI_MASTER ? SSI_MODE_MASTER : SSI_MODE_SLAVE;
|
||||
SSIDisable( spi_base[ id ] );
|
||||
|
||||
GPIOPinTypeSSI( spi_gpio_base[ id ], spi_gpio_pins[ id ] );
|
||||
|
||||
// FIXME: not sure this is always "right"
|
||||
GPIOPadConfigSet(spi_gpio_base[ id ], spi_gpio_clk_pin[ id ], GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU);
|
||||
|
||||
SSIConfigSetExpClk( spi_base[ id ], SysCtlClockGet(), protocol, mode, clock, databits );
|
||||
SSIEnable( spi_base[ id ] );
|
||||
return clock;
|
||||
}
|
||||
|
||||
spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data )
|
||||
{
|
||||
SSIDataPut( spi_base[ id ], data );
|
||||
SSIDataGet( spi_base[ id ], &data );
|
||||
return data;
|
||||
}
|
||||
|
||||
void platform_spi_select( unsigned id, int is_select )
|
||||
{
|
||||
// This platform doesn't have a hardware SS pin, so there's nothing to do here
|
||||
id = id;
|
||||
is_select = is_select;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32_USE_USART
|
||||
// ****************************************************************************
|
||||
// UART
|
||||
// TODO: Support timeouts.
|
||||
|
||||
// All possible STM32 uarts defs
|
||||
static USART_TypeDef * usart[] = { USART1, USART2, USART3, UART4 };
|
||||
static GPIO_TypeDef * usart_gpio_port[] = { GPIOA, GPIOA, GPIOB, GPIOC };
|
||||
static const u16 usart_gpio_tx_pin[] = { GPIO_Pin_9, GPIO_Pin_2, GPIO_Pin_10, GPIO_Pin_10 };
|
||||
static const u16 usart_gpio_rx_pin[] = { GPIO_Pin_10, GPIO_Pin_3, GPIO_Pin_11, GPIO_Pin_11 };
|
||||
//static const u32 uart_sysctl[] = { SYSCTL_PERIPH_UART0, SYSCTL_PERIPH_UART1, SYSCTL_PERIPH_UART2 };
|
||||
//static const u32 uart_gpio_base[] = { _BASE, GPIO_PORTD_BASE, GPIO_PORTG_BASE };
|
||||
//static const u8 uart_gpio_pins[] = { GPIO_PIN_0 | GPIO_PIN_1, GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_0 | GPIO_PIN_1 };
|
||||
static USART_TypeDef *const usart[] = { USART1, USART2, USART3, UART4, UART5 };
|
||||
static GPIO_TypeDef *const usart_gpio_rx_port[] = { GPIOA, GPIOA, GPIOB, GPIOC, GPIOD };
|
||||
static GPIO_TypeDef *const usart_gpio_tx_port[] = { GPIOA, GPIOA, GPIOB, GPIOC, GPIOC };
|
||||
static const u16 usart_gpio_rx_pin[] = { GPIO_Pin_10, GPIO_Pin_3, GPIO_Pin_11, GPIO_Pin_11, GPIO_Pin_2 };
|
||||
static const u16 usart_gpio_tx_pin[] = { GPIO_Pin_9, GPIO_Pin_2, GPIO_Pin_10, GPIO_Pin_10, GPIO_Pin_12 };
|
||||
|
||||
static void usart_init(u32 id, USART_InitTypeDef * initVals)
|
||||
{
|
||||
@ -381,12 +289,12 @@ static void usart_init(u32 id, USART_InitTypeDef * initVals)
|
||||
GPIO_InitStructure.GPIO_Pin = usart_gpio_tx_pin[id];
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_Init(usart_gpio_port[id], &GPIO_InitStructure);
|
||||
GPIO_Init(usart_gpio_tx_port[id], &GPIO_InitStructure);
|
||||
|
||||
/* Configure USART Rx Pin as input floating */
|
||||
GPIO_InitStructure.GPIO_Pin = usart_gpio_rx_pin[id];
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_Init(usart_gpio_port[id], &GPIO_InitStructure);
|
||||
GPIO_Init(usart_gpio_rx_port[id], &GPIO_InitStructure);
|
||||
|
||||
/* Configure USART */
|
||||
USART_Init(usart[id], initVals);
|
||||
@ -395,7 +303,7 @@ static void usart_init(u32 id, USART_InitTypeDef * initVals)
|
||||
//USART_ITConfig(usart[id], USART_IT_RXNE, ENABLE);
|
||||
//USART_ITConfig(usart[id], USART_IT_TXE, ENABLE);
|
||||
|
||||
/* Enable the USART1 */
|
||||
/* Enable USART */
|
||||
USART_Cmd(usart[id], ENABLE);
|
||||
}
|
||||
|
||||
@ -409,7 +317,7 @@ static void uarts_init()
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
|
||||
|
||||
// Configure the U(S)ART for 115,200, 8-N-1 operation.
|
||||
// Configure the U(S)ART
|
||||
|
||||
USART_InitStructure.USART_BaudRate = CON_UART_SPEED;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
@ -498,86 +406,90 @@ int platform_s_uart_recv( unsigned id, s32 timeout )
|
||||
while(USART_GetFlagStatus(usart[id], USART_FLAG_RXNE) == RESET);
|
||||
return USART_ReceiveData(usart[id]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32_USE_TIMERS
|
||||
// ****************************************************************************
|
||||
// Timers
|
||||
|
||||
// All possible LM3S timers defs
|
||||
static TIM_TypeDef * timer[] = { TIM2, TIM3, TIM4, TIM5};
|
||||
// We leave out TIM6/TIM for now, as they are dedicated
|
||||
static TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5, TIM8 };
|
||||
#define TIM_GET_BASE_CLK( id ) ( ( id ) == 0 || ( id ) == 5 ? ( HCLK / PCLK2_DIV ) : ( HCLK / PCLK1_DIV ) )
|
||||
#define TIM_STARTUP_CLOCK 50000
|
||||
|
||||
static void timers_init()
|
||||
{
|
||||
#if 0
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
unsigned i;
|
||||
|
||||
// Enable clocks.
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4, ENABLE );
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM5, ENABLE );
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM8, ENABLE );
|
||||
|
||||
// Configure timers
|
||||
for( i = 0; i < NUM_TIMER; i ++ )
|
||||
{
|
||||
SysCtlPeripheralEnable(timer_sysctl[ i ]);
|
||||
TimerConfigure(timer_base[ i ], TIMER_CFG_32_BIT_PER);
|
||||
TimerEnable(timer_base[ i ], TIMER_A);
|
||||
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = TIM_GET_BASE_CLK( i ) / TIM_STARTUP_CLOCK;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;
|
||||
TIM_TimeBaseInit( timer[ i ], &TIM_TimeBaseStructure );
|
||||
TIM_Cmd( timer[ i ], ENABLE );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static u32 platform_timer_get_clock(unsigned id)
|
||||
static u32 timer_get_clock( unsigned id )
|
||||
{
|
||||
RCC_ClocksTypeDef Clocks;
|
||||
TIM_TypeDef* ptimer = timer[ id ];
|
||||
|
||||
RCC_GetClocksFreq(&Clocks);
|
||||
|
||||
return Clocks.PCLK1_Frequency / (TIM_GetPrescaler(timer[id]) + 1)
|
||||
return TIM_GET_BASE_CLK( id ) / ( TIM_GetPrescaler( ptimer ) + 1 );
|
||||
}
|
||||
|
||||
static u32 platform_timer_set_clock(unsigned id, u32 clock)
|
||||
static u32 timer_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
RCC_ClocksTypeDef Clocks;
|
||||
u32 pclk, clkdiv;
|
||||
u64 tmp;
|
||||
|
||||
RCC_GetClocksFreq(&Clocks);
|
||||
|
||||
pclk = Clocks.PCLK1_Frequency; // Get peripheral bus clock frequency.
|
||||
tmp = ((u64)pclk << 16) / clock; // Convert to u32.16 fixed point and calculate prescaler divisor
|
||||
clkdiv = ((tmp & 0x8000) ? (tmp + 0x10000) : tmp) >> 16; // Round up or down and convert back to u32.0
|
||||
if (clkdiv > 0x10000) // Saturate to u16 (+1 for a clkdiv value of 1 is a reg value of 0)
|
||||
clkdiv = 0x10000;
|
||||
|
||||
TIM_PrescalerConfig(timer[id], clkdiv - 1, TIM_PSCReloadMode_Immediate); // Update timer prescaler immediately
|
||||
|
||||
return pclk / clkdiv; // Return actual clock rate used.
|
||||
TIM_TypeDef *ptimer = timer[ id ];
|
||||
u16 pre;
|
||||
|
||||
pre = TIM_GET_BASE_CLK( id ) / clock;
|
||||
TIM_PrescalerConfig( ptimer, pre, TIM_PSCReloadMode_Immediate );
|
||||
return TIM_GET_BASE_CLK( id ) / pre;
|
||||
}
|
||||
|
||||
void platform_s_timer_delay( unsigned id, u32 delay_us )
|
||||
{
|
||||
TIM_TypeDef *ptimer = timer[ id ];
|
||||
volatile unsigned dummy;
|
||||
timer_data_type final;
|
||||
u32 base = timer_base[ id ];
|
||||
|
||||
final = 0xFFFFFFFF - ( ( ( u64 )delay_us * SysCtlClockGet() ) / 1000000 );
|
||||
TimerLoadSet( base, TIMER_A, 0xFFFFFFFF );
|
||||
while( TimerValueGet( base, TIMER_A ) > final );
|
||||
final = ( ( u64 )delay_us * timer_get_clock( id ) ) / 1000000;
|
||||
TIM_SetCounter( ptimer, 0 );
|
||||
for( dummy = 0; dummy < 200; dummy ++ );
|
||||
while( TIM_GetCounter( ptimer ) < final );
|
||||
}
|
||||
|
||||
u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
{
|
||||
u32 res = 0;
|
||||
u32 base = timer_base[ id ];
|
||||
TIM_TypeDef *ptimer = timer[ id ];
|
||||
volatile unsigned dummy;
|
||||
|
||||
data = data;
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_TIMER_OP_START:
|
||||
res = 0xFFFFFFFF;
|
||||
TimerLoadSet( base, TIMER_A, 0xFFFFFFFF );
|
||||
TIM_SetCounter( ptimer, 0 );
|
||||
for( dummy = 0; dummy < 200; dummy ++ );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_READ:
|
||||
res = TimerValueGet( base, TIMER_A );
|
||||
res = TIM_GetCounter( ptimer );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 0xFFFFFFFF );
|
||||
res = platform_timer_get_diff_us( id, 0, 0xFFFF );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
|
||||
@ -585,122 +497,16 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
res = timer_set_clock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_CLOCK:
|
||||
res = SysCtlClockGet();
|
||||
res = timer_get_clock( id );
|
||||
break;
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32_USE_PWM
|
||||
// ****************************************************************************
|
||||
// PWMs
|
||||
// TODO: Everything.
|
||||
|
||||
#define PLATFORM_NUM_PWMS 6
|
||||
|
||||
// SYSCTL div data and actual div factors
|
||||
const static u32 pwm_div_ctl[] = { SYSCTL_PWMDIV_1, SYSCTL_PWMDIV_2, SYSCTL_PWMDIV_4, SYSCTL_PWMDIV_8, SYSCTL_PWMDIV_16, SYSCTL_PWMDIV_32, SYSCTL_PWMDIV_64 };
|
||||
const static u8 pwm_div_data[] = { 1, 2, 4, 8, 16, 32, 64 };
|
||||
// Port/pin information for all channels
|
||||
const static u32 pwm_ports[] = { GPIO_PORTF_BASE, GPIO_PORTG_BASE, GPIO_PORTB_BASE, GPIO_PORTB_BASE, GPIO_PORTE_BASE, GPIO_PORTE_BASE };
|
||||
const static u8 pwm_pins[] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_0, GPIO_PIN_1 };
|
||||
// PWM generators
|
||||
const static u16 pwm_gens[] = { PWM_GEN_0, PWM_GEN_1, PWM_GEN_2 };
|
||||
// PWM outputs
|
||||
const static u16 pwm_outs[] = { PWM_OUT_0, PWM_OUT_1, PWM_OUT_2, PWM_OUT_3, PWM_OUT_4, PWM_OUT_5 };
|
||||
|
||||
static void pwms_init()
|
||||
{
|
||||
SysCtlPeripheralEnable( SYSCTL_PERIPH_PWM );
|
||||
SysCtlPWMClockSet( SYSCTL_PWMDIV_1 );
|
||||
}
|
||||
|
||||
// Helper function: return the PWM clock
|
||||
static u32 platform_pwm_get_clock()
|
||||
{
|
||||
unsigned i;
|
||||
u32 clk;
|
||||
|
||||
clk = SysCtlPWMClockGet();
|
||||
for( i = 0; i < sizeof( pwm_div_ctl ) / sizeof( u32 ); i ++ )
|
||||
if( clk == pwm_div_ctl[ i ] )
|
||||
break;
|
||||
return SysCtlClockGet() / pwm_div_data[ i ];
|
||||
}
|
||||
|
||||
// Helper function: set the PWM clock
|
||||
static u32 platform_pwm_set_clock( u32 clock )
|
||||
{
|
||||
unsigned i, min_i;
|
||||
u32 sysclk;
|
||||
|
||||
sysclk = SysCtlClockGet();
|
||||
for( i = min_i = 0; i < sizeof( pwm_div_data ) / sizeof( u8 ); i ++ )
|
||||
if( ABSDIFF( clock, sysclk / pwm_div_data[ i ] ) < ABSDIFF( clock, sysclk / pwm_div_data[ min_i ] ) )
|
||||
min_i = i;
|
||||
SysCtlPWMClockSet( pwm_div_ctl[ min_i ] );
|
||||
return sysclk / pwm_div_data[ min_i ];
|
||||
}
|
||||
|
||||
int platform_pwm_exists( unsigned id )
|
||||
{
|
||||
return id < PLATFORM_NUM_PWMS;
|
||||
}
|
||||
|
||||
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
{
|
||||
u32 pwmclk = platform_pwm_get_clock();
|
||||
u32 period;
|
||||
|
||||
// Set pin as PWM
|
||||
GPIOPinTypePWM( pwm_ports[ id ], pwm_pins[ id ] );
|
||||
// Compute period
|
||||
period = pwmclk / frequency;
|
||||
// Set the period
|
||||
PWMGenConfigure( PWM_BASE, pwm_gens[ id >> 1 ], PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC );
|
||||
PWMGenPeriodSet( PWM_BASE, pwm_gens[ id >> 1 ], period );
|
||||
// Set duty cycle
|
||||
PWMPulseWidthSet( PWM_BASE, pwm_outs[ id ], ( period * duty ) / 100 );
|
||||
// Return actual frequency
|
||||
return pwmclk / period;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
{
|
||||
u32 res = 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock();
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
PWMOutputState( PWM_BASE, 1 << id, true );
|
||||
PWMGenEnable( PWM_BASE, pwm_gens[ id >> 1 ] );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
PWMOutputState( PWM_BASE, 1 << id, false );
|
||||
PWMGenDisable( PWM_BASE, pwm_gens[ id >> 1 ] );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU specific functions
|
||||
@ -717,169 +523,6 @@ void platform_cpu_disable_interrupts()
|
||||
|
||||
u32 platform_s_cpu_get_frequency()
|
||||
{
|
||||
RCC_ClocksTypeDef clocks;
|
||||
|
||||
RCC_GetClocksFreq(&clocks);
|
||||
|
||||
return clocks.HCLK_Frequency;
|
||||
return HCLK;
|
||||
}
|
||||
|
||||
u32 platform_pclk1_get_frequency()
|
||||
{
|
||||
RCC_ClocksTypeDef clocks;
|
||||
|
||||
RCC_GetClocksFreq(&clocks);
|
||||
|
||||
return clocks.PCLK1_Frequency;
|
||||
}
|
||||
|
||||
u32 platform_pclk2_get_frequency()
|
||||
{
|
||||
RCC_ClocksTypeDef clocks;
|
||||
|
||||
RCC_GetClocksFreq(&clocks);
|
||||
|
||||
return clocks.PCLK2_Frequency;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Ethernet functions
|
||||
|
||||
static void eth_init()
|
||||
{
|
||||
#ifdef BUILD_UIP
|
||||
u32 user0, user1, temp;
|
||||
static struct uip_eth_addr sTempAddr;
|
||||
|
||||
// Enable and reset the controller
|
||||
SysCtlPeripheralEnable( SYSCTL_PERIPH_ETH );
|
||||
SysCtlPeripheralReset( SYSCTL_PERIPH_ETH );
|
||||
|
||||
// Enable Ethernet LEDs
|
||||
GPIODirModeSet( GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3, GPIO_DIR_MODE_HW );
|
||||
GPIOPadConfigSet( GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD );
|
||||
|
||||
// Configure SysTick for a periodic interrupt.
|
||||
SysTickPeriodSet(SysCtlClockGet() / SYSTICKHZ);
|
||||
SysTickEnable();
|
||||
SysTickIntEnable();
|
||||
|
||||
// Intialize the Ethernet Controller and disable all Ethernet Controller interrupt sources.
|
||||
EthernetIntDisable(ETH_BASE, (ETH_INT_PHY | ETH_INT_MDIO | ETH_INT_RXER |
|
||||
ETH_INT_RXOF | ETH_INT_TX | ETH_INT_TXER | ETH_INT_RX));
|
||||
temp = EthernetIntStatus(ETH_BASE, false);
|
||||
EthernetIntClear(ETH_BASE, temp);
|
||||
|
||||
// Initialize the Ethernet Controller for operation.
|
||||
EthernetInitExpClk(ETH_BASE, SysCtlClockGet());
|
||||
|
||||
// Configure the Ethernet Controller for normal operation.
|
||||
// - Full Duplex
|
||||
// - TX CRC Auto Generation
|
||||
// - TX Padding Enabled
|
||||
EthernetConfigSet(ETH_BASE, (ETH_CFG_TX_DPLXEN | ETH_CFG_TX_CRCEN |
|
||||
ETH_CFG_TX_PADEN));
|
||||
|
||||
// Enable the Ethernet Controller.
|
||||
EthernetEnable(ETH_BASE);
|
||||
|
||||
// Enable the Ethernet interrupt.
|
||||
IntEnable(INT_ETH);
|
||||
|
||||
// Enable the Ethernet RX Packet interrupt source.
|
||||
EthernetIntEnable(ETH_BASE, ETH_INT_RX);
|
||||
|
||||
// Enable all processor interrupts.
|
||||
IntMasterEnable();
|
||||
|
||||
// Configure the hardware MAC address for Ethernet Controller filtering of
|
||||
// incoming packets.
|
||||
//
|
||||
// For the Ethernet Eval Kits, the MAC address will be stored in the
|
||||
// non-volatile USER0 and USER1 registers. These registers can be read
|
||||
// using the FlashUserGet function, as illustrated below.
|
||||
FlashUserGet(&user0, &user1);
|
||||
|
||||
// Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
|
||||
// address needed to program the hardware registers, then program the MAC
|
||||
// address into the Ethernet Controller registers.
|
||||
sTempAddr.addr[0] = ((user0 >> 0) & 0xff);
|
||||
sTempAddr.addr[1] = ((user0 >> 8) & 0xff);
|
||||
sTempAddr.addr[2] = ((user0 >> 16) & 0xff);
|
||||
sTempAddr.addr[3] = ((user1 >> 0) & 0xff);
|
||||
sTempAddr.addr[4] = ((user1 >> 8) & 0xff);
|
||||
sTempAddr.addr[5] = ((user1 >> 16) & 0xff);
|
||||
|
||||
// Program the hardware with it's MAC address (for filtering).
|
||||
EthernetMACAddrSet(ETH_BASE, (unsigned char *)&sTempAddr);
|
||||
|
||||
// Initialize the eLua uIP layer
|
||||
elua_uip_init( &sTempAddr );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
static int eth_timer_fired;
|
||||
|
||||
void platform_eth_send_packet( const void* src, u32 size )
|
||||
{
|
||||
EthernetPacketPut( ETH_BASE, uip_buf, uip_len );
|
||||
}
|
||||
|
||||
u32 platform_eth_get_packet_nb( void* buf, u32 maxlen )
|
||||
{
|
||||
return EthernetPacketGetNonBlocking( ETH_BASE, uip_buf, sizeof( uip_buf ) );
|
||||
}
|
||||
|
||||
void platform_eth_force_interrupt()
|
||||
{
|
||||
HWREG( NVIC_SW_TRIG) |= INT_ETH - 16;
|
||||
}
|
||||
|
||||
u32 platform_eth_get_elapsed_time()
|
||||
{
|
||||
if( eth_timer_fired )
|
||||
{
|
||||
eth_timer_fired = 0;
|
||||
return SYSTICKMS;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SysTickHandler(void)
|
||||
{
|
||||
// Indicate that a SysTick interrupt has occurred.
|
||||
eth_timer_fired = 1;
|
||||
|
||||
// Generate a fake Ethernet interrupt. This will perform the actual work
|
||||
// of incrementing the timers and taking the appropriate actions.
|
||||
platform_eth_force_interrupt();
|
||||
}
|
||||
#endif
|
||||
|
||||
void EthernetIntHandler()
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
// Read and Clear the interrupt.
|
||||
temp = EthernetIntStatus( ETH_BASE, false );
|
||||
EthernetIntClear( ETH_BASE, temp );
|
||||
|
||||
// Call the UIP main loop
|
||||
elua_uip_mainloop();
|
||||
}
|
||||
|
||||
#else // #ifdef ELUA_UIP
|
||||
|
||||
#if 0
|
||||
void SysTickHandler()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void EthernetIntHandler()
|
||||
{
|
||||
}
|
||||
#endif // #ifdef ELUA_UIP
|
||||
|
@ -6,11 +6,12 @@
|
||||
#include "auxmods.h"
|
||||
#include "type.h"
|
||||
#include "stacks.h"
|
||||
#include "stm32f10x_lib.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// Define here what components you want for this platform
|
||||
|
||||
//#define BUILD_XMODEM
|
||||
#define BUILD_XMODEM
|
||||
#define BUILD_SHELL
|
||||
#define BUILD_ROMFS
|
||||
#define BUILD_TERM
|
||||
@ -50,6 +51,7 @@ LUALIB_API int ( luaopen_lcd )( lua_State* L );
|
||||
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
|
||||
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
|
||||
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
LCDLINE\
|
||||
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )
|
||||
|
||||
@ -87,8 +89,8 @@ LUALIB_API int ( luaopen_lcd )( lua_State* L );
|
||||
// Number of resources (0 if not available/not implemented)
|
||||
#define NUM_PIO 7
|
||||
#define NUM_SPI 0
|
||||
#define NUM_UART 4
|
||||
#define NUM_TIMER 0
|
||||
#define NUM_UART 5
|
||||
#define NUM_TIMER 6
|
||||
#define NUM_PWM 0
|
||||
#define NUM_ADC 0
|
||||
|
||||
@ -102,7 +104,7 @@ u32 platform_s_cpu_get_frequency();
|
||||
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
|
||||
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
|
||||
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
|
||||
#define PIO_PIN_ARRAY { 16, 16, 16, 16, 16, 16, 16 }
|
||||
#define PIO_PINS_PER_PORT 16
|
||||
|
||||
// Allocator data: define your free memory zones here in two arrays
|
||||
// (start address and end address)
|
||||
@ -110,61 +112,5 @@ u32 platform_s_cpu_get_frequency();
|
||||
#define MEM_START_ADDRESS { ( void* )end }
|
||||
#define MEM_END_ADDRESS { ( void* )( SRAM_BASE + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU constants that should be exposed to the eLua "cpu" module
|
||||
|
||||
#include "stm32f10x_gpio.h"
|
||||
|
||||
#if 0
|
||||
#define PLATFORM_CPU_CONSTANTS\
|
||||
_C( INT_GPIOA ),\
|
||||
_C( INT_GPIOB ),\
|
||||
_C( INT_GPIOC ),\
|
||||
_C( INT_GPIOD ),\
|
||||
_C( INT_GPIOE ),\
|
||||
_C( INT_UART0 ),\
|
||||
_C( INT_UART1 ),\
|
||||
_C( INT_SSI0 ),\
|
||||
_C( INT_I2C0 ),\
|
||||
_C( INT_PWM_FAULT ),\
|
||||
_C( INT_PWM0 ),\
|
||||
_C( INT_PWM1 ),\
|
||||
_C( INT_PWM2 ),\
|
||||
_C( INT_QEI0 ),\
|
||||
_C( INT_ADC0 ),\
|
||||
_C( INT_ADC1 ),\
|
||||
_C( INT_ADC2 ),\
|
||||
_C( INT_ADC3 ),\
|
||||
_C( INT_WATCHDOG ),\
|
||||
_C( INT_TIMER0A ),\
|
||||
_C( INT_TIMER0B ),\
|
||||
_C( INT_TIMER1A ),\
|
||||
_C( INT_TIMER1B ),\
|
||||
_C( INT_TIMER2A ),\
|
||||
_C( INT_TIMER2B ),\
|
||||
_C( INT_COMP0 ),\
|
||||
_C( INT_COMP1 ),\
|
||||
_C( INT_COMP2 ),\
|
||||
_C( INT_SYSCTL ),\
|
||||
_C( INT_FLASH ),\
|
||||
_C( INT_GPIOF ),\
|
||||
_C( INT_GPIOG ),\
|
||||
_C( INT_GPIOH ),\
|
||||
_C( INT_UART2 ),\
|
||||
_C( INT_SSI1 ),\
|
||||
_C( INT_TIMER3A ),\
|
||||
_C( INT_TIMER3B ),\
|
||||
_C( INT_I2C1 ),\
|
||||
_C( INT_QEI1 ),\
|
||||
_C( INT_CAN0 ),\
|
||||
_C( INT_CAN1 ),\
|
||||
_C( INT_CAN2 ),\
|
||||
_C( INT_ETH ),\
|
||||
_C( INT_HIBERNATE ),\
|
||||
_C( INT_USB0 ),\
|
||||
_C( INT_PWM3 ),\
|
||||
_C( INT_UDMA ),\
|
||||
_C( INT_UDMAERR )
|
||||
#endif
|
||||
|
||||
#endif // #ifndef __PLATFORM_CONF_H__
|
||||
|
||||
|
56
src/xmodem.c
56
src/xmodem.c
@ -38,23 +38,23 @@
|
||||
#include "platform_conf.h"
|
||||
#ifdef BUILD_XMODEM
|
||||
|
||||
#define PACKET_SIZE 128
|
||||
#define PXM_ACKET_SIZE 128
|
||||
static p_xm_send_func xmodem_out_func;
|
||||
static p_xm_recv_func xmodem_in_func;
|
||||
|
||||
// Line control codes
|
||||
#define SOH 0x01
|
||||
#define ACK 0x06
|
||||
#define NAK 0x15
|
||||
#define CAN 0x18
|
||||
#define EOT 0x04
|
||||
#define XM_SOH 0x01
|
||||
#define XM_ACK 0x06
|
||||
#define XM_NAK 0x15
|
||||
#define XM_CAN 0x18
|
||||
#define XM_EOT 0x04
|
||||
|
||||
// Arguments to xmodem_flush
|
||||
#define XMODEM_FLUSH_ONLY 0
|
||||
#define XMODEM_FLUSH_AND_CAN 1
|
||||
#define XMODEM_FLUSH_AND_XM_CAN 1
|
||||
|
||||
// Delay in "flush packet" mode
|
||||
#define XMODEM_PACKET_DELAY 10000UL
|
||||
#define XMODEM_PXM_ACKET_DELAY 10000UL
|
||||
|
||||
void xmodem_init( p_xm_send_func send_func, p_xm_recv_func recv_func )
|
||||
{
|
||||
@ -65,12 +65,12 @@ void xmodem_init( p_xm_send_func send_func, p_xm_recv_func recv_func )
|
||||
// Utility function: flush the receive buffer
|
||||
static void xmodem_flush( int how )
|
||||
{
|
||||
while( xmodem_in_func( XMODEM_PACKET_DELAY ) != -1 );
|
||||
if( how == XMODEM_FLUSH_AND_CAN )
|
||||
while( xmodem_in_func( XMODEM_PXM_ACKET_DELAY ) != -1 );
|
||||
if( how == XMODEM_FLUSH_AND_XM_CAN )
|
||||
{
|
||||
xmodem_out_func( CAN );
|
||||
xmodem_out_func( CAN );
|
||||
xmodem_out_func( CAN );
|
||||
xmodem_out_func( XM_CAN );
|
||||
xmodem_out_func( XM_CAN );
|
||||
xmodem_out_func( XM_CAN );
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ static int xmodem_get_record( unsigned char blocknum, unsigned char *pbuf )
|
||||
int ch;
|
||||
|
||||
// Read packet
|
||||
for( j = 0; j < PACKET_SIZE + 4; j ++ )
|
||||
for( j = 0; j < PXM_ACKET_SIZE + 4; j ++ )
|
||||
{
|
||||
if( ( ch = xmodem_in_func( XMODEM_TIMEOUT ) ) == -1 )
|
||||
goto err;
|
||||
@ -95,7 +95,7 @@ static int xmodem_get_record( unsigned char blocknum, unsigned char *pbuf )
|
||||
if( *pbuf ++ != ( unsigned char )~blocknum )
|
||||
goto err;
|
||||
// Check CRC
|
||||
for( size = chk = 0; size < PACKET_SIZE; size++, pbuf ++ )
|
||||
for( size = chk = 0; size < PXM_ACKET_SIZE; size++, pbuf ++ )
|
||||
{
|
||||
chk = chk ^ *pbuf << 8;
|
||||
for( j = 0; j < 8; j ++ )
|
||||
@ -114,7 +114,7 @@ static int xmodem_get_record( unsigned char blocknum, unsigned char *pbuf )
|
||||
return 1;
|
||||
|
||||
err:
|
||||
xmodem_out_func( NAK );
|
||||
xmodem_out_func( XM_NAK );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ err:
|
||||
long xmodem_receive( char **dest )
|
||||
{
|
||||
int starting = 1, ch;
|
||||
unsigned char packnum = 1, buf[ PACKET_SIZE + 4 ];
|
||||
unsigned char packnum = 1, buf[ PXM_ACKET_SIZE + 4 ];
|
||||
unsigned retries = XMODEM_RETRY_LIMIT;
|
||||
u32 limit = XMODEM_INITIAL_BUFFER_SIZE, size = 0;
|
||||
void *p;
|
||||
@ -133,19 +133,19 @@ long xmodem_receive( char **dest )
|
||||
{
|
||||
if( starting )
|
||||
xmodem_out_func( 'C' );
|
||||
if( ( ( ch = xmodem_in_func( XMODEM_TIMEOUT ) ) == -1 ) || ( ch != SOH && ch != EOT && ch != CAN ) )
|
||||
if( ( ( ch = xmodem_in_func( XMODEM_TIMEOUT ) ) == -1 ) || ( ch != XM_SOH && ch != XM_EOT && ch != XM_CAN ) )
|
||||
continue;
|
||||
if( ch == EOT )
|
||||
if( ch == XM_EOT )
|
||||
{
|
||||
// End of transmission
|
||||
xmodem_out_func( ACK );
|
||||
xmodem_out_func( XM_ACK );
|
||||
xmodem_flush( XMODEM_FLUSH_ONLY );
|
||||
return size;
|
||||
}
|
||||
else if( ch == CAN )
|
||||
else if( ch == XM_CAN )
|
||||
{
|
||||
// The remote part ended the transmission
|
||||
xmodem_out_func( ACK );
|
||||
xmodem_out_func( XM_ACK );
|
||||
xmodem_flush( XMODEM_FLUSH_ONLY );
|
||||
return XMODEM_ERROR_REMOTECANCEL;
|
||||
}
|
||||
@ -159,25 +159,25 @@ long xmodem_receive( char **dest )
|
||||
packnum ++;
|
||||
|
||||
// Got a valid packet
|
||||
if( size + PACKET_SIZE > limit )
|
||||
if( size + PXM_ACKET_SIZE > limit )
|
||||
{
|
||||
limit += XMODEM_INCREMENT_AMMOUNT;
|
||||
if( ( p = realloc( *dest, limit ) ) == NULL )
|
||||
{
|
||||
// Not enough memory, force cancel and return
|
||||
xmodem_flush( XMODEM_FLUSH_AND_CAN );
|
||||
xmodem_flush( XMODEM_FLUSH_AND_XM_CAN );
|
||||
return XMODEM_ERROR_OUTOFMEM;
|
||||
}
|
||||
*dest = ( char* )p;
|
||||
}
|
||||
// Acknowledge and consume packet
|
||||
xmodem_out_func( ACK );
|
||||
memcpy( *dest + size, buf + 2, PACKET_SIZE );
|
||||
size += PACKET_SIZE;
|
||||
xmodem_out_func( XM_ACK );
|
||||
memcpy( *dest + size, buf + 2, PXM_ACKET_SIZE );
|
||||
size += PXM_ACKET_SIZE;
|
||||
}
|
||||
|
||||
// Exceeded retry count
|
||||
xmodem_flush( XMODEM_FLUSH_AND_CAN );
|
||||
xmodem_flush( XMODEM_FLUSH_AND_XM_CAN );
|
||||
return XMODEM_ERROR_RETRYEXCEED;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user