📄 bli2c.c
字号:
/**************************************************
*
* i2c.c
*
* CVS ID: $Id: bli2c.c,v 1.7 2007/10/25 10:11:40 marcucci Exp $
* Author: Maurizio Marcucci [MM] - STM
* Date: $Date: 2007/10/25 10:11:40 $
* Revision: $Revision: 1.7 $
*
* Description:
*
* Low level I2C driver
*
***************************************************
*
* COPYRIGHT (C) ST Microelectronics 2005
* All Rights Reserved
*
***************************************************
*
* STM CVS Log:
*
* $Log: bli2c.c,v $ * Revision 1.7 2007/10/25 10:11:40 marcucci * Enable SCL & SDA I2C lines only after complete I2C Hardware initilaization *
* Revision 1.6 2007/09/05 07:04:54 marcucci
* Debug Variable deleted
*
* Revision 1.5 2007/07/11 10:12:04 marcucci
* Set BUSY condition on I2C Start Detection and I2C emergency Init added
*
* Revision 1.4 2007/07/04 14:22:43 marcucci
* Continuous Data Transfer Added
*
* Revision 1.3 2007/07/03 06:45:36 marcucci
* Added Comments
*
* Revision 1.2 2007/07/02 14:56:43 marcucci
* Fixed Wrong Reference to bli2c.c file
*
* Revision 1.1 2007/07/02 08:42:59 marcucci
* I2C Bootloader
*
* Revision 1.8 2006/12/19 17:06:00 belardi
* Sends 0x00 if host requests more bytes than available in current packet
*
* Revision 1.7 2006/10/18 12:38:44 belardi
* Removed USE_STM_HOSTIF
*
* Revision 1.6 2006/09/18 09:55:23 belardi
* Corrected CVS keyword usage
*
* Revision 1.5 2006/09/18 09:24:13 belardi
* Added Log CVS keyword into file header
*
*
***************************************************/
#include "configuration.h"
#include "blgendef.h"
#include "hwreg.h"
extern BL_STRUCT * bl;
uint32 bl_i2cFillDram(void);
extern void bl_PrepareDram4Dwl(uint32 bl_start_addr, uint32 bl_end_addr);
#define RWBIT_MASK 0x01
uint8 bl_i2c_cksum_verify(uint8 * msg_ptr);
__irq void bl_i2c_event_isr(void);
__irq void bl_i2c_xfer_isr(void);
extern void sdram_init(uint32 PATCH_TABLE_ADDRESS);
extern void Reset_Handler(uint32 PATCH_TABLE_ADDRESS);
#define S_APB_CLK 67740000 //(67.74 MHZ)
/* Link layer message buffer for send and receive functions */
#define FM_I2C_CLK(clk) (((S_APB_CLK/(clk)) - 9 ) / 3)
#define I2C_100kHz 100000
#define I2C_400kHz 400000
uint8 bl_i2c_cksum(uint8 * msg_ptr);
void bl_i2c_ack(uint8 err);
void bl_i2c_tx_msg(void);
extern void configure_gpio(unsigned int port, unsigned int bit, unsigned int function);
extern void bl_copy_jt(void);
extern void emergency_i2c_init(void);
/******************************************************************************/
/* Function: i2c_soft_reset */
/* */
/*! \brief Initialize the I2C flags & Tx/Rx Buffers
* \param void
* \return void
* \remark
*/
/******************************************************************************/
void bl_i2c_soft_reset(void)
{
uint32 i;
bl->i2c_flags.msg_rcvd = 0;
bl->i2c_flags.i2c_rx_ready = 1;
bl->i2c_flags.i2c_tx_ready = 1;
bl->i2c_flags.tx_msg_done = 1;
bl->i2c_flags.i2c_new_cmd = 0;
bl->i2c_irq_tx_buffer_idx = 0;
bl->i2c_irq_rx_buffer_idx = 0;
/* Initialize the buffers, only for debug */
for(i = 0; i < BL_DEFAULT_MAX_I2C_TX_FRAME_SIZE; i++)
{
bl->i2c_irq_tx_buffer[i] = 0x00;
}
// Prepare Message MsgPowerMode: Patch Load Required
bl->i2c_irq_tx_buffer[0] = 4;// Length
bl->i2c_irq_tx_buffer[1] = 3;// GR
bl->i2c_irq_tx_buffer[2] = 1;// ID
bl->i2c_irq_tx_buffer[3] = 4;// PAR: Patch Code Downloading
bl->i2c_irq_tx_buffer[4] = bl_i2c_cksum(bl->i2c_irq_tx_buffer);
for(i = 0; i < BL_DEFAULT_MAX_I2C_RX_FRAME_SIZE; i++)
{
bl->i2c_irq_rx_buffer[i] = 0x00;
}
}
/******************************************************************************/
/* Function: i2c_init */
/* */
/*! \brief Initialize the I2C hardware
* \param void
* \return void
* \remark
*/
/******************************************************************************/
void bl_i2c_init(void)
{
uint32 isr_addr;
uint32 i;
bl_i2c_soft_reset();
bl->error.field.bad_starting_address = 0;
bl->error.field.ram_verify = 0;
bl->error.field.inv_op_code = 0;
bl->error.field.inv_checksum = 0;
bl->error.field.inv_param = 0;
bl->error.field.bad_len = 0;
bl->dwn_ctrl_flags.continous_xfer = 0;
bl->code_size = 0;
bl->code_checksum = 0;
bl->max_addr = 0;
bl->sdram_code_size = 0;
bl->sdram_code_checksum = 0;
bl->max_sdram_addr = 0;
bl->start_address = 0;
I2C0_CR.all = 0;
/* Configure Frequency Bits to match I2C setup/hold times */
I2C0_OAR2.field.fr = 6; // Input Frequency 66-80Mhz
// I2C0_CCR.field.fm_sm = 0; // Standard I2C
// I2C0_CCR.field.cc_0_6 = 0x32; // 10Khz I2C
// I2C0_ECCR = 0x1A;
/* Clock Control Register */
I2C0_CCR.field.fm_sm = 1; // Fast I2C
I2C0_CCR.field.cc_0_6 = 0x6E; // 100Khz I2C 0xde = 100Khz
// 200Khz I2C 0x6E = 200Khz
/* Extended Clock Control Register */
/* set the clock divider along with I2C_CCR register */
I2C0_ECCR = 0x00;
/* Peripheral Enable */
/* Repeated write to pe bit is required! */
I2C0_CR.field.pe = 1;
I2C0_CR.field.pe = 1;
/* Enable General Call (I2C address 0x00) */
/* This is not requires by CIS, should we delete it? */
//[MM]I2C0_CR.field.engc = 1;
I2C0_CR.field.engc = 0;
I2C0_CR.field.ack = 1;
/* Own Address Register*/
//I2C0_OAR1 = 0;
I2C0_OAR1 = BL_I2C_SLAVE_ADDRESS;
/* High bits of Own Address - used for 10 bit addressing */
I2C0_OAR2.field.add_8_9 = 0;
//OSAL_isr_install(OSAL_ISR_I2C0_EVENT, 0x0f, i2c_event_isr);
// [RB] use the same handler for both interupt sources
// [RB] This is not an error, see remarks in i2c_event_isr()
//OSAL_isr_install(OSAL_ISR_I2C0_DATA, 0x0f, i2c_event_isr);
/* wait for I2C bus to be idle (why?) */
//while(I2C0_SR1.field.busy); [Not More necessary]
isr_addr = (uint32) bl_i2c_event_isr;
EIC_SIR_9.all = (isr_addr << 16) | 0x0F;
EIC_IVR.all = isr_addr;
EIC_IER |= BL_EIC_I2C_EVENT_MASK; ;
isr_addr = (uint32) bl_i2c_xfer_isr;
EIC_SIR_10.all = (isr_addr << 16) | 0x0F;
EIC_IVR.all = isr_addr;
EIC_IER |= BL_EIC_I2C_XFER_MASK; ;
bl->dummy = I2C0_SR1.all;
bl->dummy = I2C0_SR2.all;
for(i = 0; i < 1000; i++)
{
if(I2C0_SR1.field.busy == 0)
{
break;
}
}
/* Interrupt Enable */
I2C0_CR.field.ite = 1;
BL_I2C_BUSY(); // Program CRQ Line before programming as an output port
configure_gpio(BL_PORT_B, BL_GPIO_1, BL_GPIO_OUT_OD); // use GPIO_AF_PP for I2C SCL
//configure_gpio(BL_PORT_B, BL_GPIO_2, BL_GPIO_AF_PP); // use GPIO_AF_PP for I2C SCL
//configure_gpio(BL_PORT_B, BL_GPIO_3, BL_GPIO_AF_PP); // use GPIO_AF_PP for I2C SDA
// Try to set SCL and SDA at the same time.
PC0B |= 0x000C;
PC1B |= 0x000C;
PC2B |= 0x000C;
/* Set I2C CRQ line to inactive */
BL_I2C_READY(); // CRQ ON
}
/******************************************************************************/
/* Function: bl_i2c_if */
/* */
/*! \brief I2C Boot Loader
* \param void
* \return void
* \remark
*/
/******************************************************************************/
void bl_i2cif(void)
{
volatile uint32 bl_addr;
volatile uint32 bl_data;
if(bl->i2c_flags.msg_rcvd)
{
bl->i2c_flags.msg_rcvd = 0;
bl->error.all = 0; // Clear all Error Condition Before
// Evaluating The received Message.
if(!bl_i2c_cksum_verify(bl->i2c_irq_rx_buffer))
{
// Checksum Error.
bl->error.field.inv_checksum = 1;
bl_i2c_ack(bl->error.all);
return;
}
switch (bl->i2c_irq_rx_buffer[BL_I2C_OP_CODE])
{
case BL_I2C_START_ADDRESS:
//MON1_ON(); //Debug
//bl->debug = 0x0001;
bl->start_address = ( ( ( (uint32) bl->i2c_irq_rx_buffer[BL_I2C_MSG_FIRST_BYTE+3]) << 24) +
( ((uint32) bl->i2c_irq_rx_buffer[BL_I2C_MSG_FIRST_BYTE + 2]) << 16) +
(((uint32)bl->i2c_irq_rx_buffer[BL_I2C_MSG_FIRST_BYTE + 1]) << 8) +
(uint32)bl->i2c_irq_rx_buffer[BL_I2C_MSG_FIRST_BYTE]);
//bl->error_code = BL_NO_ERROR;
if(bl->start_address == BL_RAM_A_BASE_ADDR)
{
// Clear RAM_A area devoted to patch code
bl->code_size = 0;
bl->code_checksum = 0;
bl->max_addr = 0;
bl->ram_ptr = (uint32 *)bl->start_address;
bl->code_checksum_ptr = &bl->code_checksum;
bl->code_size_ptr = &bl->code_size;
bl->max_addr_ptr = &bl->max_addr;
bl_PrepareDram4Dwl(BL_RAM_A_BASE_ADDR, BL_RAM_A_END_ADDR);
BL_I2C_READY();
}
else
{
if(bl->start_address >= BL_SDRAM_BASE_ADDR)
{
// Code must be downloaded in SDRAM
bl->sdram_code_size = 0;
bl->sdram_code_checksum = 0;
bl->max_sdram_addr = 0;
bl->ram_ptr = (uint32 *)bl->start_address;
bl->code_checksum_ptr = &bl->sdram_code_checksum;
bl->code_size_ptr = &bl->sdram_code_size;
bl->max_addr_ptr = &bl->max_sdram_addr;
if(!bl->dwn_ctrl_flags.patch_code_activated)
{
// Patch code (code for RAM_A) must be loaded first than SDRAM code then sdram_init()
// can be patched
bl->dwn_ctrl_flags.patch_code_activated = 1;
sdram_init(0x40000000);
// Clear all SDRAM that theoretically can be stored in Serial Flash
bl_PrepareDram4Dwl(BL_SDRAM_BASE_ADDR, (BL_SDRAM_BASE_ADDR + BL_I2C_SDRAM_SIZE));
}
BL_I2C_READY();
//else
//{
// Error: Patch Code Not Activated before Download something inside SDRAM
// Real Error : TBC
//}
}
else
{
// Error: Bad Starting Address
bl->error.field.bad_starting_address = 1;
}
}
bl->FlashDownLoadStatus = 1;
bl_i2c_ack(bl->error.all);
//MON1_OFF();
break;
case BL_I2C_DATA_MSG:
//bl->error_code = BL_NO_ERROR;
//bl->debug = 0x0002;
if(bl_i2cFillDram())
{
BL_I2C_READY();
}
bl->FlashDownLoadStatus = 2;
bl_i2c_ack(bl->error.all);
break;
case BL_I2C_RUN:
//bl->debug = 0x0004;
//bl_disable_interrupt();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -