S3C2416裸机开发系列二十_Libjpeg的移植

发布者:zukeq2009最新更新时间:2016-12-12 来源: eefocus关键字:S3C2416  裸机开发  Libjpeg  移植 手机看文章 扫描二维码
随时随地手机看文章

jpeg格式是一种针对相片影像而广泛使用的一种失真压缩标准,其压缩技术十分先进,用有损压缩方式去除冗余的图像数据,在获得极高压缩率的同时,能展现十分丰富生动的图像,能用最少的磁盘空间得到较好的图像品质。由于其尺寸较小,能够较快地在网络上传输,因此在数码相机、网页等领域均广泛应用到jpeg图像格式。笔者此处就移植libjpeg开源库来应用jpeg作一个简单的介绍。

1. 代码准备

libjpeg源码,libjpeg是一个完全用c语言编写的库,包含了被广泛使用的jpeg编码、jpeg解码和其它的jpeg功能的实现,这个库由独立的jpeg工作组维护。请读者自行到官网下载最新的源码。

s3c2416启动代码工程,启动代码是s3c2416/50/51这系列arm9芯片在运行用户c代码main函数之前必须先运行的代码,启动代码支持sd、Nand启动,为用户设置系统时钟,初始化内存,自动识别启动设备并搬移代码到RAM,MMU映射,中断管理等,支持x、ymodem文件传输协议,代码可直接通过串口下载进RAM执行,用户只需专注于用c开发其它功能函数即可。关于启动代码以及启动代码的实现过程,笔者前面章节有非常详细的介绍。此处在MDK下开发,下载”MDK启动代码工程应用实例”中的启动代码源码。

用户代码,用c开发的所有功能代码,其中,用户代码入口为main()函数,在这里用libjpeg库实现在屏上显示jpeg图像以及屏幕截图保存成jpeg图片。

2. 标准io库函数

libjpeg由于其开源免费,对桌面操作系统均有良好的支持,因此在linux、windows操作系统下均常用libjpeg来编解码jpeg图片。libjpeg以及例程使用了标准io库函数,如文件操作fopen、fread、fwrite等;输入、输出、错误流函数printf、fprintf等。对于嵌入式开发来说,所有的io操作均是面对特定设备,编译器的标准c库是无法统一实现的,应由用户去实现。在arm编译器中,是使用一种半主机的模式,当用户使用了标准io库函数时,默认情况下,编译器是通过一组定义好的软中断来把io应用请求传送至运行调试器的主机,如用printf和scanf来使用主机的屏幕以及键盘,需要jtag的支持。一旦目标板脱离主机,需单独运行时,在半主机模式下是无法运行,因为io软中断请求无法得到处理。因此对于libjpeg移植,我们必须先对所使用到的io库函数进行重定向,如把输入、输出、错误流重定向到串口,把文件操作重定向到对sd卡的文件操作。此处我们在sd卡中采用的是fatfs文件系统,关于fatfs的移植,笔者在前面的章节有详细的介绍,此处不再详述。在MDK中,标准io库函数最终是通过系统调用接口来完成实质的io请求,我们必须在这些系统调用接口上重定向为目标板上特定设备的请求操作。对于linux操作系统,标准io库函数最终也是通过系统调用,从用户态转到内核态,通过系统api完成实质的io请求操作。在Retarget.c中我们实现所有的标准io库函数的重定向,该部分的代码如下:

#include

#include

#include

#include

#include

#include "ff.h"

#include "diskio.h"

#include "UART0.h"

 

#pragma  import (__use_no_semihosting_swi)

#defineSTDIO  1

 

/* Standard IO device handles. */

#define STDIN   0x1

#define STDOUT  0x2

#define STDERR  0x3

 

/* Standard IO device name defines. */

const char __stdin_name[]  = "STDIN";

const char __stdout_name[] = "STDOUT";

const char __stderr_name[] = "STDERR";

 

struct  __FILE {int handle; /* Add whatever you need here */ };

 

#ifdef  STDIO

 

/*-----------------------------------------------------------------------------

  Write character to the Serial Port

 *----------------------------------------------------------------------------*/

int sendchar(int c) {

  if (c == '\n')  {

    Uart0_SendByte('\r');

  }

  Uart0_SendByte(c);

  return (c);

}

 

/*-----------------------------------------------------------------------------

  Read character from the Serial Port

 *----------------------------------------------------------------------------*/

int getkey(void) {

  int ch = Uart0_ReceiveByte();

  if (ch < 0) {

    return 0;

  }

  return ch;

}

#endif

 

/*---------------------------_ttywrch ---------------------------------------*/

void  _ttywrch(int ch) {

#ifdef STDIO

  sendchar (ch);

#endif

}

 

/*---------------------------_sys_open --------------------------------------*/

 

FILEHANDLE _sys_open (const char *name, int openmode) {

  FRESULT Res;

  FILEHANDLE fh;

  BYTE Mode = FA_READ;

  /* Register standard Input Output devices. */

  if (strcmp(name, "STDIN") == 0) {

    return (STDIN);

  }

  if (strcmp(name, "STDOUT") == 0) {

    return (STDOUT);

  }

  if (strcmp(name, "STDERR") == 0) {

    return (STDERR);

  }

 

  if (openmode & OPEN_W) {

      Mode|= FA_WRITE | FA_OPEN_ALWAYS;

      Mode&= ~FA_READ;

  } 

  if (openmode & OPEN_PLUS) {

      Mode|= FA_WRITE | FA_READ;

  } 

  if (openmode & OPEN_A) {

      Mode|= FA_OPEN_ALWAYS;

  }

  fh = (FILEHANDLE)malloc(sizeof(FIL));

  if (fh == NULL) {

     return -1;

  }

  Res = f_open((FIL *)fh, name, Mode);

  if (Res == RES_OK) {

     return fh;

  } else {   

     free((FIL *)fh);

     return -1;     

  }

}

 

/*---------------------------_sys_close -------------------------------------*/

int  _sys_close(FILEHANDLE fh) {

  FRESULT Res;

  if (fh > 0 && fh < 4) {

    return (0);

  }

  Res = f_close((FIL *)fh);

  free((FIL *)fh);

  if (Res == RES_OK) {

     return 0;

  }

  return -1;

}

 

/*---------------------------_sys_write -------------------------------------*/

int  _sys_write(FILEHANDLE fh, const uint8_t *buf, uint32_t len, int32_t mode) {

  FRESULT Res;

  UINT ByteWrite;  

#ifdef STDIO

  if (fh > 0 && fh < 4) {

    if (fh == STDOUT) {

        /* Standard Output device. */

        for ( ; len; len--) {

        sendchar (*buf++);

        }

        return (0);

    } else {

        return (-1);

    }

  }

#endif

 

#if!(_FS_READONLY)

  Res = f_write((FIL *)fh, buf, len,&ByteWrite);

  if (Res == RES_OK) {

      if(ByteWrite < len) {

         return (len-ByteWrite);

      }

     return 0;

  }

#endif

  return -1;

}

 

/*---------------------------_sys_read --------------------------------------*/

int  _sys_read(FILEHANDLE fh, uint8_t *buf, uint32_t len, int32_t mode) {

  FRESULT Res;

  UINT ByteRead;

#ifdef STDIO

  if (fh > 0 && fh < 4) {  

    if (fh == STDIN) {

        /* Standard Input device. */

        for ( ; len; len--) {

            *buf++ = getkey ();

        }

        return (0);

    } else {

        return (-1);

    }

  }

#endif

   

  Res = f_read((FIL *)fh, buf, len,&ByteRead);

  if (Res == RES_OK) {

      if(ByteRead < len) {

         return (len-ByteRead);

      }

     return 0;

  }

  return -1;

}

 

/*---------------------------_sys_istty -------------------------------------*/

int  _sys_istty(FILEHANDLE fh) {

  if (fh > 0 && fh < 4) {

    return (1);

  }

  return (0);

}

 

/*---------------------------_sys_seek --------------------------------------*/

int  _sys_seek(FILEHANDLE fh, long pos) {

  FRESULT Res; 

  if (fh > 0 && fh < 4) {

    return (-1);

  }

 

#if_FS_MINIMIZE < 3

  Res = f_lseek((FIL *)fh, pos);

  if (Res == RES_OK) {

     return 0;

  }

#endif 

  return (-1);

}

 

/*---------------------------_sys_ensure ------------------------------------*/

int  _sys_ensure(FILEHANDLE fh) {

  FRESULT Res;

  if (fh > 0 && fh < 4) {

    return (-1);

  }

 

#if!(_FS_READONLY)

  Res = f_sync((FIL *)fh);

  if (Res == RES_OK) {

    return 0;

  }

#endif

  return -1;

}

 

/*---------------------------_sys_flen --------------------------------------*/

long  _sys_flen(FILEHANDLE fh) {

  if (fh > 0 && fh < 4) {

    return (0);

  }

  return  f_tell((FIL *)fh);

}

 

/*---------------------------_sys_tmpnam ------------------------------------*/

int  _sys_tmpnam(char *name, int sig, unsigned maxlen) {

  return (1);

}

 

/*---------------------------_sys_command_string ----------------------------*/

char* _sys_command_string (char *cmd, int len) {

  return (cmd);

}

 

/*---------------------------_sys_exit --------------------------------------*/

void  _sys_exit(int return_code) {

  /* Endless loop. */

  while (1);

}

 

3. libjpeg移植

首先解压从官网下载的libjpeg源码,有很多的文件,其中以j命名开头的.h、.c文件均是源码文件,其它的有Makefile、shell脚本以及例程代码等,详细信息以及libjpeg的使用请参考源码包中的文档。把jpeg源码文件提取出加入到MDK工程,在libjpeg源码包中还包含读写bmp、gif等例程源码,可根据需要提取加入工程。此处由于重定向了标准io库函数,libjpeg内存分配也采用默认的c库malloc/free函数,因此,移植无需任何的修改,加入工程即可进行编译。

4. 显示jpeg图片

加入了文件系统fatfs,并对io库函数进行重定向以后,就可以用libjpeg库函数进行jpeg图片的编解码了。目前大量基于桌面操作系统的libjpeg应用例程均无需作太多的修改就可以应用到我们的嵌入式系统中。此处完全采用libjpeg源码包中的jpeg解压例程,但解压的像素数据输出到屏上进行显示,当然也可以输出到一块缓存中,再对缓存进行图像处理等。

struct my_error_mgr {

  struct jpeg_error_mgr pub;    /* "public" fields */

  jmp_buf setjmp_buffer;    /* for return to caller */

};

 

typedef struct my_error_mgr * my_error_ptr;

 

void my_error_exit (j_common_ptr cinfo)

{

  /* cinfo->err really points to amy_error_mgr struct, so coerce pointer */

  my_error_ptr myerr = (my_error_ptr)cinfo->err;

  /* We could postpone this untilafter returning, if we chose. */

  (*cinfo->err->output_message)(cinfo);   

  /* Return control to the setjmppoint */

  longjmp(myerr->setjmp_buffer,1);

}

 

int32_t LCD_DisplayJpeg(char * filename, int x, int y)

{

  struct jpeg_decompress_structcinfo;

  struct my_error_mgr jerr;

  FILE * infile;        /* source file */

  JSAMPARRAY buffer;        /* Output row buffer */

  JSAMPROW   RowBuffer;     /* a row buffer */ 

  uint16_t *pBuffer;

  uint8_t r, g, b;

  int row_stride;       /* physical row width in output buffer */

  uint32_t i;

  uint32_t DisplayWidth;

  uint32_t DisplayHeight;

   

  if (x<0 || x>(HSize-1) ||y<0 || y>(VSize-1)) {

     printf("parameter error\n");   

     return -1;

  }

 

  if ((infile = fopen(filename,"rb")) == NULL) {

    fprintf(stderr, "can't open%s\n", filename);

    return 1;

  }

 

  /* Step 1: allocate and initializeJPEG decompression object */

  cinfo.err =jpeg_std_error(&jerr.pub);

  jerr.pub.error_exit =my_error_exit;

  if (setjmp(jerr.setjmp_buffer)) {

   jpeg_destroy_decompress(&cinfo);

    fclose(infile);

    return 2;

  }

  /* Now we can initialize the JPEGdecompression object. */

  jpeg_create_decompress(&cinfo);

 

  /* Step 2: specify data source (eg,a file) */

  jpeg_stdio_src(&cinfo, infile);

 

  /* Step 3: read file parameterswith jpeg_read_header() */

  (void) jpeg_read_header(&cinfo,TRUE);

 

  /* Step 4: set parameters fordecompression */

  /* In this example, we don't needto change any of the defaults set by

   * jpeg_read_header(), so we donothing here.

   */

 

  /* Step 5: Start decompressor */

  (void) jpeg_start_decompress(&cinfo); 

   if (HSize - x >cinfo.output_width) {

    DisplayWidth = cinfo.output_width;   

  } else {

    DisplayWidth = HSize - x;

  }

  if (VSize - y >cinfo.output_height) {

    DisplayHeight =cinfo.output_height;

  } else {

    DisplayHeight = VSize - y;

  }   

  cinfo.output_width = DisplayWidth;

 cinfo.output_height =DisplayHeight;

 

  row_stride = cinfo.output_width *cinfo.output_components;

  buffer =(*cinfo.mem->alloc_sarray)

        ((j_common_ptr) &cinfo,JPOOL_IMAGE, row_stride, 1);

 

  /* Step 6: while (scan lines remainto be read) */

  /*           jpeg_read_scanlines(...); */

  while (cinfo.output_scanline

    (void)jpeg_read_scanlines(&cinfo, buffer, 1);

    pBuffer = (uint16_t*)GetFrameBuffer() + x + y*HSize;

    RowBuffer = *buffer;

    for (i=0; i

        r = *RowBuffer++;

        r >>= 3;

        g = *RowBuffer++;

        g >>= 2;

        b = *RowBuffer++;

        b >>= 3;

        *pBuffer++=((uint16_t)r << 11)|((uint16_t)g << 5)|((uint16_t)b << 0);

    }

    y++;

  }

 

  /* Step 7: Finish decompression */

  (void)jpeg_finish_decompress(&cinfo);

 

  /* Step 8: Release JPEGdecompression object */

 jpeg_destroy_decompress(&cinfo);

  fclose(infile);

 

  /* And we're done! */

  return 0;

}

5. 屏幕截图

像素数据可以保存成jpeg图片文件,此处把屏缓存数据提取出进行jpeg编码,并在sd卡中保存成jpeg文件。

// (x0, y0)为截屏的左上角像素位置,(x1,y1)为右下角像素位置

int32_t LCD_CaptureScreen (char * filename, int x0, int y0, int x1, int y1,int quality)

{

  struct jpeg_compress_struct cinfo;

  struct jpeg_error_mgr jerr;

  /* More stuff */

  FILE * outfile;       /* target file */

  JSAMPARRAY buffer;        /* Output row buffer */

  JSAMPROW   RowBuffer;     /* a row buffer */ 

  int row_stride;       /* physical row width in image buffer */   

  uint16_t *pBuffer;

  uint32_t i;

  int Width;

  int Height;

 

  if (x0<0 || x1>HSize ||y0<0 || y1>VSize) {

     printf("parameter error\n");   

     return -1;

  } 

  Width = x1 - x0;

  Height = y1 - y0;

  if (Width <= 0 && Height<= 0) {

     printf("parameter error\n");

     return -2;

  }

 

  /* Step 1: allocate and initializeJPEG compression object */

  cinfo.err =jpeg_std_error(&jerr);

  /* Now we can initialize the JPEGcompression object. */

  jpeg_create_compress(&cinfo);

 

  /* Step 2: specify data destination(eg, a file) */

  /* Note: steps 2 and 3 can be donein either order. */

  if ((outfile = fopen(filename,"wb")) == NULL) {

    fprintf(stderr, "can't open%s\n", filename);

    return 1;

  }

 

  jpeg_stdio_dest(&cinfo,outfile);

 

  /* Step 3: set parameters forcompression */

  cinfo.image_width = Width;    /* image width and height, in pixels */

  cinfo.image_height = Height;

  cinfo.input_components = 3;       /* # of color components per pixel */

  cinfo.in_color_space = JCS_RGB;   /* colorspace of input image */

 

  jpeg_set_defaults(&cinfo);

  jpeg_set_quality(&cinfo,quality, TRUE /* limit to baseline-JPEG values */);

 

  /* Step 4: Start compressor */

  jpeg_start_compress(&cinfo,TRUE);

  /* Step 5: while (scan lines remainto be written) */

  /*           jpeg_write_scanlines(...); */

  row_stride = Width * 3;   /* JSAMPLEs per row in image_buffer */

  buffer =(*cinfo.mem->alloc_sarray)

        ((j_common_ptr) &cinfo,JPOOL_IMAGE, row_stride, 1);

 

  while (cinfo.next_scanline

    RowBuffer = *buffer;

    pBuffer = (uint16_t*)GetFrameBuffer() + x0 + y0*HSize;

    for (i=0; i

        *RowBuffer++ = (*pBuffer &0xf800) >> 8;

        *RowBuffer++ = (*pBuffer &0x7e0) >> 3;

        *RowBuffer++ = (*pBuffer &0x1f) << 3;

        pBuffer++;

    }

    (void)jpeg_write_scanlines(&cinfo, buffer, 1);

    y0++;

  }

 

  /* Step 6: Finish compression */

  jpeg_finish_compress(&cinfo);

  /* After finish_compress, we canclose the output file. */

  fclose(outfile);

 

  /* Step 7: release JPEG compressionobject */

  /* This is an important step sinceit will release a good deal of memory. */

  jpeg_destroy_compress(&cinfo);

 

  /* And we're done! */

  return 0;

}

6. 测试实例

写好jpeg显示函数以及屏幕截图函数,就可以在main函数中编写调用测试代码,在代码中实现按”1”进行jpeg图片的显示,按”2”进行截屏保存成jpeg图片。

#include "s3c2416.h"

#include "ff.h"

#include "diskio.h"

#include "RTC.h"

#include "UART0.h"

#include "stdio.h"

#include "stdint.h"

#include "lcd_rgb.h"

 

extern int32_t LCD_DisplayJpeg(char * filename, int x, int y);

extern int32_t LCD_CaptureScreen (char * filename, int x0, int y0, int x1,int y1, int quality);

 

int main()

{

    uint8_t Command;

    FATFS fs;

 

    RTC_Time Time = {

        2014, 5, 22, 23, 00, 0, 5

    }; 

   

    RTC_Init(&Time);

    Uart0_Init();

    RTC_GetTime(&Time);

    printf("Time: %4d/%02d/%02d%02d:%02d:%02d\n", Time.Year,

                Time.Month, Time.Day,Time.Hour, Time.Min, Time.Sec);

    LCD_RGB_Init();

    f_mount(&fs, "" ,0);

    LCD_ClearScreen(0x1f);

    while (1) {

        printf("1: displaytest.jpg\n");

        printf("2: capture screenand save as a jpg file\n");

        Command = Uart0_ReceiveByte();

        if (Command == '1') {

            if(LCD_DisplayJpeg("test.jpg", 20, 20)) {

                printf("displaypicture failed\n");

            }

        } else if (Command == '2') {

            if(LCD_CaptureScreen("screen.jpg", 0, 0, HSize, VSize, 80)) {

                printf("capturescreen failed\n");

            }

        }

        printf("\n");

    }

}

7. 广 告

以下内容可能引起您的不适和反感,心理承受能力差的读者请跳过本段。本人代理广州斯道s3c2416开发板,负责s3c2416裸机方面的开发支持,有需要的童鞋可以联系本人^_^(qq: 1048272975,8位机、cortex-m0/m3、arm7/arm9均可免费支持)。icool2416由广州斯道一流开发团队设计,主处理器采用三星的S3C2416,cpu主频标配400M,可以稳定支持到533M,内存采用64MB DDR2 K4T51163(266M),NAND flash采用256MB SLCK9F2G08U0B,板载10/100M有线DM9000网卡,专业声卡WM8960,标配7寸RGB屏,真实5点触摸电容屏,外扩usb主从接口、rs232、tf卡座等标准接口,供电部分采用专业Torex的DC/DC芯片,具有非常良好的功耗,是一款极具性价比的开发板。

8. 附录

Libjpeg_MDK.rar,MDK下libjpeg移植工程源码,包含屏显示jpeg图片以及截屏保存成jpeg文件源码。

http://pan.baidu.com/s/1jGn6A26


关键字:S3C2416  裸机开发  Libjpeg  移植 引用地址:S3C2416裸机开发系列二十_Libjpeg的移植

上一篇:S3C2416裸机开发系列二一_Yaffs的移植
下一篇:S3C2416裸机开发系列十九_Fatfs下播放录音wav音频文件

推荐阅读最新更新时间:2024-03-16 15:24

ARM裸机开发笔记1(指令简介)
1.非常简单的ARM程序: arm.s文件内容 AREA Example,CODE,READONLY ;声明代码段 AREA:定义代码段 Example是代码段名称CODE:代码段关键字READONLY:只读关键字 ENTRY ;相当于C程序中的main函数,标识程序的入口 CODE32 ;使用32位指令集 START MOV R0,#1 ;具体的汇编指令 MOV R0,#0
[单片机]
Android系统移植主要事项
  移Android系统的移植工作的目的是为了在特定的硬件上运行Android系统。在移植的过程中,把握关键要点,减少工作量是一个重要的方面。从工作的角度,通常的方法为,首先要熟悉硬件抽象层的接口,其次要集成和复用已有的驱动程序,主要的工作量在硬件抽象层的实现中。为了更好地理解和调试系统,也应该适当地了解上层对硬件抽象层的调用情况。   移植方面主要的工作有两个部分:   Linux驱动   Android系统硬件抽象层   Linux中的驱动工作在内核空间,Android系统硬件抽象层工作在用户空间,有了这两个部分的结合,就可以让庞大的Android系统运行在特定的硬件平台上。   Android移植的主要工
[嵌入式]
alsa-lib及alsa-utils成功移植
准备工作 alsa-lib版本:alsa-lib-1.0.23.tar.bz2 alsa-util版本:alsa-utils-1.0.23.tar.bz2 其他版本的alsa-lib和alsa-util不能保证正常工作 arm板子:s3c2416 板子上linux内核:2.6.xx pc虚拟机:arm-linux-gcc:4.4.6 首先在Ubuntu上交叉、编译alsa-lib和alsa-util 1.解压alsa-lib-1.0.23.tar.bz2,进入解压所得目录 2.使用命令 ./configure --host=arm-jyxtec-linux-gnueabi --prefix=/usr/share/arm-als
[单片机]
Android平台移植应该做两步工作
    Android系统的移植工作的目的是为了在特定的硬件上运行Android系统。在移植的过程中,把握关键要点,减少工作量是一个重要的方面。从工作的角度,通常的方法为,首先要熟悉硬件抽象层的接口,其次要集成和复用已有的驱动程序,主要的工作量在硬件抽象层的实现中。为了更好地理解和调试系统,也应该适当地了解上层对硬件抽象层的调用情况。     移植方面主要的工作有两个部分:     Linux驱动     Android系统硬件抽象层     Linux中的驱动工作在内核空间,Android系统硬件抽象层工作在用户空间,有了这两个部分的结合,就可以让庞大的Android系统运行在特定的硬件平台上。     Androi
[嵌入式]
浅谈μCOSII在Cortex-M3核的ARM处理器上的移植
随着科学技术的发展,嵌入式技术已被广泛应用到汽车电子、无线通信、数码产品等各个领域。嵌入式操作系统及嵌入式处理器技术发展迅猛,嵌入式操作系统典型代表有μCOS—II、μClinux、Winclow CE、VxWorks等;嵌入式处理器包括ARM、MIPS、PowerPC等。 1 软硬件开发环境及处理器介绍 1.1 软件硬开发环境 本移植过程使用的软件环境是RealView MDK开发套件,此产品是ARM公司最新推出的针对各种嵌入式处理器的软件开发工具,该开发套件功能强大,包括了μVisiON3集成开发环境和RealView编译器。使用的硬件平台是深圳英蓓特公司推出的全功能评估板STMl03V100,其上所采用的处理器是S
[工业控制]
浅谈μCOSII在Cortex-M3核的ARM处理器上的<font color='red'>移植</font>
stm32之nRF24L01无线模块(1):SPI2到SPI1的移植
本来要接着写滴答定时器的,但是趁热打铁写下SPI2到SPI1的移植。 为什么SPI2到SPI1的移植要放在nRF24L01模块里写呢,因为无线模块最重要的数据传输就是通过SPI实现的。为什么需要移植呢,因为即使是一个厂家的板子,不同型号之间它的无线模块引脚也有可能是不同的,顺便稿下移植,加深下理解。SPI2移植到SPI1呢,自己做的时候遇到了一些问题,就从遇到的问题顺便讲下初始化。 1.引脚问题 看stm32的手册,不知道为什么,无论在GPIO还是在SPI里都没有看到这个引脚的问题(初学者有可能移植的时候可能纳闷为什么是这些引脚),只有在引脚复用AFIO那里才提了一下,如下图 这样才知道SPI1的引脚,但是
[单片机]
stm32之nRF24L01无线模块(1):SPI2到SPI1的<font color='red'>移植</font>
移植uboot-支持yaffs烧写,打补丁
1. 修改uboot支持yaffs 首先,每个命令都会对应一个文件,比如nand命令对应的common/cmd_nand.c 而我们使用nand命令时,便会进入do_nand()函数,位于common/cmd_nand.c 1.1do_nand()函数代码如下所示: int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv ) { ... ... if (strncmp(cmd, read , 4) == 0 || strncmp(cmd, write , 5) == 0) { ... ... #ifdef CONFIG_C
[单片机]
<font color='red'>移植</font>uboot-支持yaffs烧写,打补丁
Micro2440 Nboot ADS 移植到Keil5编译通过
由于项目需要开发老版本S3C2440,由于时间有限系统当然跑WinCE6.0,软件兼容性好 当然安装开发工具等等一大堆是相当头疼,之前做STM32特别多,个人电脑一大堆都是32的BSP包,keil用的特别顺手,这次开发2440需要用到友善提供的Nboot,由于ADS软件兼容行特差问题太多不想折腾了,将Nboot移植到keil5上, 步骤1: 需要下载keil下ARM9的支持包,给上逻辑 http://www2.keil.com/mdk5/legacy,下载Legacy support for Arm7, Arm9 & Cortex-R devices安装即可。 步骤2: 将所有Nboot文件拷贝到keil工程下,如
[单片机]
Micro2440 Nboot ADS <font color='red'>移植</font>到Keil5编译通过
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved