Archive for April, 2012

Programming and debugging Freescale TWR-K60N512 Tower Kit

Tower System from Freescale really get me excited (See http://www.freescale.com/files/32bit/doc/support_info/TWR_TRAINING.zip).

I bought a TWR-K60N512 from Freescale some time back:

http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=TWR-K60N512-IAR

Hacking starts here:

First, download from the web the latest edition of IAR Embedded Workbench:

IAR Embedded Workbench for ARM version 6.30.7

Next, install the drivers that communicate with the Open Source BDM (OSBDM) hardware:

“Freescale Kinetis OSJTAG Drivers V1.04”: http://www.keil.com/download/files/fslkinetisdriversv104.exe

Next, download some samples developed by Freescale:

http://styles.freescale.com/files/microcontrollers/software/app_software/code_examples/KINETIS512_SC.zip

And next I learned how to recompile and flash the program into the firmware.

(As noted by – TWRK60QSG: http://cache.freescale.com/files/32bit/doc/quick_ref_guide/TWRK60QSG.pdf

programming the K60N512 need to be in bootloader mode, versus the “debug” mode – which differed by shorting the J10 pin on the board)

Stepping through the code in IAR we can also learn some ARM assembly implementation in K60N512)

More information:

K60N512 Video

http://cache.freescale.com/files/32bit/doc/ref_manual/TWR-K60N512-UM.pdf

Snippets of assembly from the IAR implementation:

/*!
* brief Kinetis Start
* return None
*
* This function calls all of the needed starup routines and then
* branches to the main process.
*/
void start(void)
{
/* Disable the watchdog timer */
wdog_disable();

/* Copy any vector or data sections that need to be in RAM */
common_startup();

/* Perform processor initialization */
sysinit();

printf("nn");

/* Determine the last cause(s) of reset */
if (MC_SRSH & MC_SRSH_SW_MASK)
printf("Software Resetn");
if (MC_SRSH & MC_SRSH_LOCKUP_MASK)
printf("Core Lockup Event Resetn");
if (MC_SRSH & MC_SRSH_JTAG_MASK)
printf("JTAG Resetn");

if (MC_SRSL & MC_SRSL_POR_MASK)
printf("Power-on Resetn");
if (MC_SRSL & MC_SRSL_PIN_MASK)
printf("External Pin Resetn");
if (MC_SRSL & MC_SRSL_COP_MASK)
printf("Watchdog(COP) Resetn");
if (MC_SRSL & MC_SRSL_LOC_MASK)
printf("Loss of Clock Resetn");
if (MC_SRSL & MC_SRSL_LVD_MASK)
printf("Low-voltage Detect Resetn");
if (MC_SRSL & MC_SRSL_WAKEUP_MASK)
printf("LLWU Resetn");

/* Determine specific Kinetis device and revision */
cpu_identify();

/* Jump to main process */
main();

/* No actions to perform after this so wait forever */
while(1);
}

The sysinit() above will then call the following:

/* Actual system clock frequency */
int core_clk_khz;
int core_clk_mhz;
int periph_clk_khz;

void sysinit (void)
{
/*
* Enable all of the port clocks. These have to be enabled to configure
* pin muxing options, so most code will need all of these on anyway.
*/
SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
| SIM_SCGC5_PORTB_MASK
| SIM_SCGC5_PORTC_MASK
| SIM_SCGC5_PORTD_MASK
| SIM_SCGC5_PORTE_MASK );

#if defined(NO_PLL_INIT)
core_clk_mhz = 21; //FEI mode
#else
/* Ramp up the system clock */
core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);
#endif

/*
* Use the value obtained from the pll_init function to define variables
* for the core clock in kHz and also the peripheral clock. These
* variables can be used by other functions that need awareness of the
* system frequency.
*/
core_clk_khz = core_clk_mhz * 1000;
periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24)+ 1);

/* For debugging purposes, enable the trace clock and/or FB_CLK so that
* we'll be able to monitor clocks and know the PLL is at the frequency
* that we expect.
*/
trace_clk_init();
fb_clk_init();

/* Enable the pins for the selected UART */
if (TERM_PORT == UART0_BASE_PTR)
{
/* Enable the UART0_TXD function on PTD6 */
PORTD_PCR6 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

/* Enable the UART0_RXD function on PTD7 */
PORTD_PCR7 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
}

if (TERM_PORT == UART1_BASE_PTR)
{
/* Enable the UART1_TXD function on PTC4 */
PORTC_PCR4 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

/* Enable the UART1_RXD function on PTC3 */
PORTC_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
}

if (TERM_PORT == UART2_BASE_PTR)
{
/* Enable the UART2_TXD function on PTD3 */
PORTD_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

/* Enable the UART2_RXD function on PTD2 */
PORTD_PCR2 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
}

if (TERM_PORT == UART3_BASE_PTR)
{
/* Enable the UART3_TXD function on PTC17 */
PORTC_PCR17 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

/* Enable the UART3_RXD function on PTC16 */
PORTC_PCR16 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
}
if (TERM_PORT == UART4_BASE_PTR)
{
/* Enable the UART3_TXD function on PTC17 */
PORTE_PCR24 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

/* Enable the UART3_RXD function on PTC16 */
PORTE_PCR25 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
}
if (TERM_PORT == UART5_BASE_PTR)
{
/* Enable the UART3_TXD function on PTC17 */
PORTE_PCR8 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

/* Enable the UART3_RXD function on PTC16 */
PORTE_PCR9 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
}
/* UART0 and UART1 are clocked from the core clock, but all other UARTs are
* clocked from the peripheral clock. So we have to determine which clock
* to send to the uart_init function.
*/
if ((TERM_PORT == UART0_BASE_PTR) | (TERM_PORT == UART1_BASE_PTR))
uart_init (TERM_PORT, core_clk_khz, TERMINAL_BAUD);
else
uart_init (TERM_PORT, periph_clk_khz, TERMINAL_BAUD);
}
/********************************************************************/
void trace_clk_init(void)
{
/* Set the trace clock to the core clock frequency */
SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;

/* Enable the TRACE_CLKOUT pin function on PTA6 (alt7 function) */
PORTA_PCR6 = ( PORT_PCR_MUX(0x7));
}

What is the use of TRACE_CLKOUT?

Anyway, at the end of start() is the call to the application-specific main(). For example, for the “adc_demo” I am compiling:

void main (void)
{
Init_Gpio();
Hw_Trig_Test(); // demo the adc/pdb
}

%d bloggers like this: