石玉

  • 2019-09-21
  • 回复了主题帖: KEIL每次打开工程工程文件都会丢失?

    终于找到原因了,要点一次全部保存才行

  • 2019-09-10
  • 回复了主题帖: 回忆当年教我的那些老师们

    老前辈

  • 2019-09-04
  • 回复了主题帖: 出售讯为4412开发板

    500块买了一块,9寸屏,也在吃灰中

  • 2019-08-30
  • 回复了主题帖: 蓝牙模块的问题

    模块里面的CC2541也是可以编程的,看下TI的蓝牙SDK

  • 2019-08-17
  • 发表了主题帖: android驱动学习1-驱动开发流程(Android.mk)

    本帖最后由 石玉 于 2019-8-19 00:10 编辑 QQ:971586331 软件环境: 操作系统:windows 10 IDE版本:Android Studio 3.4.2 JAVA版本:jdk-8u221-windows-x64 NDK版本:android-ndk-r20-windows-x86_64 Kernel版本:linux 3.0 开发板android版本:android 4.0.3 硬件环境: 开发板:itop-4412 精英版 本文内容:本文描述了如何使用android应用程序调用linux驱动控制LED灯的亮灭。要实现android应用程序控制LED,需要三个程序,LED的linux驱动,JNI库和android应用程序。android应用程序通过JNI库调用LED驱动程序,从而实现android应用程序控制LED。 1.开发板环境搭建 开发环境搭建请参考《iTOP-4412开发板之精英版使用手册_V3.1.pdf》,本文使用的配置是 uboot:iTop4412_uboot_20180320.tar kernel:iTop4412_Kernel_3.0_20180604.tar android:iTop4412_ICS_git_20151120.tar 编译完成后将ramdisk-uboot.img,system.img,zImage,u-boot-iTOP-4412.bin文件通过OTG或SD烧写到开发板的EMMC中,如果在uboot下使用OTG,发现windows 10装不上光盘中的android_drv_90000_64.exe驱动,可以谷歌搜索安装android_11000010001_x64_718.exe。 2.LED的驱动程序 LED驱动在kernel的drivers/char/itop4412-leds.c中,从itop4412-leds.c中我们可以得知LED驱动的设备文件名叫“leds”。驱动程序实现了ioctl函数。 long leds_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) { printk("debug: leds_ioctl cmd is %d\n" , cmd); switch(cmd) { case 0: case 1: if (arg > LED_NUM) { return -EINVAL; } gpio_set_value(led_gpios[arg], cmd); break; default: return -EINVAL; } return 0; } leds_ioctl的cmd参数表示灯的亮灯,arg参数表示灯的编号,根据文件中的定义可以知,0表示GPL2_0,也就是LED2,1表示GPK1_1,也就是LED3。 static int led_gpios[] = { EXYNOS4_GPL2(0), EXYNOS4_GPK1(1), }; 接下来我们查看drivers/char/Makefile文件,宏CONFIG_LEDS_CTL控制LED驱动是否编译 obj-$(CONFIG_LEDS_CTL) += itop4412_leds.o 再查看drivers/char/Kconfig文件,默认就是y config LEDS_CTL bool "Enable LEDS config" default y help Enable LEDS config 再查看.config,已经将LED驱动编入了内核 CONFIG_LEDS_CTL=y 看来板子的驱动已经做好了,完全不用我们动手,接下我们看怎么编写JNI接口调用linux驱动 3.JNI和NDK 因为android是使用java语言进行开发的,但linux驱动是用C语言进行开发的,所以面临java如果调用C语言接口的问题,JNI提供的API就是解决java和其他语言通信的问题。NDK 是一套工具集合,允许你使用C语言来实现应用程序的部分功能。我们写好JNI接口后使用NDK打包成库文件,就可以提供给android应用程序调用了。接下来我们新建工程编写JNI。 新建一个空activity 填写工程名,选择工程路径,开发语言选择java,API选择15 创建工程后得待编译完成,然后在包名下创建一个名叫jni_led的类 文件内容如下: package com.example.led_test; public class jni_led { public native static String Leds_Operation(int ledNum, boolean status); //操作接口 } 打开 Android Studio 的 Terminal,使用javac命令将java文件编译成.class文件 F:\OneDrive\Linux\android_project\led_test>javac .\app\src\main\java\com\example\led_test\jni_led.java 使用javah命令创建头文件。-encoding UTF-8表示指定编码格式,防止出现“错误: 编码GBK的不可映射字符”,-d jni表示在当前目录下创建jni目录,将生成的文件放在jni目录中,-classpath表示指定类文件的路径。这里有一个地方要注意,类文件在写的时候是包名+类名,所有路径只用写到java目录,后面的com,example和led_test虽然都是文件夹,但这里表示包名(第一次写在这里纠结了好久,我想我路径明明写对了啊,为什么找不到\app\src\main\java\com\example\led_test文件夹下的类) F:\OneDrive\Linux\android_project\led_test>javah -encoding UTF-8 -d jni -classpath ./app/src/main/java com.example.led_test.jni_led 指令执行完成后可以发现在jni目录下生成了包名加类名的头文件 /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_led_test_jni_led */ #ifndef _Included_com_example_led_test_jni_led #define _Included_com_example_led_test_jni_led #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_led_test_jni_led * Method: Leds_Operation * Signature: (IZ)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_led_1test_jni_1led_Leds_1Operation (JNIEnv *, jclass, jint, jboolean); #ifdef __cplusplus } #endif #endif 可以发现,头文件中根据jni_led.java中定义的java类接口生成了JNI接口函数,我们要实现这个接口函数。 然后在JNI下创建com_example_led_test_jni_led.c文件 在com_example_led_test_jni_led.c中,我们将头文件中的接口函数据复制过来,然后使用linux API操作linux设备文件 // // Created by shiyu on 2019/8/17. // #include<jni.h> #include<stdio.h> #include <fcntl.h> #include <linux/ioctl.h> //导入我们创建的头文件 #include "com_example_led_test_jni_led.h" #define DEVICE_NAME "/dev/leds" JNIEXPORT jstring JNICALL Java_com_example_led_JNITest_Leds_1Operation (JNIEnv *env, jclass obj, jint ledsNum, jboolean status){ int leds_fd = 0; leds_fd = open(DEVICE_NAME, O_RDWR); //打开设备节点 if (leds_fd == -1) { return 1; } switch (ledsNum) { case 0: if (status) ioctl(leds_fd, 0, 0); else ioctl(leds_fd, 1, 0); break; case 1: if (status) ioctl(leds_fd, 0, 1); else ioctl(leds_fd, 1, 1); break; defautl : break; } close(leds_fd); return 0; //操作成功返回0 } 在jni下创建一个Android.mk文件 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jni_led LOCAL_SRC_FILES := com_example_led_test_jni_led.c include $(BUILD_SHARED_LIBRARY) 这时指定了生成库的名字和源文件,再新建一个Application.mk文件 APP_ABI := all 安装NDK工具集后,进入jni目录使用ndk-build命令将JNI接口程序编译成库文件 在libs目录下生成了各种平台的库文件 为了让项目能够找到我们的生成的库,在 build.gradle 文件夹的 android 下添加: sourceSets { main() { jniLibs.srcDirs = ['../libs'] jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程 } } 然后在jni_led.java中加载生成的库文件 package com.example.led_test; public class jni_led { static { System.loadLibrary("jni_led"); //加载生成的.so文件 } public native static String Leds_Operation(int ledNum, boolean status); //操作接口 } 接下来我们编写android应用程序利用Leds_Operation接口控制LED灯 4.编写android应用程序 打开工程目录下的activity_main.xml文件,添加4个button,并指写button的onClick回调函数 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TableLayout android:id="@+id/TableLayout2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:collapseColumns="4" > <TableRow> <Button android:id="@+id/button_led3off" android:layout_width="200dp" android:layout_height="200dp" android:onClick="led3_off_click" android:text="led3_off" tools:layout_editor_absoluteX="228dp" tools:layout_editor_absoluteY="186dp" /> <Button android:id="@+id/button_led3on" android:layout_width="200dp" android:layout_height="200dp" android:onClick="led3_on_click" android:text="led3_on" tools:layout_editor_absoluteX="98dp" tools:layout_editor_absoluteY="186dp" /> <Button android:id="@+id/button_led2off" android:layout_width="200dp" android:layout_height="200dp" android:onClick="led2_on_click" android:text="led2_off" tools:layout_editor_absoluteX="228dp" tools:layout_editor_absoluteY="100dp" /> <Button android:id="@+id/button_led2on" android:layout_width="200dp" android:layout_height="200dp" android:onClick="led2_off_click" android:text="led2_on" tools:layout_editor_absoluteX="98dp" tools:layout_editor_absoluteY="100dp" /> </TableRow> </TableLayout> </androidx.constraintlayout.widget.ConstraintLayout> 我们为4个按键指定了4个回调函数据,接下来我们在MainActivity.java中实现这4个回调函数 package com.example.led_test; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void led2_on_click( View view ) { jni_led.Leds_Operation(0, false); } public void led2_off_click( View view ) { jni_led.Leds_Operation(0, true); } public void led3_on_click( View view ) { jni_led.Leds_Operation(1, false); } public void led3_off_click( View view ) { jni_led.Leds_Operation(1, true); } } 如上,我们实现了这4个回调函数,调用jni_led库中的Leds_Operation函数,Leds_Operation会调用Java_com_example_led_JNITest_Leds_1Operation函数,这样就实现了android应用程序调用linux驱动接口。 连接开发板,编译运行。  

  • 2019-08-16
  • 发表了主题帖: TMS570学习3-内部Flash编程

    QQ:971586331 软件环境: 操作系统:windows 10 IDE:CCS7.4 代码生成工具:HALCoGen 04.07.01 Flash操作库:F021FlashApi-02.01.01 硬件环境: 目标板:TMDS570LS31HDK 本文内容:描述了TMS570系统芯片内部flash编程方法 1.新建CCS工程 按TMS570学习1中的流程新建工程boot_test。 2.安装F021库 在TI官网下载F021库,HERCULES F021FLASHAPI,下载后是一个exe,安装完后是下面这样 include:API接口的头文件 source:用户自定义的回调,只有一个Fapi_UserDefinedFunctions.c文件,文件中只有一个函数Fapi_serviceWatchdogTimer,根据描述,这个函数会在擦除,写和读时被调用,可以在函数中喂狗,防止flash操作时间太长导致复位。 lib文件:lib文件分三类,M3_BE,R4_BE和R4_LE,BE是大端模式,LE是小端模式,我们用的TMS570是大端模式(可以通过读ENDIAN_REG寄存器得知),所以我们使用R4_BE。 SPNA148.pdf:这个文档是操作flash的例子,里面有操作代码和流程图 SPNU501G.pdf:这个文档是API说明 3.移植F021库 将include目录,source目录,R4_BE后缀的lib文件拷贝到工程中,在工程中添加头文件路径 参考SPNA148.pdf中第三章的程序模板和SPNU501G.pdf中第5章的流程图编写flash操作函数,如下是flash操作的程序模板: 扇区擦除流程: 块擦流程: 编程流程: 4.编写flash操作函数 根据上一节的操作流程,编写flash操作接口,主要实现下列4个接口: Flash_EraseSector:擦除扇区 Flash_EraseBanks:擦除块 Flash_WriteData:写数据 Flash_ReadData:读数据 /* * flash_handle.h * * Created on: 2019年8月15日 * Author: shiyu */ #ifndef USER_FLASH_HANDLE_H_ #define USER_FLASH_HANDLE_H_ #include "F021.h" enum e_flash_status { flash_succeed, flash_failure, }; struct Sector_List { Fapi_FlashBankType banks_num; uint32_t sector_num; uint32_t low_addr; uint32_t size; }; #define SECTOR_NUM (15+12+4) enum e_flash_status Flash_EraseSector(Fapi_FlashBankType oNewFlashBank, uint32_t sector); enum e_flash_status Flash_EraseBanks(Fapi_FlashBankType oNewFlashBank); enum e_flash_status Flash_WriteData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len); void Flash_ReadData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len); #endif /* USER_FLASH_HANDLE_H_ */ /* * flash_handle.c * * Created on: 2019年8月15日 * Author: shiyu */ #include "F021.h" #include "flash_handle.h" //TMS570LS3137的flash分区表 struct Sector_List gSector_List[SECTOR_NUM] = { // 块编号 扇区编号 扇区起始地址 扇区大小 {Fapi_FlashBank0, 0, 0x00000000, 32*1024}, {Fapi_FlashBank0, 1, 0x00008000, 32*1024}, {Fapi_FlashBank0, 2, 0x00010000, 32*1024}, {Fapi_FlashBank0, 3, 0x00018000, 32*1024}, {Fapi_FlashBank0, 4, 0x00020000, 128*1024}, {Fapi_FlashBank0, 5, 0x00040000, 128*1024}, {Fapi_FlashBank0, 6, 0x00060000, 128*1024}, {Fapi_FlashBank0, 7, 0x00080000, 128*1024}, {Fapi_FlashBank0, 8, 0x000A0000, 128*1024}, {Fapi_FlashBank0, 9, 0x000C0000, 128*1024}, {Fapi_FlashBank0, 10, 0x000E0000, 128*1024}, {Fapi_FlashBank0, 11, 0x00100000, 128*1024}, {Fapi_FlashBank0, 12, 0x00012000, 128*1024}, {Fapi_FlashBank0, 13, 0x00014000, 128*1024}, {Fapi_FlashBank0, 14, 0x00016000, 128*1024}, {Fapi_FlashBank1, 0, 0x00018000, 128*1024}, {Fapi_FlashBank1, 1, 0x0001A000, 128*1024}, {Fapi_FlashBank1, 2, 0x0001C000, 128*1024}, {Fapi_FlashBank1, 3, 0x0001E000, 128*1024}, {Fapi_FlashBank1, 4, 0x00020000, 128*1024}, {Fapi_FlashBank1, 5, 0x00022000, 128*1024}, {Fapi_FlashBank1, 6, 0x00024000, 128*1024}, {Fapi_FlashBank1, 7, 0x00026000, 128*1024}, {Fapi_FlashBank1, 8, 0x00028000, 128*1024}, {Fapi_FlashBank1, 9, 0x0002A000, 128*1024}, {Fapi_FlashBank1, 10, 0x0002C000, 128*1024}, {Fapi_FlashBank1, 11, 0x0002E000, 128*1024}, {Fapi_FlashBank7, 0, 0xF0200000, 16*1024}, {Fapi_FlashBank7, 1, 0xF0204000, 16*1024}, {Fapi_FlashBank7, 2, 0xF0208000, 16*1024}, {Fapi_FlashBank7, 3, 0xF020C000, 16*1024}, }; /* @brief 查找扇区信息 * @param[in] oNewFlashBank:块编号 * @param[in] sector:扇区编号 * * return:扇区在数据结构中的位置 */ uint32_t find_sector(Fapi_FlashBankType oNewFlashBank, uint32_t sector) { int i=0; for(i=0; i<SECTOR_NUM; i++) { if( (gSector_List.banks_num == oNewFlashBank) && (gSector_List.sector_num == sector) ) { return i; } } } /* @brief 擦除扇区 * @param[in] oNewFlashBank:块编号 * @param[in] sector:扇区编号 * * return: */ enum e_flash_status Flash_EraseSector(Fapi_FlashBankType oNewFlashBank, uint32_t sector) { int num = 0; Fapi_StatusType oReturnCheck = Fapi_Status_Success; num = find_sector(oNewFlashBank, sector); //根据块ID和扇区ID查找扇区信息 printf("addr = %x\n", gSector_List[num].low_addr); oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作 if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy)) { oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank); //设置活动的Flash Bank if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) ) oReturnCheck = Fapi_enableMainBankSectors( 1<<(sector+1) ); //设置EEPROM存储区中可用的扇区以进行擦除和编程 else if( oNewFlashBank == Fapi_FlashBank7 ) oReturnCheck = Fapi_enableEepromBankSectors(1<<(sector+1) ,1<<((sector+1)%32)); //设置EEPROM存储区中可用的扇区以进行擦除和编程 while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy); Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, gSector_List[num].low_addr); //向Flash状态机发出命令 /* Place specific example code here */ /* Wait for FSM to finish */ while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy); /* Check the FSM Status to see if there were no errors */ if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0) { /* Put Error handling code here */ return flash_failure; } } return flash_succeed; } /* @brief 擦除块 * @param[in] oNewFlashBank:块编号 * * return: */ enum e_flash_status Flash_EraseBanks(Fapi_FlashBankType oNewFlashBank) { int num = 0; Fapi_StatusType oReturnCheck = Fapi_Status_Success; num = find_sector(oNewFlashBank, 0); oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作 if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy)) { oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank); //设置活动的Flash Bank if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) ) oReturnCheck = Fapi_enableMainBankSectors( 0xffffffff ); //设置EEPROM存储区中可用的扇区以进行擦除和编程 else if( oNewFlashBank == Fapi_FlashBank7 ) oReturnCheck = Fapi_enableEepromBankSectors(0xffffffff, 0xffffffff); //设置EEPROM存储区中可用的扇区以进行擦除和编程 while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy); Fapi_issueAsyncCommandWithAddress(Fapi_EraseBank, gSector_List[num].low_addr); //向Flash状态机发出命令 /* Place specific example code here */ /* Wait for FSM to finish */ while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy); /* Check the FSM Status to see if there were no errors */ if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0) { /* Put Error handling code here */ return flash_failure; } } return flash_succeed; } /* @brief 写扇区数据 * @param[in] oNewFlashBank:块编号 * @param[in] sector:扇区编号 * @param[in] offset:扇区偏移地址 * @param[in] buff:数据 * @param[in] len:数据长度 * * return: */ enum e_flash_status Flash_WriteData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len) { int num = 0; Fapi_StatusType oReturnCheck = Fapi_Status_Success; num = find_sector(oNewFlashBank, sector); //如果写的大小起过扇区的大小 if( (offset+len) > gSector_List[num].size ) { return flash_failure; } oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作 if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy)) { oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank); //设置活动的Flash Bank if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) ) oReturnCheck = Fapi_enableMainBankSectors( 1<<sector ); //设置EEPROM存储区中可用的扇区以进行擦除和编程 else if( oNewFlashBank == Fapi_FlashBank7 ) oReturnCheck = Fapi_enableEepromBankSectors(1<<sector ,1<<(sector%32)); //设置EEPROM存储区中可用的扇区以进行擦除和编程 while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy); Fapi_issueProgrammingCommand(gSector_List[num].low_addr+offset, buff, len, 0, 0, Fapi_DataOnly); //设置数据并将程序命令发送到有效的闪存地址 /* Place specific example code here */ /* Wait for FSM to finish */ while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy); /* Check the FSM Status to see if there were no errors */ if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0) { /* Put Error handling code here */ return flash_failure; } } return flash_succeed; } /* @brief 读扇区数据 * @param[in] oNewFlashBank:块编号 * @param[in] sector:扇区编号 * @param[in] offset:扇区偏移地址 * @param[in] buff:数据 * @param[in] len:数据长度 * * return: */ void Flash_ReadData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len) { int num = 0; num = find_sector(oNewFlashBank, sector); //如果读的大小超过扇区的大小 if( (offset+len) > gSector_List[num].size ) { return flash_failure; } memcpy(buff, gSector_List[num].low_addr+offset, len); } /* USER CODE BEGIN (0) */ #include "sys_common.h" #include "gio.h" #include "rti.h" #include "delay.h" #include "het.h" #include "pinmux.h" #include "F021.h" /* USER CODE END */ /* Include Files */ #include "sys_common.h" /* USER CODE BEGIN (1) */ /* USER CODE END */ /** @fn void main(void) * @brief Application main function * @note This function is empty by default. * * This function is called after startup. * The user can use this function to implement the application. */ /* USER CODE BEGIN (2) */ uint32 g_ulTransferAddress; uint8 flash_write_buf0[10] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x10}; uint8 flash_write_buf1[10] = {0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x10}; uint8 flash_write_buf2[10] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x10}; uint8 flash_write_buf3[10] = {0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x10}; uint8 flash_read_buf[10]; /* USER CODE END */ uint8 emacAddress[6U] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU}; uint32 emacPhyAddress = 1U; int main(void) { /* USER CODE BEGIN (3) */ int i = 0; gioInit(); muxInit(); rtiInit(); /* Set high end timer GIO port hetPort pin direction to all output */ gioSetDirection(hetPORT1, 0xFFFFFFFF); /* Enable RTI Compare 0 interrupt notification */ rtiEnableNotification(rtiNOTIFICATION_COMPARE0); /* Enable IRQ - Clear I flag in CPS register */ /* Note: This is usually done by the OS or in an svc dispatcher */ _enable_IRQ(); /* Start RTI Counter Block 0 */ rtiStartCounter(rtiCOUNTER_BLOCK0); printf("ENDIAN_REG = %x\n", ENDIAN_REG); //擦除整个块 Flash_EraseBanks(Fapi_FlashBank7); //读数据,这时读出来的全是FF Flash_ReadData(Fapi_FlashBank7, 0, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 1, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 2, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 3, 0, flash_read_buf, 10); //向4个扇区写不同的数据 Flash_WriteData(Fapi_FlashBank7, 0, 0, flash_write_buf0, 10); Flash_WriteData(Fapi_FlashBank7, 1, 0, flash_write_buf1, 10); Flash_WriteData(Fapi_FlashBank7, 2, 0, flash_write_buf2, 10); Flash_WriteData(Fapi_FlashBank7, 3, 0, flash_write_buf3, 10); //读数据,这时读出来的是刚才写入的数据 Flash_ReadData(Fapi_FlashBank7, 0, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 1, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 2, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 3, 0, flash_read_buf, 10); //擦除整个块 Flash_EraseBanks(Fapi_FlashBank7); //读数据,这时读出来的全是FF Flash_ReadData(Fapi_FlashBank7, 0, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 1, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 2, 0, flash_read_buf, 10); Flash_ReadData(Fapi_FlashBank7, 3, 0, flash_read_buf, 10); while(1) { } /* USER CODE END */ return 0; } /* USER CODE BEGIN (4) */ /* Note-You need to remove rtiNotification from notification.c to avoid redefinition */ void rtiNotification(uint32 notification) { /* enter user code between the USER CODE BEGIN and USER CODE END. */ /* Toggle HET pin 5 */ gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<5)); } /* USER CODE END */ 在sys_main.c中验证读写擦除操作是否生效 1.先擦除Fapi_FlashBank7 2.然后读Fapi_FlashBank7的4个扇区,读出来应该全为FF 3.然后向Fapi_FlashBank7的4个扇区分别写入不同的数据 4.再次读Fapi_FlashBank7的4个扇区,读出来应该刚才写入的数据 5.再擦除Fapi_FlashBank7 6.再次读Fapi_FlashBank7的4个扇区,读出来应该全为FF 以上证明flash读写擦除都正常 此内容由EEWORLD论坛网友石玉原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 回复了主题帖: TMS570学习2-bootload跳转实验

    石玉 发表于 2019-8-16 14:03 有一个地方没看明白,cmd文件中VECTORS段占用了起始的0x20个字节,是作什么用的?
    明白了,是异常向量表

  • 回复了主题帖: TMS570学习2-bootload跳转实验

    有一个地方没看明白,cmd文件中VECTORS段占用了起始的0x20个字节,是作什么用的?

  • 发表了主题帖: TMS570学习2-bootload跳转实验

    本帖最后由 石玉 于 2019-8-16 14:57 编辑 QQ:971586331 软件环境: 操作系统:windows 10 IDE:CCS7.4 代码生成工具:HALCoGen 04.07.01 烧写工具:CCS UniFlash 硬件环境: 目标板:TMDS570LS31HDK 本文内容:详细描述了TMS570系统处理器bootload跳转原理,编写2份程序,一个是bootload,一个是应用程序,在bootload中,使LED D5(HET1[00])闪烁5次后跳转到0x00180000处开始执行应用程序,应用程序中使LED D4(HET1[31])闪烁5次后软复位,再次执行bootload,如此往复。   1.编写bootload程序 按TMS570学习1中的流程新建工程boot_test,在hal下的sys_main.c中的编写主程序 /* USER CODE BEGIN (0) */ #include "sys_common.h" #include "gio.h" #include "delay.h" #include "het.h" #include "pinmux.h" #include "F021.h" /* USER CODE END */ /* Include Files */ /* USER CODE BEGIN (1) */ #define APP1_START_ADDRESS (0x00180000) #define APP2_START_ADDRESS (0x00040000) #define APP3_START_ADDRESS (0x00060000) #define APP4_START_ADDRESS (0x00080000) /* USER CODE END */ /** @fn void main(void) * @brief Application main function * @note This function is empty by default. * * This function is called after startup. * The user can use this function to implement the application. */ /* USER CODE BEGIN (2) */ uint32 g_ulTransferAddress; /* USER CODE END */ uint8 emacAddress[6U] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU}; uint32 emacPhyAddress = 1U; int main(void) { /* USER CODE BEGIN (3) */ int i = 0; gioInit(); muxInit(); /* Set high end timer GIO port hetPort pin direction to all output */ gioSetDirection(hetPORT1, 0xFFFFFFFF); for( i=0; i<10; i++) { gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<0)); my_delay(1000); } g_ulTransferAddress = (uint32_t)APP1_START_ADDRESS; ((void (*)(void))g_ulTransferAddress)(); //跳转程序指针 while(1) { } /* USER CODE END */ return 0; } /* USER CODE BEGIN (4) */ /* USER CODE END */ 在主程序中,我们先初始化IO,让HET1[00]闪烁5次,然后让程序指针跳转到0x00180000处开始运行,因为要下载2个程序,为了把程序下载到指定地址和防止程序地址空间冲突,修改cmd文件。 /* */ /*----------------------------------------------------------------------------*/ /* USER CODE BEGIN (0) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Linker Settings */ --retain="*(.intvecs)" /* USER CODE BEGIN (1) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Memory Map */ MEMORY { VECTORS (X) : origin=0x00000000 length=0x00000020 FLASH0 (RX) : origin=0x00000020 length=0x0017FFE0 //FLASH1 (RX) : origin=0x00180000 length=0x00180000 STACKS (RW) : origin=0x08000000 length=0x00001500 RAM (RW) : origin=0x08001500 length=0x0003EB00 /* USER CODE BEGIN (2) */ /* USER CODE END */ } /* USER CODE BEGIN (3) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Section Configuration */ SECTIONS { .intvecs : {} > VECTORS //.text : {} > FLASH0 | FLASH1 //.const : {} > FLASH0 | FLASH1 //.cinit : {} > FLASH0 | FLASH1 //.pinit : {} > FLASH0 | FLASH1 .text : {} > FLASH0 .const : {} > FLASH0 .cinit : {} > FLASH0 .pinit : {} > FLASH0 .bss : {} > RAM .data : {} > RAM .sysmem : {} > RAM /* USER CODE BEGIN (4) */ /* USER CODE END */ } /* USER CODE BEGIN (5) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Misc */ /* USER CODE BEGIN (6) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ 因为bootload程序上电启动,所以从0x00000000开始,FLASH1段的位置正好是我们放应用程序的位置,所以屏蔽掉,SECTIONS中的text等段就只能放在FLASH0中,编译下载,可以看到板上的HET1[00]灯闪烁5次后熄灭,因为0x00180000处没有代码可以执行,程序跑飞。 2.编写应用程序 按TMS570学习1中的流程新建工程test,在hal下的sys_main.c中的编写主程序 /* USER CODE BEGIN (0) */ /* USER CODE END */ /* Include Files */ #include "sys_common.h" /* USER CODE BEGIN (1) */ #include "rti.h" #include "het.h" #include "gio.h" #include "emif.h" #include "pinmux.h" #include "sci.h" #include "delay.h" #include <stdio.h> #include <reg_system.h> /* USER CODE END */ /** @fn void main(void) * @brief Application main function * @note This function is empty by default. * * This function is called after startup. * The user can use this function to implement the application. */ /* USER CODE BEGIN (2) */ /* USER CODE END */ uint8 emacAddress[6U] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU}; uint32 emacPhyAddress = 0U; int main(void) { /* USER CODE BEGIN (3) */ int i=0; int ret; int buff; /* Initialize RTI driver */ gioInit(); rtiInit(); muxInit(); sciInit(); sciEnableNotification(sciREG, SCI_RX_INT); /* Set high end timer GIO port hetPort pin direction to all output */ gioSetDirection(hetPORT1, 0xFFFFFFFF); /* Enable RTI Compare 0 interrupt notification */ rtiEnableNotification(rtiNOTIFICATION_COMPARE0); /* Enable IRQ - Clear I flag in CPS register */ /* Note: This is usually done by the OS or in an svc dispatcher */ _enable_IRQ(); /* Start RTI Counter Block 0 */ rtiStartCounter(rtiCOUNTER_BLOCK0); //让HET1[31]闪烁5次 for( i=0; i<10; i++) { gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<31)); my_delay(1000); } systemREG1->SYSECR = 0x8000; //软件复位 /* Run forever */ while(1) { //gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<0)); my_delay(1000); } /* USER CODE END */ return 0; } /* USER CODE BEGIN (4) */ /* Note-You need to remove rtiNotification from notification.c to avoid redefinition */ void rtiNotification(uint32_t notification) { /* enter user code between the USER CODE BEGIN and USER CODE END. */ /* Toggle HET pin 0 */ gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<17)); } /* USER CODE END */ 在主程序中,先初始化IO,然后让HET1[31]闪烁5次,然后让程序软复位,因为应用程序要放到0x00180000位置,所以要修改cmd文件 /* */ /*----------------------------------------------------------------------------*/ /* USER CODE BEGIN (0) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Linker Settings */ --retain="*(.intvecs)" /* USER CODE BEGIN (1) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Memory Map */ MEMORY { //VECTORS (X) : origin=0x00000000 length=0x00000020 VECTORS (X) : origin=0x00180000 length=0x00000020 //FLASH0 (RX) : origin=0x00000020 length=0x0017FFE0 FLASH1 (RX) : origin=0x00180020 length=0x0001FFE0 STACKS (RW) : origin=0x08000000 length=0x00001500 RAM (RW) : origin=0x08001500 length=0x0003EB00 /* USER CODE BEGIN (2) */ /* USER CODE END */ } /* USER CODE BEGIN (3) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Section Configuration */ SECTIONS { .intvecs : {} > VECTORS //.text : {} > FLASH0 | FLASH1 //.const : {} > FLASH0 | FLASH1 //.cinit : {} > FLASH0 | FLASH1 //.pinit : {} > FLASH0 | FLASH1 .text : {} > FLASH1 .const : {} > FLASH1 .cinit : {} > FLASH1 .pinit : {} > FLASH1 .bss : {} > RAM .data : {} > RAM .sysmem : {} > RAM /* USER CODE BEGIN (4) */ /* USER CODE END */ } /* USER CODE BEGIN (5) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ /* Misc */ /* USER CODE BEGIN (6) */ /* USER CODE END */ /*----------------------------------------------------------------------------*/ 因为程序要在0x00180000开始,所将起始地址改为0x00180000,屏蔽FLASH0,SECTIONS中的段放在FLASH1中,编译程序,此时不能仿真因为程序不是下载到0地址的 3.烧写引导程序和应用程序 用TI的CCS UniFlash工具一次性烧写引导和应用程序 点Add选择引导和应用程序的out文件,点击Program,按下开发板上的复位键,可以观察到HET1[0]闪烁5次后HET1[31]闪烁5次,然后重复,说明先运行了bootload程序,然后运行了应用程序,应用程序运行完后程序复位,又运行bootload程序。 此内容由EEWORLD论坛网友石玉原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 发表了主题帖: TMS570学习1-创建工程点灯

    本帖最后由 石玉 于 2019-8-16 14:57 编辑 软件环境: 操作系统:windows 10 IDE:CCS7.4 代码生成工具:HALCoGen 04.07.01 硬件环境: 目标板:TMDS570LS31HDK   1.新建CCS工程 打开CCS,File->New->CCS Project,选择控制器型号,仿真器型号,输入工程名,选择空工程 工程结构如下图所示 2.新建HALCoGen 工程 打开HALCoGen,File->New->Project,选择芯片型号,填写工程名,选择CCS工程目录,选择开发工具为TI的 可以看到对芯片的功能可以图形化配置,这里我们不配置,直接File->Generate Code生成代码 生成后CCS工程如下所示,可以看到hal下多了源文件和头文件,hcg是HALCoGen工程文件 3.编写主函数 打开hal下的sys_main.c,注意代码中的“USER CODE BEGIN”和“USER CODE END”,用户编写的代码要放在USER CODE当中,不然重新生成代码后USER CODE之外的代码不会保留。 查看TMDS570LS31HDK板原理图,我们让D5闪烁。 D5连接的IO是HET1[00]。所以我们在代码中控制HET1模块的第0个引脚输出。 /* USER CODE BEGIN (0) */ #include "delay.h" #include "gio.h" #include "reg_het.h" /* USER CODE END */ /* Include Files */ #include "sys_common.h" /* USER CODE BEGIN (1) */ /* USER CODE END */ /** @fn void main(void) * @brief Application main function * @note This function is empty by default. * * This function is called after startup. * The user can use this function to implement the application. */ /* USER CODE BEGIN (2) */ /* USER CODE END */ uint8 emacAddress[6U] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU}; uint32 emacPhyAddress = 1U; int main(void) { /* USER CODE BEGIN (3) */ gioInit(); muxInit(); /* Set high end timer GIO port hetPort pin direction to all output */ gioSetDirection(hetPORT1, 0xFFFFFFFF); while(1) { gioSetPort(hetPORT1, gioGetPort(hetPORT1) ^ (1<<0)); my_delay(1000); } /* USER CODE END */ return 0; } /* USER CODE BEGIN (4) */ /* USER CODE END */ 主函数中添加控制IO需要的头文件,然后初始化IO和引脚复用,gioSetDirection将HET1的所有引脚设置为输出,gioSetPort设置输出值,编译工程,如果提示头文件找不到,在工程->properties->include options中添加头文件的路径,开始仿真,可以发现开发板上的D5开始闪烁。 此内容由EEWORLD论坛网友石玉原创,如需转载或用于商业用途需征得作者同意并注明出处

  • 2019-08-14
  • 回复了主题帖: 几次面试,说说感受,应届生真成大白菜了!

    14年毕业时一个月才2500

  • 2019-08-07
  • 回复了主题帖: 【奖品发送完毕】快来访问泰克高速串行通信专题 配置您的专属解决方案 赢好礼!

    确认信息无误,麻烦兑换成E金币,谢谢EEWORLD

  • 2019-08-02
  • 回复了主题帖: TMS570LS 如何配置PBIST、STC和ESM?

    楼主能不能留个联系方式,有问题想请教,谢谢(QQ:971586331)

  • 2019-07-30
  • 回复了主题帖: 单独烧录dtb文件

    DTB不是有个分区放吗,烧到分区不就可以了

  • 2019-07-26
  • 回复了主题帖: 【奖品发送完毕】:是德科技 DATA Center 资料,满足您的需求~下载有好礼!

    确认个人信息无误,请帮我兑换为E金币,谢谢EEWORLD

  • 2019-07-23
  • 回复了主题帖: 请教TMS570外接SDRAM使用的方法

                                                    学习了,楼主有用EMIF外接过nand flash吗?                        

  • 2019-07-01
  • 加入了学习《将JTAG与UCD3138配合使用》,观看 将JTAG与UCD3138配合使用:使用CCS JTAG Flash GUI下载程序

  • 2019-06-19
  • 回复了主题帖: itop4418开发板操作过程中遇到问题

    这样操作是不是要在内核中先初始化这个IO

  • 2019-06-13
  • 回复了主题帖: itop4412开发板Android4.0.3镜像的编译

    刚买了这块板,学习了

  • 2019-05-15
  • 发表了主题帖: Silicon Labs Bluetooth EFR32MG学习笔记 1 - 安装Simplicity Studio开发环境

    shiyu 20190515 in Shenzhen QQ:971586331 软件环境:Windows 10、Simplicity Studio 4 硬件环境:Silicon Labs Wireless Starter Kit Mainboard(BRD4001A Rev A01),BGM111 Bluetooth Module Radio Board(BRD4300A Rev A01) 1.在管网下载Simplicity Studio https://www.silabs.com/support/g ... luetooth-low-energy 2.将开发板接入电脑(如果你有开发板的话,没有也没有关系,可以手动选择) 3.安装一路下一步,在图3-1时选择是通过设备安装开发包还是通过产品系列安装开发包,选择第一项 图3-1 https://img-blog.csdnimg.cn/201905150916382.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N5ODQ0MzY0NDY=,size_16,color_FFFFFF,t_70 4.如果你接入了开发板,这里会自动识别出来,如果没有开发板,在左下角选择你的设备,按>>选择,下一步 图4-1 https://img-blog.csdnimg.cn/20190515092119305.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N5ODQ0MzY0NDY=,size_16,color_FFFFFF,t_70 5.这时可能要登录Silicon Labs账号,没有的话注册一个,下一步 图5-1 https://img-blog.csdnimg.cn/20190515092343618.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N5ODQ0MzY0NDY=,size_16,color_FFFFFF,t_70 6.这时显示要安装的开发包,默认就好,因为我之前已经安装过,所以很多开发包都没有显示出来,取消“show latest versions”前的勾可以显示历史版本的SDK,根据需要安装,下方会显示要下载数据的大小,按Finish https://img-blog.csdnimg.cn/20190515092634169.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N5ODQ0MzY0NDY=,size_16,color_FFFFFF,t_70 7.开始下载和安装SDK,等待安装完成后重启IDE https://img-blog.csdnimg.cn/20190515093046362.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N5ODQ0MzY0NDY=,size_16,color_FFFFFF,t_70 8.进入IDE后在IDE的左边会显示你当前连接的设备,右下角会显示你当前使用的SDK和例程 https://img-blog.csdnimg.cn/20190515093252790.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N5ODQ0MzY0NDY=,size_16,color_FFFFFF,t_70 下一篇会介绍如何更新适配器固件和烧录演示Demo 此内容由EEWORLD论坛网友石玉原创,如需转载或用于商业用途需征得作者同意并注明出处

统计信息

已有799人来访过

  • 芯币:2370
  • 好友:14
  • 主题:90
  • 回复:869
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


yuyang159 2018-10-25
石先生 您好,我们公司最近设计了一款GPIB设备,设备的主要流程为通过arm模拟IO时序控制NAT9914 与电脑带的GPIB卡链接,通过对9914的初始化后发现GPIB卡未能找到设备(此时9914设备被置为讲者状态,但BO位并未置为高),请问你们开发遇见过这个问题没 ,任何帮助都不胜感激
chenbingjy 2016-5-17
你好!你QQ多少?方便想你请教Linux下编译安卓开发内核?谢谢!
bingling_894 2014-6-29
石玉: 可以,你告诉我地址和电话,我寄给你后你你再给邮费我,
嗯嗯,好的,真的很谢谢你。可以问你要QQ吗?我在那上面发给你。
bingling_894 2014-6-29
石玉: 需要那几本书?
可以借MSP430单片机原理与实例详解和proteus这两本吗?谢谢!
bingling_894 2014-6-29
石玉: 需要那几本书?
可以借MSP430单片机原理与实例应用和proteus这两本吗?谢谢!
TCYAMAKASI 2014-6-10
石同学,您好,我是东华大学的唐川,我想请教一下有关磁悬浮的技术,请问可以发我信息吗?手机:13917978563
查看全部