1.概述
在东芝官网上下载的TMPM3Hy_v1.2.0软件包里包含了芯片的底层驱动程序和相关例程,例程的代码都是基于东芝TT_M3HQ开发板做了封装,软件结构做了优化设计,这对于我个人来说,还是需要花点时间去熟悉例程的编程设计思路;所以我干脆对照例程,我自己新建工程,一步一步操作,加深印象,最主要的是可以掌握这款芯片的使用及相关的注意事项。我所使用的软件开发环境是Keil MDK软件。
2.新建项目工程
2.1.打开Keil MDK软件,点击菜单栏Project->New uVision Project...,在弹出的Create New Project窗口中选择项目的存储路径及工程名,此项目工程名称命名为:TT_M3HQ,然后点击保存。
2.2.在弹出的Select Device for Target 'Target1'...窗口中选择我们东芝TT_M3HQ开发板的芯片型号:TMPM3HQFDFG,然后点击OK。
2.3.在弹出的Manage Run-Time Environment窗口中,选中CMSIS中的CORE勾选项,然后点击OK。至此工程就创建完成后,接下来我们来配置项目工程等操作。
2.4.点击File Extensions,Books and Environment...按键,弹出如下所示窗口,修改Progect Targets为TT_M3HQ;在Groups中添加3个组,分别为TMPM3Hy、Periph_driver、User;TMPM3Hy组中添加文件如下图所示:
2.5.Periph_driver组中添加文件如下图所示:
2.6.User组中添加文件如下图所示,然后点击OK,至此项目工程的所有文件就添加完成了,接下来是配置工程。
2.7.点击Options for Target...弹出如下所示窗口,Target选项卡设置如下所示:
2.8.在C/C++选项卡中,点击Include Path后面的...,对头文件的包含路径进行设置,如下图所示:
2.9.C/C++选项卡设置如下所示:
2.10.Debug选项卡设置如下所示:
2.11.Utilities选项卡设置如下所示:
2.12.点击Utilities选项卡中Settings按钮,弹出如下CMSIS-DAP Cortex-M Target Driver Setup窗口,设置如下图所示:
2.13.在CMSIS-DAP Cortex-M Target Driver Setup窗口的Debug选项卡中查看是否正常识别到板载芯片,如下图所示。至此整个项目工程就设置完成了,接下来可以编写应用程序了。
3.编写代码
作为新建的第一个项目工程,需要实现的功能相对简单,点亮LED灯进行闪烁,通过示波器实时监控MCU运行时的各个时钟频率输出。代码如下所示:
main.h
#ifndef __MAIN_H__#define __MAIN_H__ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include "txz_driver_def.h" #include "txz_hal.h" #include "txz_cg.h" #include "txz_gpio.h" #endif
复制代码main.c
#define __MAIN_C__#include "main.h" static void fsys_all_enable(void) { /*--- [CGFSYSENA] ---*/ TSB_CG_FSYSENA_IPENA00 = 1; /* Port A */ TSB_CG_FSYSENA_IPENA01 = 1; /* Port B */ TSB_CG_FSYSENA_IPENA02 = 1; /* Port C */ TSB_CG_FSYSENA_IPENA03 = 1; /* Port D */ TSB_CG_FSYSENA_IPENA04 = 1; /* Port E */ #if (defined(TMPM3HM) || defined(TMPM3HL)) /* Port F is not available. */ #else TSB_CG_FSYSENA_IPENA05 = 1; /* Port F */ #endif TSB_CG_FSYSENA_IPENA06 = 1; /* Port G */ TSB_CG_FSYSENA_IPENA07 = 1; /* Port H */ TSB_CG_FSYSENA_IPENA08 = 1; /* Port J */ TSB_CG_FSYSENA_IPENA09 = 1; /* Port K */ TSB_CG_FSYSENA_IPENA10 = 1; /* Port L */ TSB_CG_FSYSENA_IPENA11 = 1; /* Port M */ TSB_CG_FSYSENA_IPENA12 = 1; /* Port N */ TSB_CG_FSYSENA_IPENA13 = 1; /* Port P */ #if (defined(TMPM3HM) || defined(TMPM3HL)) /* Port R is not available. */ #else TSB_CG_FSYSENA_IPENA14 = 1; /* Port R */ #endif #if (defined(TMPM3HN) || defined(TMPM3HM) || defined(TMPM3HL) || defined(TMPM3HN_L)) /* Port T is not available. */ #else TSB_CG_FSYSENA_IPENA15 = 1; /* Port T */ #endif #if (defined(TMPM3HP) || defined(TMPM3HN) || defined(TMPM3HM) || defined(TMPM3HL) || defined(TMPM3HN_L)) /* Port U is not available. */ #else TSB_CG_FSYSENA_IPENA16 = 1; /* Port U */ #endif TSB_CG_FSYSENA_IPENA17 = 1; /* Port V */ TSB_CG_FSYSENA_IPENA18 = 1; /* DMAC 0 */ TSB_CG_FSYSENA_IPENA19 = 1; /* DMAC 1 */ TSB_CG_FSYSENA_IPENA20 = 1; /* A-PMD */ TSB_CG_FSYSENA_IPENA21 = 1; /* A-ENC */ TSB_CG_FSYSENA_IPENA22 = 1; /* RMC */ TSB_CG_FSYSENA_IPENA23 = 1; /* RTC */ TSB_CG_FSYSENA_IPENA24 = 1; /* T32A 0 */ TSB_CG_FSYSENA_IPENA25 = 1; /* T32A 1 */ TSB_CG_FSYSENA_IPENA26 = 1; /* T32A 2 */ TSB_CG_FSYSENA_IPENA27 = 1; /* T32A 3 */ TSB_CG_FSYSENA_IPENA28 = 1; /* T32A 4 */ TSB_CG_FSYSENA_IPENA29 = 1; /* T32A 5 */ TSB_CG_FSYSENA_IPENA30 = 1; /* T32A 6 */ TSB_CG_FSYSENA_IPENA31 = 1; /* T32A 7 */ /*--- [CGFSYSENB] ---*/ TSB_CG_FSYSENB_IPENB00 = 1; /* TSPI 0 */ #if defined(TMPM3HL) /* TSPI 1 is not available. */ #else TSB_CG_FSYSENB_IPENB01 = 1; /* TSPI 1 */ #endif #if defined(TMPM3HL) /* TSPI 2 is not available. */ #else TSB_CG_FSYSENB_IPENB02 = 1; /* TSPI 2 */ #endif #if defined(TMPM3HL) /* TSPI 3 is not available. */ #else TSB_CG_FSYSENB_IPENB03 = 1; /* TSPI 3 */ #endif #if (defined(TMPM3HN) || defined(TMPM3HM) || defined(TMPM3HL) || defined(TMPM3HN_L)) /* TSPI 4 is not available. */ #else TSB_CG_FSYSENB_IPENB04 = 1; /* TSPI 4 */ #endif TSB_CG_FSYSENB_IPENB05 = 1; /* UART 0 */ TSB_CG_FSYSENB_IPENB06 = 1; /* UART 1 */ TSB_CG_FSYSENB_IPENB07 = 1; /* UART 2 */ TSB_CG_FSYSENB_IPENB08 = 1; /* UART 3 */ TSB_CG_FSYSENB_IPENB09 = 1; /* UART 4 */ TSB_CG_FSYSENB_IPENB10 = 1; /* UART 5 */ TSB_CG_FSYSENB_IPENB11 = 1; /* I2C 0 */ #if defined(TMPM3HL) /* I2C 1 is not available. */ #else TSB_CG_FSYSENB_IPENB12 = 1; /* I2C 1 */ #endif TSB_CG_FSYSENB_IPENB13 = 1; /* I2C 2 */ #if (defined(TMPM3HN) || defined(TMPM3HM) || defined(TMPM3HL) || defined(TMPM3HN_L)) /* I2C 3 is not available. */ #else TSB_CG_FSYSENB_IPENB14 = 1; /* I2C 3 */ #endif TSB_CG_FSYSENB_IPENB15 = 1; /* ADC */ TSB_CG_FSYSENB_IPENB16 = 0; /* Reserved */ TSB_CG_FSYSENB_IPENB17 = 1; /* DAC 0 */ TSB_CG_FSYSENB_IPENB18 = 1; /* DAC 1 */ TSB_CG_FSYSENB_IPENB19 = 1; /* RAMPARITY */ TSB_CG_FSYSENB_IPENB20 = 1; /* CRC */ TSB_CG_FSYSENB_IPENB21 = 1; /* OFD */ TSB_CG_FSYSENB_IPENB22 = 1; /* TRM */ TSB_CG_FSYSENB_IPENB23 = 1; /* TRGSEL */ TSB_CG_FSYSENB_IPENB31 = 1; /* SIWDT */ } static void dnf_clock_enable(void) { /*--- [CGFCEN:FCIPEN07] ---*/ TSB_CG_FCEN_FCIPEN07 = 1; } static void adc_clock_enable(void) { /*--- [CGSPCLKEN:ADCKEN] ---*/ TSB_CG_SPCLKEN_ADCKEN = 1; } static void trace_clock_enable(void) { #if defined(TMPM3HL) /* ETM Trace is not available. */ #else /*--- [CGSPCLKEN:ADCKEN] ---*/ TSB_CG_SPCLKEN_TRCKEN = 1; #endif } static gpio_t port; /*!< Port driver instance. */ static void bsp_error(void) { #ifdef BSP_DEBUG while(1) { __nop(); } #endif } static void port_initialize(void) { /*--- Construct ---*/ /* Register Allocation */ port.p_pb_instance = TSB_PB; /*--- Initialize ---*/ if (gpio_init(&port, GPIO_PORT_B) != TXZ_SUCCESS) { bsp_error(); } /*--- Setting ---*/ /*- PB0 -*/ if (gpio_func(&port, GPIO_PORT_B, GPIO_PORT_0, (uint32_t)GPIO_PB0_SCOUT, GPIO_PIN_OUTPUT) != TXZ_SUCCESS) { bsp_error(); } /*===============================================================================*/ /* [Port K] */ /*-------------------------------------------------------------------------------*/ /* Port | Function | I/O | PKDATA | PKCR | PKFRn | PKOD | PKPUP | PKDN | PKIE */ /*-------------------------------------------------------------------------------*/ /* PK0 | - | - | 0 | 0 | 0 | 0 | 0 | 0 | 0 */ /* PK1 | - | - | 0 | 0 | 0 | 0 | 0 | 0 | 0 */ /* PK2 | - | - | 0 | 0 | 0 | 0 | 0 | 0 | 0 */ /* PK3 | - | - | 0 | 0 | 0 | 0 | 0 | 0 | 0 */ /* PK4 |PORT_LED[0]| O | 0 | 1 | 0 | 0 | 0 | 0 | 0 */ /* PK5 |PORT_LED[1]| O | 0 | 1 | 0 | 0 | 0 | 0 | 0 */ /* PK6 |PORT_LED[2]| O | 0 | 1 | 0 | 0 | 0 | 0 | 0 */ /* PK7 |PORT_LED[3]| O | 0 | 1 | 0 | 0 | 0 | 0 | 0 */ /*===============================================================================*/ /*--- Construct ---*/ /* Register Allocation */ port.p_pk_instance = TSB_PK; /*--- Initialize ---*/ if (gpio_init(&port, GPIO_PORT_K) != TXZ_SUCCESS) { bsp_error(); } /*--- Setting ---*/ /*- PK0 -*/ /* Use reset value. */ /*- PK1 -*/ /* Use reset value. */ /*- PK2 -*/ /* Use reset value. */ /*- PK3 -*/ /* Use reset value. */ /*- PK4 -*/ if (gpio_func(&port, GPIO_PORT_K, GPIO_PORT_4, (uint32_t)GPIO_PK4_OUTPUT, GPIO_PIN_OUTPUT) != TXZ_SUCCESS) { bsp_error(); } /*- PK5 -*/ if (gpio_func(&port, GPIO_PORT_K, GPIO_PORT_5, (uint32_t)GPIO_PK5_OUTPUT, GPIO_PIN_OUTPUT) != TXZ_SUCCESS) { bsp_error(); } /*- PK6 -*/ if (gpio_func(&port, GPIO_PORT_K, GPIO_PORT_6, (uint32_t)GPIO_PK6_OUTPUT, GPIO_PIN_OUTPUT) != TXZ_SUCCESS) { bsp_error(); } /*- PK7 -*/ if (gpio_func(&port, GPIO_PORT_K, GPIO_PORT_7, (uint32_t)GPIO_PK7_OUTPUT, GPIO_PIN_OUTPUT) != TXZ_SUCCESS) { bsp_error(); } } #define ELOSC_CFG_WARM_UP_TIME ((uint32_t)(5000)) /*!< Warm up time(us). */ #define ELOSC_CFG_CLOCK ((uint32_t)(32768)) /*!< Clock(hz). */ /* WUPTL */ #define CGWUPLCR_WUPTL_HIGH_MASK ((uint32_t)0x07FFF000) /*!< WUPTL :High Bit Mask. */ /* WULEF */ #define CGWUPLCR_WULEF_MASK ((uint32_t)0x00000002) /*!< WULEF :Mask. */ #define CGWUPLCR_WULEF_R_DONE ((uint32_t)0x00000000) /*!< WULEF :[R] :Done */ #define CGWUPLCR_WULEF_R_RUNNING ((uint32_t)0x00000002) /*!< WULEF :[R] :Running */ /* WULON */ #define CGWUPLCR_WULON_MASK ((uint32_t)0x00000001) /*!< WULON :Mask. */ #define CGWUPLCR_WULON_W_ENABLE ((uint32_t)0x00000001) /*!< WULON :[W] :Enable */ /* XTEN */ #define RLMLOSCCR_XTEN_RW_DISABLE ((uint8_t)0x00) /*!< XTEN :[R/W] :Disable */ #define RLMLOSCCR_XTEN_RW_ENABLE ((uint8_t)0x01) /*!< XTEN :[R/W] :Enable */ static void external_losc_enable(void) { uint32_t work; /* [CGWUPLCR]<WUPTL> :Warm up time */ /*-----------------------------------------------*/ /* "1"counter (s) = 1 / ELOSC */ /* "1"counter (us) = (10^6) / ELOSC */ /* "x"counter (us) = time */ /*-----------------------------------------------*/ /* x : time = 1 : (10^6) / ELOSC */ /*-----------------------------------------------*/ { uint64_t x = (uint64_t)((uint64_t)(ELOSC_CFG_WARM_UP_TIME) * (uint64_t)(ELOSC_CFG_CLOCK)); x = (uint64_t)(x / (uint64_t)(1000000)); if (x > (uint64_t)(0x7FFFF)) { /* invalid value */ } work = (uint32_t)x; } work &= (uint32_t)(0xFFFFFFF0); work <<= 8; TSB_CG->WUPLCR = work; /* [RLMLOSCCR]<XTEN> :LOSC Enable */ TSB_RLM->LOSCCR = RLMLOSCCR_XTEN_RW_ENABLE; /* [CGWUPLCR]<WULON> :Enable */ work = (uint32_t)(TSB_CG->WUPLCR & CGWUPLCR_WUPTL_HIGH_MASK); TSB_CG->WUPLCR = (uint32_t)(work | CGWUPLCR_WULON_W_ENABLE); /* [CGWUPLCR]<WULEF> :Read(wait for warm-up) */ while ((TSB_CG->WUPLCR & CGWUPLCR_WULEF_MASK) != CGWUPLCR_WULEF_R_DONE) { /* no processing */ } TSB_CG->SCOCR &= 0xFFFFFF80; TSB_CG->SCOCR |= (0x2 << 1); // fs TSB_CG->SCOCR |= (0x1 << 4); // Devide-by-2, if select fs ignore TSB_CG->SCOCR |= 0x1; // Enable SCOUT output } static void bsp_initialize(void) { /*--- Fsys Enable ---*/ fsys_all_enable(); /*--- DNF Clock Enable ---*/ dnf_clock_enable(); /*--- ADC Clock Enable ---*/ adc_clock_enable(); /*--- EMT Trace Clock Enable ---*/ trace_clock_enable(); /*--- Port ---*/ port_initialize(); /*--- ELOSC Enable ---*/ external_losc_enable(); } void software_delay(void) { uint32_t i = 0, j = 0; for(i = 0; i < 80; i++) { for(j = 0; j < 100000; j++); } } int main(void) { bsp_initialize(); while(1) { gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_4, GPIO_Mode_DATA, GPIO_PIN_SET); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_5, GPIO_Mode_DATA, GPIO_PIN_SET); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_6, GPIO_Mode_DATA, GPIO_PIN_SET); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_7, GPIO_Mode_DATA, GPIO_PIN_SET); software_delay(); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_4, GPIO_Mode_DATA, GPIO_PIN_RESET); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_5, GPIO_Mode_DATA, GPIO_PIN_RESET); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_6, GPIO_Mode_DATA, GPIO_PIN_RESET); gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_7, GPIO_Mode_DATA, GPIO_PIN_RESET); software_delay(); } }
复制代码4.总结体会
一个晚上的时间自己新建了一个工程,然后通过软件延时的方式让LED灯闪烁,设置PB0为SCOUT功能,通过示波器监控系统运行时的时钟频率。东芝给出的Reference Manual都是按照功能模块来划分的单独的文档,要实现一个SCOUT功能需要看两个文档,相互切换着看,感觉不太方便,希望后面可以整合成一个文档;第二个感觉就是官方提供的库函数功能覆盖范围还不是太全,或者说我自己还没找到应用的配置函数,还是实现SCOUT的功能,都是通过直接操作寄存器的方式实现的,后面也希望官方的库函数越来越便于使用吧,直接操作寄存器的方式还是需要花时间去对照手册去编程的,效率比较低。
5.工程代码及手册
5.1.工程代码: