This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28075: The use of #include "device.h" directive in c2000ware peripheral examples.

Part Number: TMS320F28075
Other Parts Discussed in Thread: C2000WARE

Looking through the peripheral examples provided in c2000ware, they all use the #include "driverlib.h" and #include "device.h". I have read through the user guides and I do understand how to use the provided libraries. 

Through the reading I've done, I don't see any need for including the #include "device.h" header in these examples since the  #include "driverlib.h" header will include all what's needed to get the different peripherals working. 

Please explain to me why the #include "device.h" header is included and where it's root is located in the c2000ware library packages? Find code from an example below. 

#include "driverlib.h"
#include "device.h"

//
// Defines
//
#define RESULTS_BUFFER_SIZE 256
#define EX_ADC_RESOLUTION 12

//
// Globals
//
uint16_t adcAResult0;
uint16_t adcAResult1;
uint16_t adcBResult0;
uint16_t adcBResult1;

//
// Function Prototypes
//
void initADCs(void);
void initADCSOCs(void);

//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();

//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();

//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();

//
// Set up ADCs, initializing the SOCs to be triggered by software
//
initADCs();
initADCSOCs();

//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;

//
// Loop indefinitely
//
while(1)
{
//
// Convert, wait for completion, and store results
//
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0);
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER1);
ADC_forceSOC(ADCB_BASE, ADC_SOC_NUMBER0);
ADC_forceSOC(ADCB_BASE, ADC_SOC_NUMBER1);

//
// Wait for ADCA to complete, then acknowledge flag
//
while(ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1) == false)
{
}
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

//
// Wait for ADCB to complete, then acknowledge flag
//
while(ADC_getInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1) == false)
{
}
ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);

//
// Store results
//
adcAResult0 = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
adcAResult1 = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER1);
adcBResult0 = ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER0);
adcBResult1 = ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER1);

//
// Software breakpoint. At this point, conversion results are stored in
// adcAResult0, adcAResult1, adcBResult0, and adcBResult1.
//
// Hit run again to get updated conversions.
//
ESTOP0;
}
}

//
// Function to configure and power up ADCs A and B.
//
void initADCs(void)
{
//
// Set ADCCLK divider to /4
//
ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_4_0);
ADC_setPrescaler(ADCB_BASE, ADC_CLK_DIV_4_0);

//
// Set pulse positions to late
//
ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);
ADC_setInterruptPulseMode(ADCB_BASE, ADC_PULSE_END_OF_CONV);

//
// Power up the ADCs and then delay for 1 ms
//
ADC_enableConverter(ADCA_BASE);
ADC_enableConverter(ADCB_BASE);

DEVICE_DELAY_US(1000);
}

//
// Function to configure SOCs 0 and 1 of ADCs A and B.
//
void initADCSOCs(void)
{
//
// Configure SOCs of ADCA
// - SOC0 will convert pin A0.
// - SOC1 will convert pin A1.
// - Both will be triggered by software only.
// - For 12-bit resolution, a sampling window of 15 (75 ns at a 200MHz
// SYSCLK rate) will be used. For 16-bit resolution, a sampling window
// of 64 (320 ns at a 200MHz SYSCLK rate) will be used.
//
#if(EX_ADC_RESOLUTION == 12)
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN0, 15);
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN1, 15);
#elif(EX_ADC_RESOLUTION == 16)
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN0, 64);
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN1, 64);
#endif

//
// Set SOC1 to set the interrupt 1 flag. Enable the interrupt and make
// sure its flag is cleared.
//
ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER1);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

//
// Configure SOCs of ADCB
// - SOC0 will convert pin B0.
// - SOC1 will convert pin B1.
// - Both will be triggered by software only.
// - For 12-bit resolution, a sampling window of 15 (75 ns at a 200MHz
// SYSCLK rate) will be used. For 16-bit resolution, a sampling window
// of 64 (320 ns at a 200MHz SYSCLK rate) will be used.
//
#if(EX_ADC_RESOLUTION == 12)
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN0, 15);
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN1, 15);
#elif(EX_ADC_RESOLUTION == 16)
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN0, 64);
ADC_setupSOC(ADCB_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_SW_ONLY,
ADC_CH_ADCIN1, 64);
#endif

