1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00

added support for the I2C interface. UNTESTED, for now enabled only for the STR9 platform. Documentation will follow shortly

This commit is contained in:
Bogdan Marinescu 2010-07-21 20:21:55 +00:00
parent ebaf0c1160
commit 6b3f038db3
11 changed files with 1017 additions and 4 deletions

View File

@ -383,7 +383,7 @@ if not GetOption( 'help' ):
comp.Append(CPPPATH = ['src/fatfs']) comp.Append(CPPPATH = ['src/fatfs'])
# Lua module files # Lua module files
module_names = "pio.c spi.c tmr.c pd.c uart.c term.c pwm.c lpack.c bit.c net.c cpu.c adc.c can.c luarpc.c bitarray.c elua.c" module_names = "pio.c spi.c tmr.c pd.c uart.c term.c pwm.c lpack.c bit.c net.c cpu.c adc.c can.c luarpc.c bitarray.c elua.c i2c.c"
module_files = " " + " ".join( [ "src/modules/%s" % name for name in module_names.split() ] ) module_files = " " + " ".join( [ "src/modules/%s" % name for name in module_names.split() ] )
# Remote file system files # Remote file system files

View File

@ -211,8 +211,8 @@ enum
}; };
// Functions requiring platform-specific implementation // Functions requiring platform-specific implementation
int platform_adc_update_sequence( ); int platform_adc_update_sequence();
int platform_adc_start_sequence( ); int platform_adc_start_sequence();
void platform_adc_stop( unsigned id ); void platform_adc_stop( unsigned id );
u32 platform_adc_setclock( unsigned id, u32 frequency); u32 platform_adc_setclock( unsigned id, u32 frequency);
@ -221,6 +221,31 @@ int platform_adc_exists( unsigned id );
int platform_adc_check_timer_id( unsigned id, unsigned timer_id ); int platform_adc_check_timer_id( unsigned id, unsigned timer_id );
u32 platform_adc_op( unsigned id, int op, u32 data ); u32 platform_adc_op( unsigned id, int op, u32 data );
// *****************************************************************************
// I2C platform interface
// I2C speed
enum
{
PLATFORM_I2C_SPEED_SLOW = 100000,
PLATFORM_I2C_SPEED_FAST = 400000
};
// I2C direction
enum
{
PLATFORM_I2C_DIRECTION_TRANSMITTER,
PLATFORM_I2C_DIRECTION_RECEIVER
};
int platform_i2c_exists( unsigned id );
u32 platform_i2c_setup( unsigned id, u32 speed );
void platform_i2c_send_start( unsigned id );
void platform_i2c_send_stop( unsigned id );
int platform_i2c_send_address( unsigned id, u16 address, int direction );
int platform_i2c_send_byte( unsigned id, u8 data );
int platform_i2c_recv_byte( unsigned id, int ack );
// ***************************************************************************** // *****************************************************************************
// Ethernet specific functions // Ethernet specific functions

View File

@ -461,6 +461,16 @@ void* platform_get_last_free_ram( unsigned id )
return ( void* )p; return ( void* )p;
} }
// I2C support
int platform_i2c_exists( unsigned id )
{
#ifndef NUM_I2C
return 0;
#else
return id < NUM_I2C;
#endif
}
// **************************************************************************** // ****************************************************************************
// Misc support // Misc support
unsigned int intlog2( unsigned int v ) unsigned int intlog2( unsigned int v )

View File

