Part Number: TMS320F28020
Other Parts Discussed in Thread: C2000WARE
Hi All,
Using CCS 10.4, I'm adding I2C functionality to a project that started as the TIREX example, "Example_2802xScia_FFDLB.c", shown here:
//#############################################################################
//
// File: Example_F2802xSci_FFDLB.c
//
// Title: F2802x Device SCI FIFO Digital Loop Back Test.
//
//! \addtogroup example_list
//! <h1>SCI FIFO Digital Loop Back</h1>
//!
//! This test uses the loopback test mode of the SCI module to send
//! characters starting with 0x00 through 0xFF. The test will send
//! a character and then check the receive buffer for a correct match.
//!
//! Watch Variables:
//! - LoopCount - Number of characters sent
//! - ErrorCount - Number of errors detected
//! - SendChar - Character sent
//! - ReceivedChar - Character received
//
//#############################################################################
// $TI Release: $
// $Release Date: $
// $Copyright:
// Copyright (C) 2009-2022 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//
// Included Files
//
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <stdio.h>
#include <file.h>
#include "common/include/adc.h"
#include "common/include/clk.h"
#include "common/include/flash.h"
#include "common/include/gpio.h"
#include "common/include/pie.h"
#include "common/include/pll.h"
#include "common/include/sci.h"
#include "common/include/wdog.h"
//
// Function Prototypes
//
void scia_init(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void error(void);
//
// Globals
//
uint16_t LoopCount;
uint16_t ErrorCount;
ADC_Handle myAdc;
CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
SCI_Handle mySci;
//
// Main
//
void main(void)
{
uint16_t SendChar;
uint16_t ReceivedChar;
CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;
//
// Initialize all the handles needed for this application
//
myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
//
// Perform basic system initialization
//
WDOG_disable(myWDog);
CLK_enableAdcClock(myClk);
(*Device_cal)();
//
// Select the internal oscillator 1 as the clock source
//
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);
//
// Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
//
PLL_setup(myPll, PLL_Multiplier_10, PLL_DivideSelect_ClkIn_by_2);
//
// Disable the PIE and all interrupts
//
PIE_disable(myPie);
PIE_disableAllInts(myPie);
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);
//
// If running from flash copy RAM only functions to RAM
//
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif
//
// Setup GPIO
//
GPIO_setPullUp(myGpio, GPIO_Number_28, GPIO_PullUp_Enable);
GPIO_setPullUp(myGpio, GPIO_Number_29, GPIO_PullUp_Disable);
GPIO_setQualification(myGpio, GPIO_Number_28, GPIO_Qual_ASync);
GPIO_setMode(myGpio, GPIO_Number_28, GPIO_28_Mode_SCIRXDA);
GPIO_setMode(myGpio, GPIO_Number_29, GPIO_29_Mode_SCITXDA);
//
// Setup a debug vector table and enable the PIE
//
PIE_setDebugIntVectorTable(myPie);
PIE_enable(myPie);
LoopCount = 0;
ErrorCount = 0;
scia_init(); // Initialize SCI for digital loop back
scia_fifo_init(); // Initialize the SCI FIFO
//
// Send a character starting with 0
//
SendChar = 0;
//
// Send Characters forever starting with 0x00 and going through 0xFF.
// After sending each, check the receive buffer for the correct value
//
for(;;)
{
SCI_putDataBlocking(mySci, SendChar);
while(SCI_getRxFifoStatus(mySci) == SCI_FifoStatus_Empty)
{
}
//
// Check received character
//
ReceivedChar = SCI_getData(mySci);
if(ReceivedChar != SendChar)
{
error();
}
//
// Move to the next character and repeat the test
//
SendChar++;
//
// Limit the character to 8-bits
//
SendChar &= 0x00FF;
LoopCount++;
}
}
//
// Step 7. Insert all local Interrupt Service Routines (ISRs) and
// functions here:
//
//
// error -
//
void
error(void)
{
ErrorCount++;
__asm(" ESTOP0"); // Uncomment to stop the test here
for (;;)
{
}
}
//
// scia_init -
//
void
scia_init()
{
CLK_enableSciaClock(myClk);
//
// 1 stop bit, No loopback, No parity,8 char bits, async mode,
// idle-line protocol
//
SCI_disableParity(mySci);
SCI_setNumStopBits(mySci, SCI_NumStopBits_One);
SCI_setCharLength(mySci, SCI_CharLength_8_Bits);
//
// enable TX, RX, internal SCICLK, Disable RX ERR, SLEEP, TXWAKE
//
SCI_enableTx(mySci);
SCI_enableRx(mySci);
SCI_enableTxInt(mySci);
SCI_enableRxInt(mySci);
SCI_enableLoopBack(mySci);
//SCI BRR = LSPCLK/(SCI BAUDx8) - 1
#if (CPU_FRQ_50MHZ)
SCI_setBaudRate(mySci, SCI_BaudRate_9_6_kBaud);
#elif (CPU_FRQ_40MHZ)
SCI_setBaudRate(mySci, (SCI_BaudRate_e)129);
#endif
SCI_enable(mySci);
return;
}
//
// scia_fifo_init - Initialize the SCI FIFO
//
void
scia_fifo_init()
{
SCI_enableFifoEnh(mySci);
SCI_resetTxFifo(mySci);
SCI_clearTxFifoInt(mySci);
SCI_resetChannels(mySci);
SCI_setTxFifoIntLevel(mySci, SCI_FifoLevel_Empty);
SCI_resetRxFifo(mySci);
SCI_clearRxFifoInt(mySci);
SCI_setRxFifoIntLevel(mySci, SCI_FifoLevel_4_Words);
return;
}
//
// End of File
//
This code and its containing project were imported from the Resource Explorer in this path:
/Software/C2000Ware (4.01.00.00)/English/Devices/F2802X/F28020/Examples/DriverLib/scia_loopback/Example_2802xScia_FFDLB.c
SCIA communications are working well, and now I'm trying to add simple I2C write functionality.
Separately, I've modified the Bitfiled Example_2802xI2C_eeprom.c from C2000Ware to enable the I2C needs, and that was working fine, too. Now I'm moving the functionality from that I2C Bitfield example into the SCIA Driverlib example code.
When complete, RS232 commands will be received over the SCIA module, parsed, and commands sent out to peripherals over I2C.
The first step was to insert the I2C initialization function into the SCIA Driverlib example code. Here is the function I created and inserted:
//
// Start I2C_init() Initialization Routine
//
void
I2C_init()
{
EALLOW;
// Initialize I2C
I2caRegs.I2CMDR.bit.IRS = 0; // SEE BELOW - Put I2C module in reset while making changes
//
// Own Address Register
// // Bit 15: READ ONLY - Reserved
I2caRegs.I2COAR = 0x40; // Own address = 0x40
I2caRegs.I2CSAR = 0x44; // Bits 0-9: Address to which data will be transmitted (Master only)
/* // Bits 7-15: Reserved
//
// I2C Interrupt Enable Register
//
#ifdef BIT_SET_REGISTERS
// Bits 7-15: READ ONLY - Reserved
I2caRegs.I2CIER.bit.AAS = 0; // Bit 6: 1 = Addressed as slave interrupt request enabled
I2caRegs.I2CIER.bit.SCD = 0; // Bit 5: 1 = Stop condition detected interrupt request enabled
I2caRegs.I2CIER.bit.XRDY = 0; // Bit 4: 1 = Transmit data ready interrupt request disabled
I2caRegs.I2CIER.bit.RRDY = 0; // Bit 3: 1 = W1C - Receive data ready interrupt request enabled
I2caRegs.I2CIER.bit.ARDY = 0; // Bit 2: 1 = Master Only - Register access ready interrupt request enabled
I2caRegs.I2CIER.bit.NACK = 0; // Bit 1: 0 = W1C - No-ack interrupt request disabled
I2caRegs.I2CIER.bit.ARBL = 0; // Bit 0: 0 = W1C - Arbitration lost interrupt request disabled
#else
I2caRegs.I2CIER.all = 0x0000; // Per above bit settings
#endif
//
// I2C Status Register
//
#ifdef BIT_SET_REGISTERS
// Bit 15: READ ONLY - Reserved
I2caRegs.I2CSTR.bit.SDIR = 0; // Bit 14: W1C - Slave direction bit 0 = not addressed as slave transmitter
I2caRegs.I2CSTR.bit.NACKSNT = 0; // Bit 13: W1C - NACK sent bit 0 = NACK not sent
I2caRegs.I2CSTR.bit.BB = 0; // Bit 12: Bus Busy bit 0 = bus free
I2caRegs.I2CSTR.bit.RSFULL = 0; // Bit 11: 1 = receive shift register overrun condition detected
I2caRegs.I2CSTR.bit.XSMT = 0; // Bit 10: 0 = transmit shift register underflow detected (empty)
I2caRegs.I2CSTR.bit.AAS = 0; // Bit 9: 1 = I2C module recognized its own slave address
I2caRegs.I2CSTR.bit.AD0 = 0; // Bit 8: 1 = address of all zeros (general call) was detected
// Bits 6-7: READ ONLY - Reserved
I2caRegs.I2CSTR.bit.SCD = 0; // Bit 5: W1C - 1 = stop condition was detected
I2caRegs.I2CSTR.bit.XRDY = 0; // Bit 4: 1 = Ready for more transmit data to go in I2CDXR
I2caRegs.I2CSTR.bit.RRDY = 0; // Bit 3: W1C - Receive data ready int flag 1 = data is in I2CDRR
I2caRegs.I2CSTR.bit.ARDY = 0; // Bit 2: Master Only - Register access ready int flag
I2caRegs.I2CSTR.bit.NACK = 0; // Bit 1: W1C - 1 = NACK received
I2caRegs.I2CSTR.bit.ARBL = 0; // Bit 0: W1C - 1 = arbitration lost
#else
I2caRegs.I2CSTR.all = 0x0000; // Per above bit settings
#endif
//
// I2C Clock Prescale Register
//
// Setup I2C data rate
I2caRegs.I2CPSC.bit.IPSC = 5; // Prescaler value 60mHz SYSCLK / 6 = 10mHz (5+1=6)
//
// I2C Clock high-time and low-time Registers
//
// 10mHz / 200 = 50kHz for comm's with 2x16 debugging display
I2caRegs.I2CCLKL = 129; // 129 + 5 = 136
I2caRegs.I2CCLKH = 61; // 61 + 5 = 66
//
// Data Count Register
//
I2caRegs.I2CCNT = 0; // Bits 0-15: Set data count (ignored in RM mode)
// Is changed to actual number of bytes to transfer when in
// transmit mode.
//
// Slave Address Register
// // Bits 10-15: READ ONLY - Reserved
I2caRegs.I2CSAR = 0x44; // Bits 0-9: Address to which data will be transmitted (Master only)
//
// Data transmit register
//
I2caRegs.I2CDXR = 0x00;
//
// I2C Mode Register
//
#ifdef BIT_SET_REGISTERS
// Bits 14-15: READ ONLY - Reserved
I2caRegs.I2CMDR.bit.NACKMOD = 0; // Bit 15: NACK mode
I2caRegs.I2CMDR.bit.FREE = 0; // Bit 14: For debugging: 0 = I2C halts during interrupts
// I2caRegs.I2CMDR.bit.STT = 0; // Bit 13: Master only - Start bit Can't be written when IRS=0
// Bit 12: Reserved
// I2caRegs.I2CMDR.bit.STP = 0; // Bit 11: Master only - Stop bit Can't be written when IRS=0
I2caRegs.I2CMDR.bit.MST = 1; // Bit 10: Remains 0 for slave mode. 1 = Master mode
I2caRegs.I2CMDR.bit.TRX = 1; // Bit 9: 0 = Receive mode, 1 = Transmit mode
I2caRegs.I2CMDR.bit.XA = 0; // Bit 8: 0 = 7 bit address mode
I2caRegs.I2CMDR.bit.RM = 1; // Bit 7: 1 = repeat mode
I2caRegs.I2CMDR.bit.DLB = 0; // Bit 6: 0 = Digital loopback mode disabled
// I2caRegs.I2CMDR.bit.IRS = 1; // Bit 5: I2C module is re-enabled after making changes
I2caRegs.I2CMDR.bit.STB = 0; // Bit 4: Master only - Start Byte mode
I2caRegs.I2CMDR.bit.FDF = 0; // Bit 3: Keep at 0. Free data format mode
I2caRegs.I2CMDR.bit.BC = 0; // Bits 0-2: Set bit count to 8 bits (0 = 8)
#else
I2caRegs.I2CMDR.all = 0x06a0; // Per above bit settings
#endif
//
// I2C Extended Mode Register
// // Bits 1-15: READ ONLY - Reserved
I2caRegs.I2CEMDR.bit.BCM = 0; // Bit 0: Backwards compatibility mode
//
// Transmit FIFO Register
//
#ifdef BIT_SET_REGISTERS
// Bits 14-15: READ ONLY - Reserved
// Bit 15: Reserved
I2caRegs.I2CFFTX.bit.I2CFFEN = 0; // Bit 14: 1 = Enable transmit & receive FIFOs
I2caRegs.I2CFFTX.bit.TXFFRST = 0; // Bit 13: 1 = Take transmit FIFO out of reset
// I2caRegs.I2CFFTX.bit.TXFFST = 0; // Bits 8-12: READ ONLY - How many bytes are in the transmit FIFO
// I2caRegs.I2CFFTX.bit.TXFFINT = 0; // Bit 7: READ ONLY - 1 = interrupt occurred
I2caRegs.I2CFFTX.bit.TXFFINTCLR = 0; // Bit 6: W1C - Clears transmit interrupt flag (do again after irs = 1)
I2caRegs.I2CFFTX.bit.TXFFIENA = 0; // Bit 5: 0 = Disable transmit FIFO interrupt
I2caRegs.I2CFFTX.bit.TXFFIL = 0; // Bits 0-4: Set the transmit FIFO interrupt Threshold
#else
I2caRegs.I2CFFTX.all = 0x0000; // Per above bit settings
#endif
//
// Receive FIFO Register
//
#ifdef BIT_SET_REGISTERS
// Bits 14-15: READ ONLY - Reserved
I2caRegs.I2CFFRX.bit.RXFFRST = 0; // Bit 13: 1 = enable receive FIFO operation
// I2caRegs.I2CFFRX.bit.RXFFST = 0; // BitS 8-12: READ ONLY - Bytes in receive FIFO
// I2caRegs.I2CFFRX.bit.RXFFINT = 0; // Bit 7: READ ONLY - Receive interrupt flag 1 = int
I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0; // Bit 6: Write 1 to clear receive int flag
I2caRegs.I2CFFRX.bit.RXFFIENA = 0; // Bit 5: 1 = receive interrupt is enabled
I2caRegs.I2CFFRX.bit.RXFFIL = 0; // Bits 0-4: Set the receive FIFO interrupt level
#else
I2caRegs.I2CFFRX.all = 0x0000; // Per above bit settings
#endif
*/
// Clean up and exit
I2caRegs.I2CMDR.bit.IRS = 1; // SEE ABOVE - I2C module is re-enabled after making changes
EDIS;
return;
}
/*
* End I2C_init()
*/
As can be seen in the above code, I tried setting each register one bit-at-a-time as well as tried setting each register word-at-a-time.
The code compiles without problem, uploads to target and runs normally, except none of the I2C registers change.
The code runs, so I set a breakpoint at a register change, and then stepped through several lines that should change register values. Watching the Registers View as well as the Memory Browser view, no changes are occurring.
When I enter code to write to a register, CCS identifies the various elements of that register that I may choose from a list to autofill:
Questions:
1. Is this issue due to combining Bitfiled example code with Driverlib code?
2. Am I missing some includes?
3. What is the proper way to write to the registers to set their values?
Thanks,
robin