//
// Set SOC1 to set the interrupt 1 flag. Enable the interrupt and make
// sure its flag is cleared.
//
ADC_setInterruptSource(ADCB_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER1);
ADC_enableInterrupt(ADCB_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);
}

  • Hi,

    device.h and device.c files can be found under the <C2000ware>\device_support\<device name>\common\include and <C2000ware>\device_support\<device name>\common\source folders respectively.

    The device.c file consists of basic device init functions like enabling the clocks, peripherals, gpio configurations etc. device.h inldes the function prototypes for these functions. These functions are not included as part of driverlib.

    Regards,
    Veena
  • Thanks for the reply Veena.
    I have two more questions.
    1) In the example I presented i.e. adc_ex1_soc_software.c (ADC software Triggering), I see functions such as initADC() calling functions that are are declared as static in the adc.h file located in C:\TI\c2000\C2000Ware_1_00_06_00\driverlib\f2807x\driverlib and yet initADC() isn't declared in adc.h file. This seems to be going against the intended use of static functions since functions that are static can only be accessed by functions in the same file as it. This question applies for all functions declared as static in adc.h and yet they are being accessed by initADCSOCs(), initADC(). Please clarify on this.

    2) Secondly, there is a drivers library located in C:\TI\c2000\C2000Ware_1_00_06_00\driverlib\f2807x\driverlib, and this driver library is described in document titled "F2807x Peripheral Driver Library 1.04.00.00 User's guide", is it possible for me to use this library only in order to use the different peripherals on the TMS320F2807x microcontrollers.
    I ask this because the documentation clearly describes the use of these drivers hence making it simple to use.
    Incase I have no option but to use the device.h, and driverlib.h headers as in the example, please refer me to a document that explains their use or explain it over here.
  • Hi Mabonga Paul,

    1) initADC() is not a driverlib function. It is local function defined in the example. It uses the functions available in the ADC driver. The static functions declared in the adc.h file are all inline functions and hence can be used in any file that includes this header file.

    2) You can just use the drivelib as mentioned in the the user guide. The device.h and device.c files provides some sample init functions for the configuring the clocks, GPIOs, enabling peripherals etc. It internally uses driverlib functions. If you like to have your own init functions, you can totally skip that file and write your own init code. But I recommend the usage of device.c file. They are used in all the examples for system initialization.

    Regards,
    Veena
  • Thanks very much. I'll do as you've recommended.
  • Good day Veena.

    I've been studying the device.c and device.h files. In the device initialization function Device_int() found in the device.c file, am failing to fully understand line 74, i.e. 

       memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

    I do know it's meant to copy code from the flash memory to RAM during start up. I've read through document SPRA958L but i've still failed to get a good understanding. 

    Please explain to me how this function is being used or can be used? 

  • Hi Mabonga Paul,

    As you might be aware that the Flash memories and non volatile and RAM memories are volatile but faster than Flash memories.

    So, typically the application code that needs to be run on the microcontroller is loaded on Flash memories and a subset of functions(or all the functions) are then copied to RAM for faster execution.

    In the linker command file, you will find something line below:

      .TI.ramfunc      : LOAD = FLASH_BANK0_SEC1,
    
                         RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
    
                         LOAD_START(RamfuncsLoadStart),
    
                         LOAD_SIZE(RamfuncsLoadSize),
    
                         LOAD_END(RamfuncsLoadEnd),
    
                         RUN_START(RamfuncsRunStart),
    
                         RUN_SIZE(RamfuncsRunSize),
    
                         RUN_END(RamfuncsRunEnd),
    
                         PAGE = 0, ALIGN(4)

    This means the functions defined under the ramFuncs section is loaded in Flash but run from RAM. The memcpy is required to copy the contents of Flash memory to RAM memory.

    Regards,

    Veena