@ -54,6 +54,9 @@ LUALIB_API int ( luaopen_bitarray )( lua_State *L );
#define AUXLIB_ELUA "elua" #define AUXLIB_ELUA "elua"
LUALIB_API int ( luaopen_elua )( lua_State *L ); LUALIB_API int ( luaopen_elua )( lua_State *L );
#define AUXLIB_I2C "i2c"
LUALIB_API int ( luaopen_i2c )( lua_State *L );
// Helper macros // Helper macros
#define MOD_CHECK_ID( mod, id )\ #define MOD_CHECK_ID( mod, id )\
if( !platform_ ## mod ## _exists( id ) )\ if( !platform_ ## mod ## _exists( id ) )\
@ -68,3 +71,4 @@ LUALIB_API int ( luaopen_elua )( lua_State *L );
lua_setfield( L, -2, name ) lua_setfield( L, -2, name )
#endif #endif

154
src/modules/i2c.c Normal file
View File

@ -0,0 +1,154 @@
// Module for interfacing with the I2C interface
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
#include <string.h>
#include <ctype.h>
// Lua: speed = i2c.setup( id, speed )
static int i2c_setup( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
u32 speed = ( u32 )luaL_checkinteger( L, 2 );
MOD_CHECK_ID( i2c, id );
lua_pushinteger( L, platform_i2c_setup( id, speed ) );
return 1;
}
// Lua: i2c.start( id )
static int i2c_start( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( i2c, id );
platform_i2c_send_start( id );
return 0;
}
// Lua: i2c.stop( id )
static int i2c_stop( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( i2c, id );
platform_i2c_send_stop( id );
return 0;
}
// Lua: i2c.address( id, address, direction )
static int i2c_address( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
u16 address = ( u16 )luaL_checkinteger( L, 2 );
int direction = luaL_checkinteger( L, 3 );
MOD_CHECK_ID( i2c, id );
lua_pushboolean( L, platform_i2c_send_address( id, address, direction ) );
return 1;
}
// Lua: wrote = i2c.write( id, string | table | 8-bit number )
static int i2c_write( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
const char *pdata;
size_t datalen, i;
int numdata;
u32 wrote;
MOD_CHECK_ID( i2c, id );
if( lua_isnumber( L, 2 ) )
{
numdata = ( int )luaL_checkinteger( L, 2 );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "numeric data can be between 0 and 255" );
wrote = platform_i2c_send_byte( id, numdata );
}
else if( lua_istable( L, 2 ) )
{
datalen = lua_objlen( L, 2 );
for( i = 0; i < datalen; i ++ )
{
lua_rawgeti( L, 2, i + 1 );
numdata = luaL_checkinteger( L, -1 );
lua_pop( L, 1 );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "numeric data can be between 0 and 255" );
if( platform_i2c_send_byte( id, numdata ) == 0 )
break;
}
wrote = i;
}
else
{
pdata = luaL_checklstring( L, 2, &datalen );
for( i = 0; i < datalen; i ++ )
if( platform_i2c_send_byte( id, pdata[ i ] ) == 0 )
break;
wrote = i;
}
lua_pushinteger( L, wrote );
return 1;
}
// Lua: read = i2c.read( id, size )
static int i2c_read( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
u32 size = ( u32 )luaL_checkinteger( L, 2 ), i;
luaL_Buffer b;
int data;
MOD_CHECK_ID( i2c, id );
luaL_buffinit( L, &b );
for( i = 0; i < size; i ++ )
if( ( data = platform_i2c_recv_byte( id, i < size - 1 ) ) == -1 )
break;
else
luaL_addchar( &b, ( char )data );
luaL_pushresult( &b );
return 1;
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE i2c_map[] =
{
{ LSTRKEY( "setup" ), LFUNCVAL( i2c_setup ) },
{ LSTRKEY( "start" ), LFUNCVAL( i2c_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( i2c_stop ) },
{ LSTRKEY( "address" ), LFUNCVAL( i2c_address ) },
{ LSTRKEY( "write" ), LFUNCVAL( i2c_write ) },
{ LSTRKEY( "read" ), LFUNCVAL( i2c_read ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "SPEED_FAST" ), LNUMVAL( PLATFORM_I2C_SPEED_FAST ) },
{ LSTRKEY( "SPEED_SLOW" ), LNUMVAL( PLATFORM_I2C_SPEED_SLOW ) },
{ LSTRKEY( "TRANSMITTER" ), LNUMVAL( PLATFORM_I2C_DIRECTION_TRANSMITTER ) },
{ LSTRKEY( "RECEIVER" ), LNUMVAL( PLATFORM_I2C_DIRECTION_RECEIVER ) },
#endif
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_i2c( lua_State *L )
{
#if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else // #if LUA_OPTIMIZE_MEMORY > 0
luaL_register( L, AUXLIB_I2C, i2c_map );
// Add the stop bits and parity constants (for uart.setup)
MOD_REG_NUMBER( L, "SPEED_FAST", PLATFORM_I2C_SPEED_FAST );
MOD_REG_NUMBER( L, "SPEED_SLOW", PLATFORM_I2C_SPEED_SLOW );
MOD_REG_NUMBER( L, "TRANSMITTER", PLATFORM_I2C_DIRECTION_TRANSMITTER );
MOD_REG_NUMBER( L, "RECEIVER", PLATFORM_I2C_DIRECTION_RECEIVER );
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
}

View File

@ -1221,3 +1221,5 @@ int platform_adc_start_sequence( )
} }
#endif // ifdef BUILD_ADC #endif // ifdef BUILD_ADC

615
src/platform/str9/91x_i2c.c Executable file
View File

@ -0,0 +1,615 @@
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : 91x_i2c.c
* Author : MCD Application Team
* Version : V2.1
* Date : 12/22/2008
* Description : This file provides all the I2C firmware functions.
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "91x_i2c.h"
#include "91x_scu.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* I2C IT enable */
#define I2C_IT_Enable 0x01
#define I2C_IT_Disable 0xFE
/* I2C Peripheral Enable/Disable */
#define I2C_PE_Set 0x20
#define I2C_PE_Reset 0xDF
/* Address direction bit */
#define I2C_ADD0_Set 0x01
#define I2C_ADD0_Reset 0xFE
/* I2C START Enable/Disable */
#define I2C_Start_Enable 0x08
#define I2C_Start_Disable 0xF7
/* I2C STOP Enable/Disable */
#define I2C_Stop_Enable 0x02
#define I2C_Stop_Disable 0xFD
/* I2C Masks */
#define I2C_Frequency_Mask 0x1F
#define I2C_AddressHigh_Mask 0xF9
#define I2C_OwnAddress_Mask 0x0300
#define I2C_StandardMode_Mask 0x7f
#define I2C_FastMode_Mask 0x80
#define I2C_Event_Mask 0x3FFF
#define I2C_HeaderSet_Mask 0xF1
#define I2C_HeaderReset_Mask 0xFE
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : I2C_DeInit
* Description : Deinitializes the I2C peripheral registers to their default
* reset values.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* Output : None
* Return : None
*******************************************************************************/
void I2C_DeInit(I2C_TypeDef* I2Cx)
{
if (I2Cx == I2C0)
{
/* Reset the I2C0 registers values */
SCU_APBPeriphReset(__I2C0, ENABLE);
SCU_APBPeriphReset(__I2C0, DISABLE);
}
if (I2Cx == I2C1)
{
/* Reset the I2C1 registers values */
SCU_APBPeriphReset(__I2C1, ENABLE);
SCU_APBPeriphReset(__I2C1, DISABLE);
}
}
/*******************************************************************************
* Function Name : I2C_Init
* Description : Initializes the I2C peripheral according to the specified
* parameters in the I2C_InitTypeDef structure.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
*
* - I2C_InitStruct: pointer to an I2C_InitTypeDef structure that
* contains the configuration information for the specified I2C
* peripheral.
* Output : None
* Return : None
*******************************************************************************/
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
{
u16 wResult = 0x0F;
u32 dPCLK = SCU_GetPCLKFreqValue() * 1000;
/* Get PCLK frequency value */
dPCLK = SCU_GetPCLKFreqValue()*1000;
/* Disable I2C peripheral to set FR[2:0] bits */
I2C_Cmd (I2Cx, DISABLE);
/* Clear frequency FR[2:0] bits */
I2Cx->OAR2 &= I2C_Frequency_Mask;
/* Set frequency bits depending on PCLK value */
if ((dPCLK <1667000) & (dPCLK > 10000000))
I2Cx->OAR2 |= 0x20;
else if (dPCLK < 26670000)
I2Cx->OAR2 |= 0x40;
else if (dPCLK < 40000000)
I2Cx->OAR2 |= 0x60;
else if (dPCLK < 53330000)
I2Cx->OAR2 |= 0x80;
else if (dPCLK < 66000000)
I2Cx->OAR2 |= 0xA0;
else if (dPCLK < 80000000)
I2Cx->OAR2 |= 0xC0;
else if (dPCLK < 100000000)
I2Cx->OAR2 |= 0xE0;
I2C_Cmd (I2Cx, ENABLE);
/* Configure general call */
if (I2C_InitStruct->I2C_GeneralCall == I2C_GeneralCall_Enable)
{
/* Enable general call */
I2Cx->CR |= I2C_GeneralCall_Enable;
}
else
{
/* Disable general call */
I2Cx->CR &= I2C_GeneralCall_Disable;
}
/* Configure acknowledgement */
if (I2C_InitStruct->I2C_Ack == I2C_Ack_Enable)
{
/* Enable acknowledgement */
I2Cx->CR |= I2C_Ack_Enable;
}
else
{
/* Disable acknowledgement */
I2Cx->CR &= I2C_Ack_Disable;
}
/* Configure LSB own address */
I2Cx->OAR1 = I2C_InitStruct->I2C_OwnAddress;
/* Clear MSB own address ADD[9:8] bits */
I2Cx->OAR2 &= I2C_AddressHigh_Mask;
/* Set MSB own address value */
I2Cx->OAR2 |= (I2C_InitStruct->I2C_OwnAddress & I2C_OwnAddress_Mask)>>7;
/* Configure speed in standard mode */
if (I2C_InitStruct->I2C_CLKSpeed <= 100000)
{
/* Standard mode speed calculate */
wResult = ((dPCLK/I2C_InitStruct->I2C_CLKSpeed)-7)/2;
/* Set speed value and clear FM/SM bit for standard mode in LSB clock divider */
I2Cx->CCR = wResult & I2C_StandardMode_Mask;
}
/* Configure speed in fast mode */
else if (I2C_InitStruct->I2C_CLKSpeed <= 400000)
{
/* Fast mode speed calculate */
wResult = ((dPCLK/I2C_InitStruct->I2C_CLKSpeed)-9)/3;
/* Set speed value and set FM/SM bit for fast mode in LSB clock divider */
I2Cx->CCR = wResult | I2C_FastMode_Mask;
}
/* Set speed in MSB clock divider */
I2Cx->ECCR = wResult >>7;
}
/*******************************************************************************
* Function Name : I2C_StructInit
* Description : Initialize the I2C Init Structure parameters
* Input : - I2C_InitStruct: pointer to an I2C_InitTypeDef structure
which will be initialized.
* Output : None
* Return : None.
*******************************************************************************/
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct)
{
/* Initialize the I2C_CLKSpeed member */
I2C_InitStruct->I2C_CLKSpeed = 5000;
/* Initialize the I2C_OwnAddress member */
I2C_InitStruct->I2C_OwnAddress = 0x0;
/* Initialize the I2C_GeneralCall member */
I2C_InitStruct->I2C_GeneralCall = I2C_GeneralCall_Disable;
/* Initialize the I2C_Ack member */
I2C_InitStruct->I2C_Ack = I2C_Ack_Disable;
}
/*******************************************************************************
* Function Name : I2C_Cmd
* Description : Enables or disables the specified I2C peripheral.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - NewState: new state of the I2C peripheral. This parameter
* can be: ENABLE or DISABLE.
* Output : None
* Return : None.
*******************************************************************************/
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState == ENABLE)
{
/* Enable the I2C peripheral by setting twice the PE bit on the CR register */
I2Cx->CR |= I2C_PE_Set;
I2Cx->CR |= I2C_PE_Set;
}
else
{
/* Disable the I2C peripheral */
I2Cx->CR &= I2C_PE_Reset;
}
}
/*******************************************************************************
* Function Name : I2C_GenerateSTART
* Description : Generates I2C communication START condition.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
*
* - NewState: new state of the Start condition. This parameter
* can be: ENABLE or DISABLE.
* Output : None
* Return : None.
*******************************************************************************/
void I2C_GenerateStart(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState == ENABLE)
{
/* Generate a START condition */
I2Cx->CR |= I2C_Start_Enable;
}
else
{
/* Disable the START condition generation */
I2Cx->CR &= I2C_Start_Disable;
}
}
/*******************************************************************************
* Function Name : I2C_GenerateSTOP
* Description : Generates I2C communication STOP condition.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
*
* - NewState: new state of the Stop condition. This parameter
* can be: ENABLE or DISABLE.
* Output : None
* Return : None.
*******************************************************************************/
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
if (NewState == ENABLE)
{
/* Generate a SIOP condition */
I2Cx->CR |= I2C_Stop_Enable;
}
else
{
/* Disable the STOP condition generation */
I2Cx->CR &= I2C_Stop_Disable;
}
}
/*******************************************************************************
* Function Name : I2C_AcknowledgeConfig
* Description : Enables or disables I2C acknowledge feature.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - NewState: new state of the Acknowledgement. This parameter
* can be: ENABLE or DISABLE.
* Output : None
* Return : None.
*******************************************************************************/
void I2C_AcknowledgeConfig(I2C_TypeDef *I2Cx, FunctionalState NewState)
{
if (NewState == ENABLE)
{
/* Enable the acknowledgement */
I2Cx->CR |= I2C_Ack_Enable;
}
else
{
/* Disable the acknowledgement */
I2Cx->CR &= I2C_Ack_Disable;
}
}
/*******************************************************************************
* Function Name : I2C_ITConfig
* Description : Enables or disables I2C interrupt feature.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - NewState: new state of the specified I2C interrupt.
* This parameter can be: ENABLE or DISABLE.
* Output : None
* Return : None.
*******************************************************************************/
void I2C_ITConfig(I2C_TypeDef *I2Cx, FunctionalState NewState)
{
if (NewState == ENABLE)
{
/* Enable the I2C interrupt */
I2Cx->CR |= I2C_IT_Enable;
}
else
{
/* Disable the I2C interrupt */
I2Cx->CR &= I2C_IT_Disable;
}
}
/*******************************************************************************
* Function Name : I2C_ReadRegister
* Description : Reads any I2C register and returns its value.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - I2C_Register: the I2C register to be read. This parameter
* can be one of the following values:
* - I2C_CR: CR register.
* - I2C_SR1: SR1 register.
* - I2C_SR2: SR2 register.
* - I2C_CCR: CCR register.
* - I2C_OAR1: OAR1 register.
* - I2C_OAR2: OAR2 register.
* - I2C_DR: DR register.
* - I2C_ECCR: ECCR register.
* Output : None
* Return : The value of the register passed as parameter
*******************************************************************************/
u8 I2C_ReadRegister(I2C_TypeDef* I2Cx, u8 I2C_Register)
{
/* Return the selected register value */
if (I2Cx == I2C0)
{
return (*(u8 *)(I2C0_BASE + I2C_Register));
}
if (I2Cx == I2C1)
{
return (*(u8 *)(I2C1_BASE + I2C_Register));
}
return 0;
}
/*******************************************************************************
* Function Name : I2C_GetFlagStatus
* Description : Checks whether the specified I2C flag is set or not.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - I2C_FLAG: flag to check. This parameter can be one of the
* following values:
* - I2C_FLAG_SB: Start bit flag
* - I2C_FLAG_M_SL: Master/Slave flag
* - I2C_FLAG_ADSL: Adress matched flag
* - I2C_FLAG_BTF: Byte transfer finished flag
* - I2C_FLAG_BUSY: Bus busy flag
* - I2C_FLAG_TRA: Transmitter/Receiver flag
* - I2C_FLAG_ADD10: 10-bit addressing in Master mode flag
* - I2C_FLAG_EVF: Event flag
* - I2C_FLAG_GCAL: General call flag
* - I2C_FLAG_BERR: Bus error flag
* - I2C_FLAG_ARLO: Arbitration lost flag
* - I2C_FLAG_STOPF: Stop detection flag
* - I2C_FLAG_AF: Acknowledge failure flag
* - I2C_FLAG_ENDAD: End of address transmission flag
* - I2C_FLAG_ACK: Acknowledge enable flag
* Output : None
* Return : The NewState of the I2C_Flag (SET or RESET).
*******************************************************************************/
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, u16 I2C_FLAG)
{
u16 wFlag1=0, wFlag2=0, wTmp=0;
wFlag1 = I2Cx->SR2;
wFlag1 = wFlag1<<8;
wFlag2 = I2Cx->CR & 0x04;
/* Get all the I2C flags in a unique register*/
wTmp = (((I2Cx->SR1 | (wFlag1)) & I2C_Event_Mask) | (wFlag2<<12));
/* Check the status of the specified I2C flag */
if((wTmp & I2C_FLAG) != RESET)
{
/* Return SET if I2C_FLAG is set */
return SET;
}
else
{
/* Return RESET if I2C_FLAG is reset */
return RESET;
}
}
/*******************************************************************************
* Function Name : I2C_ClearFlag
* Description : Clears the I2C Flag passed as a parameter
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - I2C_FLAG: flag to check. This parameter can be one of the
* following values:
* - I2C_FLAG_SB: Start bit flag
* - I2C_FLAG_M_SL: Master/Slave flag
* - I2C_FLAG_ADSL: Adress matched flag
* - I2C_FLAG_BTF: Byte transfer finished flag
* - I2C_FLAG_BUSY: Bus busy flag
* - I2C_FLAG_TRA: Transmitter/Receiver flag
* - I2C_FLAG_ADD10: 10-bit addressing in Master mode flag
* - I2C_FLAG_EVF: Event flag
* - I2C_FLAG_GCAL: General call flag
* - I2C_FLAG_BERR: Bus error flag
* - I2C_FLAG_ARLO: Arbitration lost flag
* - I2C_FLAG_STOPF: Stop detection flag
* - I2C_FLAG_AF: Acknowledge failure flag
* - I2C_FLAG_ENDAD: End of address transmission flag
* - I2C_FLAG_ACK: Acknowledge enable flag
* - parameter needed in the case that the flag to be cleared
* need a write in one register
* Output : None
* Return : None.
*******************************************************************************/
void I2C_ClearFlag(I2C_TypeDef* I2Cx, u16 I2C_FLAG, ...)
{
u8 bTmp = (u8)*((u32 *) & I2C_FLAG + sizeof(I2C_FLAG));
/* flags that need a read of the SR2 register to be cleared */
if ((I2C_FLAG==I2C_FLAG_ADD10) || (I2C_FLAG==I2C_FLAG_EVF) || (I2C_FLAG==I2C_FLAG_BERR) || (I2C_FLAG==I2C_FLAG_ARLO) |
(I2C_FLAG==I2C_FLAG_STOPF) ||(I2C_FLAG==I2C_FLAG_AF) || (I2C_FLAG==I2C_FLAG_ENDAD))
{
/* Read the SR2 register */
I2Cx->SR2;
/* Two flags need a second step to be cleared */
switch (I2C_FLAG)
{
case I2C_FLAG_ADD10:
/* Send the MSB 10bit address passed as second parameter */
I2Cx->DR = bTmp;
break;
case I2C_FLAG_ENDAD:
/* Write to the I2C_CR register by setting PE bit */
I2Cx->CR |= I2C_PE_Set;
break;
}
}
/* flags that need a read of the SR1 register to be cleared */
else if (I2C_FLAG==I2C_FLAG_SB || I2C_FLAG==I2C_FLAG_ADSL || I2C_FLAG==I2C_FLAG_BTF || I2C_FLAG==I2C_FLAG_TRA)
{
/* Read the SR1 register */
(void)I2Cx->SR1;
/* three flags need a second step to be cleared */
if (I2C_FLAG == I2C_FLAG_SB)
{
/* Send the address byte passed as second parameter */
I2Cx->DR = bTmp;
}
else if (I2C_FLAG==I2C_FLAG_BTF || I2C_FLAG==I2C_FLAG_TRA)
{
/* return the received byte in the variable passed as second parameter */
bTmp=I2Cx->DR;
}
}
/* flags that need to disable the I2C interface */
else if ( I2C_FLAG==I2C_FLAG_M_SL || I2C_FLAG==I2C_FLAG_GCAL)
{
I2C_Cmd(I2Cx, DISABLE);
I2C_Cmd(I2Cx, ENABLE);
}
}
/*******************************************************************************
* Function Name : I2C_Send7bitAddress
* Description : Transmits the address byte to select the slave device.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - Address: specifies the slave address which will be transmitted
* - Direction: specifies whether the I2C device will be a
* Transmitter or a Receiver. This parameter can be one of the
* following values
* - I2C_MODE_TRANSMITTER: Transmitter mode
* - I2C_MODE_RECEIVER: Receiver mode
* Output : None
* Return : None.
*******************************************************************************/
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, u8 Address, u8 Direction)
{
/* Test on the direction to define the read/write bit */
if (Direction == I2C_MODE_RECEIVER)
{
/* Set the address bit0 for read */
Address |= I2C_ADD0_Set;
}
else
{
/* Reset the address bit0 for write */
Address &= I2C_ADD0_Reset;
}
/* Send the address */
I2Cx->DR = Address;
}
/*******************************************************************************
* Function Name : I2C_SendData
* Description : Send a data byte.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - bData : the byte to be sent
* Output : None
* Return : None.
*******************************************************************************/
void I2C_SendData(I2C_TypeDef* I2Cx, u8 bData)
{
/* Write in the DR register the byte to be sent */
I2Cx->DR = bData;
}
/*******************************************************************************
* Function Name : I2C_ReceiveData
* Description : Read the received byte.
* Input : - I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* Output : None
* Return : The received byte
*******************************************************************************/
u8 I2C_ReceiveData(I2C_TypeDef* I2Cx)
{
/* Return from the DR register the received byte */
return I2Cx->DR;
}
/*******************************************************************************
* Function Name : I2C_GetLastEvent
* Description : Get the Last happened I2C Event.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* Output : None
* Return : The Last happened Event.
*******************************************************************************/
u16 I2C_GetLastEvent(I2C_TypeDef* I2Cx)
{
u16 wFlag1=0, wFlag2 =0, wLastEvent=0;
wFlag2 = I2Cx->SR1;
wFlag1 = I2Cx->SR2;
wFlag1 = wFlag1<<8;
/* Get the last event value from I2C status register */
wLastEvent = ((( wFlag2 | (wFlag1)) & I2C_Event_Mask));
/* Return the last event */
return wLastEvent;
}
/*******************************************************************************
* Function Name : I2C_CheckEvent
* Description : Checks whether the Last I2C Event is equal to the one passed
* as parameter.
* Input :- I2Cx: I2C peripheral can be:
* - I2C0
* - I2C1
* - I2C_EVENT: the event to check. This parameter can be one of
* the following values:
* - I2C_EVENT_SLAVE_ADDRESS_MATCHED
* - I2C_EVENT_SLAVE_BYTE_RECEIVED
* - I2C_EVENT_SLAVE_BYTE_TRANSMITTED
* - I2C_EVENT_MASTER_MODE_SELECT
* - I2C_EVENT_MASTER_MODE_SELECTED
* - I2C_EVENT_MASTER_BYTE_RECEIVED
* - I2C_EVENT_MASTER_BYTE_TRANSMITTED
* - I2C_EVENT_MASTER_MODE_ADDRESS10
* - I2C_EVENT_SLAVE_STOP_DETECTED
* - I2C_EVENT_SLAVE_ACK_FAILURE
- I2C_EV31
* Output : None
* Return : An ErrorStatus enumuration value:
* - SUCCESS: Last event is equal to the I2C_Event
* - ERROR: Last event is different from the I2C_Event
*******************************************************************************/
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx,u16 I2C_EVENT)
{
u16 wLastEvent = I2C_GetLastEvent(I2Cx);
/* Check whther the last event is equal to I2C_EVENT */
if (wLastEvent == I2C_EVENT)
{
/* Return SUCCESS when last event is equal to I2C_EVENT */
return SUCCESS;
}
else
{
/* Return ERROR when last event is different from I2C_EVENT */
return ERROR;
}
}
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

112
src/platform/str9/91x_i2c.h Normal file
View File

@ -0,0 +1,112 @@
/******************** (C) COPYRIGHT 2006 STMicroelectronics ********************
* File Name : 91x_i2c.h
* Author : MCD Application Team
* Date First Issued : 05/18/2006 : Version 1.0
* Description : This file contains all the functions prototypes for the
* I2C software library.
********************************************************************************
* History:
* 05/24/2006 : Version 1.1
* 05/18/2006 : Version 1.0
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Define to prevent recursive inclusion ------------------------------------ */
#ifndef __91x_I2C_H
#define __91x_I2C_H
/* Includes ----------------------------------------------------------------- */
#include "91x_map.h"
/* Exported types ----------------------------------------------------------- */
/* I2C Init structure definition */
typedef struct
{
u32 I2C_CLKSpeed;
u16 I2C_OwnAddress;
u8 I2C_GeneralCall;
u8 I2C_Ack;
}I2C_InitTypeDef;
/* Exported constants --------------------------------------------------------*/
#define I2C_GeneralCall_Enable 0x10
#define I2C_GeneralCall_Disable 0xEF
/* Acknowledgement */
#define I2C_Ack_Enable 0x04
#define I2C_Ack_Disable 0xFB
/* I2C Flags */
#define I2C_FLAG_SB 0x0001
#define I2C_FLAG_M_SL 0x0002
#define I2C_FLAG_ADSL 0x0004
#define I2C_FLAG_BTF 0x0008
#define I2C_FLAG_BUSY 0x0010
#define I2C_FLAG_TRA 0x0020
#define I2C_FLAG_ADD10 0x0040
#define I2C_FLAG_EVF 0x0080
#define I2C_FLAG_GCAL 0x0100
#define I2C_FLAG_BERR 0x0200
#define I2C_FLAG_ARLO 0x0400
#define I2C_FLAG_STOPF 0x0800
#define I2C_FLAG_AF 0x1000
#define I2C_FLAG_ENDAD 0x2000
#define I2C_FLAG_ACK 0x4000
/* I2C Events */
#define I2C_EVENT_SLAVE_ADDRESS_MATCHED ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_ADSL)
#define I2C_EVENT_SLAVE_BYTE_RECEIVED ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_BTF )
#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_BTF | I2C_FLAG_TRA )
#define I2C_EVENT_MASTER_MODE_SELECT ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL | I2C_FLAG_SB )
#define I2C_EVENT_MASTER_MODE_SELECTED ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL | I2C_FLAG_ENDAD )
#define I2C_EVENT_MASTER_BYTE_RECEIVED ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL | I2C_FLAG_BTF )
#define I2C_EVENT_MASTER_BYTE_TRANSMITTED ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL | I2C_FLAG_BTF | I2C_FLAG_TRA )
#define I2C_EVENT_MASTER_MODE_ADDRESS10 ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL |I2C_FLAG_ADD10 )
#define I2C_EVENT_SLAVE_STOP_DETECTED I2C_FLAG_STOPF
#define I2C_EVENT_SLAVE_ACK_FAILURE ( I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_BTF | I2C_FLAG_TRA | I2C_FLAG_AF)
#define I2C_BUS_ERROR_DETECTED I2C_FLAG_BERR
#define I2C_ARBITRATION_LOST I2C_FLAG_ARLO
#define I2C_SLAVE_GENERAL_CALL (I2C_FLAG_BUSY | I2C_FLAG_GCAL)
/* Master/Receiver Mode */
#define I2C_MODE_TRANSMITTER 0x00
#define I2C_MODE_RECEIVER 0x01
/* I2C Registers offset */
#define I2C_CR 0x00
#define I2C_SR1 0x04
#define I2C_SR2 0x08
#define I2C_CCR 0x0C
#define I2C_OAR1 0x10
#define I2C_OAR2 0x14
#define I2C_DR 0x18
#define I2C_ECCR 0x1C
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void I2C_DeInit(I2C_TypeDef* I2Cx);
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateStart(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_AcknowledgeConfig(I2C_TypeDef *I2Cx, FunctionalState NewState);
void I2C_ITConfig(I2C_TypeDef *I2Cx, FunctionalState NewState);
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, u8 Address, u8 Direction);
u8 I2C_ReadRegister(I2C_TypeDef* I2Cx, u8 I2C_Register);
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, u16 I2C_FLAG);
void I2C_ClearFlag(I2C_TypeDef* I2Cx, u16 I2C_FLAG, ...);
void I2C_SendData(I2C_TypeDef* I2Cx, u8 bData);
u8 I2C_ReceiveData(I2C_TypeDef* I2Cx);
u16 I2C_GetLastEvent(I2C_TypeDef* I2Cx);
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx,u16 I2C_Event);
#endif /* __91x_I2C_H */
/******************* (C) COPYRIGHT 2006 STMicroelectronics *****END OF FILE****/

View File

@ -2,7 +2,7 @@
cpumode = ARGUMENTS.get( 'cpumode', 'arm' ).lower() cpumode = ARGUMENTS.get( 'cpumode', 'arm' ).lower()
specific_files = "startup912.s startup_generic.s platform.c 91x_scu.c 91x_fmi.c 91x_gpio.c 91x_uart.c 91x_tim.c 91x_vic.c interrupt.c str9_pio.c" specific_files = "startup912.s startup_generic.s platform.c 91x_scu.c 91x_fmi.c 91x_gpio.c 91x_uart.c 91x_tim.c 91x_vic.c interrupt.c str9_pio.c 91x_i2c.c"
# Check CPU # Check CPU
if comp[ 'cpu' ] == 'STR912FAW44': if comp[ 'cpu' ] == 'STR912FAW44':

View File

@ -19,6 +19,7 @@
#include "platform_conf.h" #include "platform_conf.h"
#include "91x_vic.h" #include "91x_vic.h"
#include "lrotable.h" #include "lrotable.h"
#include "91x_i2c.h"
// **************************************************************************** // ****************************************************************************
// Platform initialization // Platform initialization
@ -60,6 +61,10 @@ static void platform_config_scu()
// Enable the GPIO clocks // Enable the GPIO clocks
SCU_APBPeriphClockConfig(__GPIO_ALL, ENABLE); SCU_APBPeriphClockConfig(__GPIO_ALL, ENABLE);
// Enable the I2C clocks
SCU_APBPeriphClockConfig(__I2C0, ENABLE);
SCU_APBPeriphClockConfig(__I2C1, ENABLE);
} }
// Port/pin definitions of the eLua UART connection for different boards // Port/pin definitions of the eLua UART connection for different boards
@ -421,6 +426,90 @@ void platform_cpu_disable_interrupts()
disable_ints(); disable_ints();
} }
// ****************************************************************************
// I2C support
static const GPIO_TypeDef* i2c_port_data[] = { GPIO1, GPIO2 };
static const I2C_TypeDef* i2cs[] = { I2C0, I2C1 };
static const u8 i2c_clock_pin[] = { GPIO_Pin_4, GPIO_Pin_2 };
static const u8 i2c_data_pin[] = { GPIO_Pin_6, GPIO_Pin_3 };
u32 platform_i2c_setup( unsigned id, u32 speed )
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// Setup PIO
GPIO_StructInit( &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Pin = i2c_clock_pin[ id ] | i2c_data_pin[ id ];
GPIO_InitStructure.GPIO_Type = GPIO_Type_OpenCollector;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = id == 0 ? GPIO_OutputAlt3 : GPIO_OutputAlt2;
GPIO_Init( ( GPIO_TypeDef* )i2c_port_data[ id ], &GPIO_InitStructure );
// Setup and interface
I2C_StructInit( &I2C_InitStructure );
I2C_InitStructure.I2C_GeneralCall = I2C_GeneralCall_Disable;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_CLKSpeed = speed;
I2C_InitStructure.I2C_OwnAddress = 0XA0 + id; // dummy, shouldn't matter
I2C_Init( ( I2C_TypeDef* )i2cs[ id ], &I2C_InitStructure );
// Return actual speed
return speed;
}
void platform_i2c_send_start( unsigned id )
{
I2C_TypeDef *pi2c = ( I2C_TypeDef* )i2cs[ id ];
while( I2C_GetFlagStatus( pi2c, I2C_FLAG_BUSY ) );
I2C_GenerateStart( pi2c, ENABLE );
while( !I2C_CheckEvent( pi2c, I2C_EVENT_MASTER_MODE_SELECT ) );
}
void platform_i2c_send_stop( unsigned id )
{
I2C_TypeDef *pi2c = ( I2C_TypeDef* )i2cs[ id ];
while( I2C_GetFlagStatus( pi2c, I2C_FLAG_BUSY ) );
I2C_GenerateSTOP( pi2c, ENABLE );
}
int platform_i2c_send_address( unsigned id, u16 address, int direction)
{
I2C_TypeDef *pi2c = ( I2C_TypeDef* )i2cs[ id ];
while( I2C_GetFlagStatus( pi2c, I2C_FLAG_BUSY ) );
I2C_Send7bitAddress( pi2c, address, direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ? I2C_MODE_TRANSMITTER : I2C_MODE_RECEIVER );
while( !I2C_CheckEvent( pi2c, I2C_EVENT_MASTER_MODE_SELECTED ) )
if( I2C_GetFlagStatus( pi2c, I2C_FLAG_AF ) == SET )
return 0;
return 1;
}
int platform_i2c_send_byte( unsigned id, u8 data )
{
I2C_TypeDef *pi2c = ( I2C_TypeDef* )i2cs[ id ];
while( I2C_GetFlagStatus( pi2c, I2C_FLAG_BUSY ) );
I2C_SendData( pi2c, data );
while( !I2C_CheckEvent( pi2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) )
if( I2C_GetFlagStatus( pi2c, I2C_FLAG_AF ) == SET )
return 0;
return 1;
}
int platform_i2c_recv_byte( unsigned id, int ack )
{
I2C_TypeDef *pi2c = ( I2C_TypeDef* )i2cs[ id ];
while( I2C_GetFlagStatus( pi2c, I2C_FLAG_BUSY ) );
I2C_AcknowledgeConfig( pi2c, ack ? ENABLE : DISABLE );
if( I2C_CheckEvent( pi2c, I2C_EVENT_MASTER_BYTE_RECEIVED ) )
return I2C_ReceiveData( pi2c );
return -1;
}
// **************************************************************************** // ****************************************************************************
// Platform specific modules go here // Platform specific modules go here

View File

@ -46,6 +46,7 @@
#define NUM_PWM 4 #define NUM_PWM 4
#define NUM_ADC 0 #define NUM_ADC 0
#define NUM_CAN 0 #define NUM_CAN 0
#define NUM_I2C 2
// RPC boot options // RPC boot options
#define RPC_UART_ID CON_UART_ID #define RPC_UART_ID CON_UART_ID
@ -96,6 +97,7 @@ u32 SCU_GetMCLKFreqValue();
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\ _ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map)\ _ROM( AUXLIB_CPU, luaopen_cpu, cpu_map)\
_ROM( AUXLIB_CPU, luaopen_elua, elua_map)\ _ROM( AUXLIB_CPU, luaopen_elua, elua_map)\
_ROM( AUXLIB_I2C, luaopen_i2c, i2c_map)\
RPCLINE\ RPCLINE\
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map)\ _ROM( AUXLIB_PWM, luaopen_pwm, pwm_map)\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\ _ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\