当前位置:首页 > 芯闻号 > 充电吧
[导读]一、框架分析: 我们先来分析一下核心层的代码fbmem.c: ① 入口函数fbmem_init: fbmem_init(void) { create_proc_r

一、框架分析:

我们先来分析一下核心层的代码fbmem.c: ① 入口函数fbmem_init:
fbmem_init(void)  
{  
    create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);  

    if (register_chrdev(FB_MAJOR,"fb",&fb_fops))  
        printk("unable to get major %d for fb devsn", FB_MAJOR);  

    fb_class = class_create(THIS_MODULE, "graphics");  
    if (IS_ERR(fb_class)) {  
        printk(KERN_WARNING "Unable to create fb class; errno = %ldn", PTR_ERR(fb_class));  
        fb_class = NULL;  
    }  
    return 0;  
}  

fbmem_init里面注册字符设备fb,其主设备号为29.并且创建了类class_create,注意在此没有创建设备节点

② file_operations fb_fops
static const struct file_operations fb_fops = {
    .owner =    THIS_MODULE,
    .read =     fb_read,
    .write =    fb_write,
    .ioctl =    fb_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl = fb_compat_ioctl,
#endif
    .mmap =     fb_mmap,
    .open =     fb_open,
    .release =  fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
    .get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
    .fsync =    fb_deferred_io_fsync,
#endif
};

Ⅰ、 我们假设 app: open(“/dev/fb0”, …) 主设备号: 29, 次设备号: 0 //应用程序打开 /dev/fb0,主设备号29 次设备号0;那么就会调用内核中的 fb_open:

fb_open(struct inode *inode, struct file *file)
{
 int fbidx = iminor(inode);     // 得到次设备号 0 
 struct fb_info *info = registered_fb[fbidx(0)];         //fb_info 这个结构体等于registered_fb数组里面的次设备号检索出来。
}

Ⅱ、 我们假设 app: read() //应用程序read的时候;那么就会调用内核中的 fb_read:

fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
            int fbidx = iminor(inode);//得到次设备号0
            struct fb_info *info = registered_fb[fbidx];//在registered_fb数组里得到一个fb_info 结构体
}

由I、Ⅱ可知open read都依赖fb_info结构体,从registered_fb数组中得到fb_info结构体。
也就是说内核中主设备号为29的设备可能有很多,open的时候根据次设备号从registered_fb数组得到一个fb_info。
registered_fb数组在register_framebuffer被设置

register_framebuffer(struct fb_info*fb_info)
{
    fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), "fb%d", i); //创建设备节点
       registered_fb[i]= fb_info;
}
小结:到此已经可以很清晰看出LCD的框架。

首先内核帮助我们实现了一个主设备号为29的设备,此时只创建了类,并没有在类下创建设备节点。
当我们的下层硬件驱动调用注册函数的时候,会初始化registered_fb结构体,并创建设备节点。
此时应用程序可以来打开一个设备节点了,比如open(“/dev/fb0”, …),最终会调用到fbmem核心层提供的open函数,这个open函数中根据次设备号,registered_fb数组中取出硬件注册进来的结构体,调用里面的open函数,或者使用一些属性。这样内核可以方便管理类似的设备了。

③ fbmem.c系统实现并抽象出来的,使用的时候依赖于底层框架实现,那么我们来写底层框架实现函数xxxfb.c

上层fbmem.c内核已经写好,并完成上层驱动注册。我们要做的是写出硬件部分的函数,来初始化registered_fb:
1. 分配一个fb_info结构体: 怎么分配:framebuffer_alloc
2. 设置fb_info里面的相关参数
3. 注册:register_framebuffer
4. 硬件相关的设置

来列举一下写底层框架函数将用到的结构体: fb_info 结构体:
struct fb_info {  
    int node;/*  序号索引值,/dev/fb0,/dev/fb1  其中0,1 就是从这里获得的*/  
    int flags;  
    struct fb_var_screeninfo var;   /* Current var  可变参数,很重要 */  
    struct fb_fix_screeninfo fix;   /* Current fix  固定参数,很重要 */  
    struct fb_monspecs monspecs;    /* Current Monitor specs */  
    struct work_struct queue;   /* Framebuffer event queue */  
    struct fb_pixmap pixmap;    /* Image hardware mapper */  
    struct fb_pixmap sprite;    /* Cursor hardware mapper */  
    struct fb_cmap cmap;        /* Current cmap */  
    struct list_head modelist;      /* mode list */  
    struct fb_videomode *mode;  /* current mode */  

#ifdef CONFIG_FB_BACKLIGHT  
    /* assigned backlight device */  
    /* set before framebuffer registration,  
       remove after unregister */  
    struct backlight_device *bl_dev;  
    /* Backlight level curve */  
    struct mutex bl_curve_mutex;      
    u8 bl_curve[FB_BACKLIGHT_LEVELS];  
#endif  
#ifdef CONFIG_FB_DEFERRED_IO  
    struct delayed_work deferred_work;  
    struct fb_deferred_io *fbdefio;  
#endif  
    struct fb_ops *fbops;/* fb_ops,各种帧缓冲操作函数,很重要 */  
    struct device *device;      /* This is the parent */  
    struct device *dev;     /* This is this fb device */  
    int class_flag;                    /* private sysfs flags */  
#ifdef CONFIG_FB_TILEBLITTING  
    struct fb_tile_ops *tileops;    /* Tile Blitting */  
#endif  
    char __iomem *screen_base;  /* Virtual address  "显存“的基地址 */  
    unsigned long screen_size;  /* Amount of ioremapped VRAM or 0 ”显存“的大小,重要 */   
    void *pseudo_palette;       /* Fake palette of 16 colors */ /* 16位假的调色板,重要 */   
#define FBINFO_STATE_RUNNING    0  
#define FBINFO_STATE_SUSPENDED  1  
    u32 state;          /* Hardware state i.e suspend */  
    void *fbcon_par;                /* fbcon use-only private area */  
    /* From here on everything is device dependent */  
    void *par;   /* 这个用来存放私有数据 */  
};  

将用到下面6个内容:
struct fb_var_screeninfo var; /* Current var 可变参数,很重要 */
struct fb_fix_screeninfo fix; /* Current fix 固定参数,很重要 */
struct fb_ops fbops;/ fb_ops,各种帧缓冲操作函数,很重要 */
char __iomem screen_base; / Virtual address “显存“的基地址 */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 ”显存“的大小,重要 */
void pseudo_palette; / Fake palette of 16 colors / / 16位假的调色板,重要 */

Ⅰ、 fb_var_screeninfo 结构体:
struct fb_var_screeninfo {  
    __u32 xres;         /* visible resolution       */  
    __u32 yres;  
    __u32 xres_virtual;     /* virtual resolution       */  
    __u32 yres_virtual;  
    __u32 xoffset;          /* offset from virtual to visible */  
    __u32 yoffset;          /* resolution           */  

    __u32 bits_per_pixel;       /* guess what           */  
    __u32 grayscale;        /* != 0 Graylevels instead of colors */  

    struct fb_bitfield red;     /* bitfield in fb mem if true color, */  
    struct fb_bitfield green;   /* else only length is significant */  
    struct fb_bitfield blue;  
    struct fb_bitfield transp;  /* transparency         */    

    __u32 nonstd;           /* != 0 Non standard pixel format */  

    __u32 activate;         /* see FB_ACTIVATE_*        */  

    __u32 height;           /* height of picture in mm    */  
    __u32 width;            /* width of picture in mm     */  

    __u32 accel_flags;      /* (OBSOLETE) see fb_info.flags */  

    /* Timing: All values in pixclocks, except pixclock (of course) */  
    __u32 pixclock;         /* pixel clock in ps (pico seconds) */  
    __u32 left_margin;      /* time from sync to picture    */  
    __u32 right_margin;     /* time from picture to sync    */  
    __u32 upper_margin;     /* time from sync to picture    */  
    __u32 lower_margin;  
    __u32 hsync_len;        /* length of horizontal sync    */  
    __u32 vsync_len;        /* length of vertical sync  */  
    __u32 sync;         /* see FB_SYNC_*        */  
    __u32 vmode;            /* see FB_VMODE_*       */  
    __u32 rotate;           /* angle we rotate counter clockwise */  
    __u32 reserved[5];      /* Reserved for future compatibility */  
};  
Ⅱ、fb_fix_screeninfo fix结构体:
struct fb_fix_screeninfo {  
    char id[16];            /* identification string eg "TT Builtin" */  
    unsigned long smem_start;   /* Start of frame buffer mem */  
                    /* (physical address) */  
    __u32 smem_len;         /* Length of frame buffer mem */  
    __u32 type;         /* see FB_TYPE_*        */  
    __u32 type_aux;         /* Interleave for interleaved Planes */  
    __u32 visual;           /* see FB_VISUAL_*      */   
    __u16 xpanstep;         /* zero if no hardware panning  */  
    __u16 ypanstep;         /* zero if no hardware panning  */  
    __u16 ywrapstep;        /* zero if no hardware ywrap    */  
    __u32 line_length;      /* length of a line in bytes    */  
    unsigned long mmio_start;   /* Start of Memory Mapped I/O   */  
                    /* (physical address) */  
    __u32 mmio_len;         /* Length of Memory Mapped I/O  */  
    __u32 accel;            /* Indicate to driver which */  
                    /*  specific chip/card we have  */  
    __u16 reserved[3];      /* Reserved for future compatibility */  
};
Ⅲ、fb_ops 结构体:
struct fb_ops {
    struct module *owner;
    /* 打开/释放 */
    int (*fb_open)(struct fb_info *info, int user);
    int (*fb_release)(struct fb_info *info, int user);

/* 对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要 */
    ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
               size_t count, loff_t *ppos);
    ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
                size_t count, loff_t *ppos);

    /* 检测可变参数,并调整到支持的值*/
    int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);

    /* 根据 info->var 设置 video 模式 */
    int (*fb_set_par)(struct fb_info *info);

    /* 设置 color 寄存器 */
    int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
                unsigned blue, unsigned transp, struct fb_info *info);

    /* 批量设置 color 寄存器,设置颜色表 */
    int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);

    /*显示空白 */
    int (*fb_blank)(int blank, struct fb_info *info);

    /* pan 显示 */
    int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);

    /* 矩形填充 */
    void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
    /* 数据复制 */
    void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
    /* 图形填充 */
    void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);

    /* 绘制光标 */
    int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);

    /* 旋转显示 */
    void (*fb_rotate)(struct fb_info *info, int angle);

    /* 等待 blit 空闲 (可选) */
    int (*fb_sync)(struct fb_info *info);

    /* fb 特定的 ioctl (可选) */
    int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
            unsigned long arg);

    /* 处理 32 位的 compat ioctl (可选) */
    int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
            unsigned long arg);

     /* fb 特定的 mmap */
    int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);

    /* 保存目前的硬件状态 */
    void (*fb_save_state)(struct fb_info *info);

    /* 恢复被保存的硬件状态 */
    void (*fb_restore_state)(struct fb_info *info);

    /* get capability given var */
    void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
                struct fb_var_screeninfo *var);
};
二、代码:

底层驱动lcd.c:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 设置lcd的控制寄存器
struct lcd_regs {  
    unsigned long   lcdcon1;  
    unsigned long   lcdcon2;  
    unsigned long   lcdcon3;  
    unsigned long   lcdcon4;  
    unsigned long   lcdcon5;  
    unsigned long   lcdsaddr1;  
    unsigned long   lcdsaddr2;  
    unsigned long   lcdsaddr3;  
    unsigned long   redlut;  
    unsigned long   greenlut;  
    unsigned long   bluelut;  
    unsigned long   reserved[9];  
    unsigned long   dithmode;  
    unsigned long   tpal;  
    unsigned long   lcdintpnd;  
    unsigned long   lcdsrcpnd;  
    unsigned long   lcdintmsk;  
    unsigned long   lpcsel;  
};  

//设置fb_ops 结构体
static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
                 unsigned int green, unsigned int blue,
                 unsigned int transp, struct fb_info *info);
static struct fb_ops s3c_lcdfb_ops = {
    .owner      = THIS_MODULE,
    .fb_setcolreg   = s3c_lcdfb_setcolreg, // 设置 color 寄存器
    .fb_fillrect    = cfb_fillrect,        // 矩形填充
    .fb_copyarea    = cfb_copyarea,        // 数据复制
    .fb_imageblit   = cfb_imageblit,       // 图形填充
};

/* 定义LCD的操作寄存器 */
static volatile unsigned long *GPBCON;
static volatile unsigned long *GPBDAT;
static volatile unsigned long *GPCCON;
static volatile unsigned long *GPDCON;
static volatile unsigned long *GPGCON;
static volatile struct lcd_regs *lcd_regs;

//定义fb_info结构体
static struct fb_info *s3c_lcd;
static u32 pseudo_palette[16];

/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
    chan &= 0xffff;
    chan >>= 16 - bf->length;
    return chan << bf->offset;
}


static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
                 unsigned int green, unsigned int blue,
                 unsigned int transp, struct fb_info *info)
{
    unsigned int val;

    if (regno > 16)
        return 1;

    /* 用red,green,blue三原色构造出val */
    val  = chan_to_field(red,   &info->var.red);
    val |= chan_to_field(green, &info->var.green);
    val |= chan_to_field(blue,  &info->var.blue);

    //((u32 *)(info->pseudo_palette))[regno] = val;
    pseudo_palette[regno] = val;
    return 0;
}




static int lcd_init(void)
{   
    /* 1.分配一个fb_info */
    s3c_lcd = framebuffer_alloc(0,NULL);

    /* 2.设置 */
    /* 2.1 设置固定参数fix */
    strcpy(s3c_lcd->fix.id,"czg_led");
    s3c_lcd->fix.smem_len = 480*272*16/8;
    s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;
    s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR;/* TFT */
    s3c_lcd->fix.line_length = 480*2;

    /* 2.2 设置可变参数var */
    s3c_lcd->var.xres           = 480;
    s3c_lcd->var.yres           = 272;
    s3c_lcd->var.xres_virtual   = 480;
    s3c_lcd->var.yres_virtual   = 272;
    s3c_lcd->var.bits_per_pixel = 16;

    /* RGB:565 */
    s3c_lcd->var.red.offset   = 11;
    s3c_lcd->var.red.length   = 5;
    s3c_lcd->var.green.offset = 5;
    s3c_lcd->var.green.length = 6;
    s3c_lcd->var.blue.offset  = 0;
    s3c_lcd->var.blue.length  = 5;

    s3c_lcd->var.activate     = FB_ACTIVATE_NOW;



    /* 2.3 设置帧缓冲操作函数fobps */
    s3c_lcd->fbops = &s3c_lcdfb_ops;

    /* 2.4 设置“显存“的基地址 */
    //s3c_lcd->screen_base; /* 显存的虚拟地址 */ //在3.3设置

    /* 2.5 设置”显存“的大小 */
    s3c_lcd->screen_size = 480*272*16/8;    /* 显存的大小 */ 

    /* 2.6 设置6位伪调色板  */
    s3c_lcd->pseudo_palette = pseudo_palette;


    /* 3.硬件相关的操作 */
    /* 3.1 配置GPIO用于LCD */
    GPBCON = ioremap(0x56000010,8);
    GPBDAT = GPBCON + 1;
    GPCCON = ioremap(0x56000020,4);
    GPDCON = ioremap(0x56000030,4);
    GPGCON = ioremap(0x56000060,4);

    *GPCCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND 
    *GPDCON  = 0xaaaaaaaa;  // GPIO管脚用于VD[23:8]

    *GPBCON &= ~(3<<0);// KEYBOARD output pin
    *GPBCON |= 1;
    *GPBDAT &= ~(1<<0);            // KEYBOARD off

    *GPGCON |=  (3<<(2*4));


    /* 3.2 根据LCD手册设置LCD控制器,比如VCLK的频率等等 */
    lcd_regs = ioremap(0X4D000000,sizeof(struct lcd_regs));

    /* bit[17:8] : TFT: VCLK = HCLK / [(CLKVAL+1) x 2] ( CLKVAL >= 0 ) */
    /*             HCLK通过dmesg命令查看为100MHZ*/
    /*             VCLK在LCD芯片手册P11页中取典型值9MHZ     */
    /*            CLKVAL = 100/9/2 -1 = 4.5 = 4 */
    /* bit[6:5] = 0b11  TFT LCD panel */
    /* bit[4:1] = 0b1100    16 bpp for TFT */
    /* bit[0]   = 0 Disable the video output and the LCD control signal */
    lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0c<<1);

    /* 垂直方向时间参数 */
    /* bit[31:24] : LCD芯片手册P11页和2440数据手册时序图对比 */
    /*              VBPD = tvb - 1 = 2-1 = 1  */
    /* bit[23:14] : LINEVAL = tvd - 1 = 272-1 = 271 */
    /* bit[13:6]  : VFPD = tvf - 1 = 2-1 = 1  */
    /* bit[5:0]   : VSPW = tvp - 1 = 10-1 = 9*/
    lcd_regs->lcdcon2 = (1<<24) | (271<<14) | (1<<6)| (9<<0);

    /* 水平方向时间参数 */
    /* bit[[25:19] : LCD芯片手册P11页和2440数据手册时序图对比 */
    /*               HBPD (TFT) = thb - 1 = 2-1 = 1  */
    /* bit[18:8]   : HOZVAL = thd - 1 = 480-1 = 479 */
    /* bit[7:0]    : HFPD (TFT) = thf - 1 = 2-1 = 1  */
    lcd_regs->lcdcon3 = (1<<19) | (479<<8) | (1<<0);

    /* 水平方向的同步信号 */
    /* bit[7:0]    : HSPW(TFT) = thp - 1 = 41-1 = 40  */
    lcd_regs->lcdcon4 = (40<<0);

    /* bit[11]    : FRM565 = 1      5:6:5 Format */
    /* bit[10]     : INVVCLK = 0 The video data is fetched at VCLK falling edge  */
    /* bit[9]     : INVVLINE  = 1 Inverted VLINE/HSYNC 低电平有效 */
    /* bit[8]      : INVVFRAME = 1 Inverted VFRAME/VSYNC 低电平有效 */
    /* bit[7]      : INVVD = 0  Normal VD (video data) */
    /* bit[6]      : INVVDEN = 0  normal VDEN数据信号 高电平有效不需要反转 */
    /* bit[5]      : INVPWREN = 0  normal PWREN 电源信号 高电平有效不需要反转 */
    /* bit[3]      : LCD_PWREN output = 0  Disable PWREN signal 设置完再使能 */
    /* bit[1:0]    : BSWP-HWSWP:0b01 = 0x01,数据手册P413 像素排列P1-P2-P3-P4 */

    lcd_regs->lcdcon5 = (1<<11) | (1<<9) | (1<<8) | (1<<0);


    /* 3.3 分配显存(framebuffer),并把地址告诉L CD控制器 */
    //s3c_lcd->fix.smem_start /* 显存的物理地址 */
    s3c_lcd->screen_base = dma_alloc_writecombine(NULL,s3c_lcd->fix.smem_len,(u32 *)&s3c_lcd->fix.smem_start,GFP_KERNEL);
    lcd_regs->lcdsaddr1 = (s3c_lcd->fix.smem_start >> 1) & ~(3<<30);
    lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & (0x1fffff);
    lcd_regs->lcdsaddr3 = (480*16/16);

    /* 3.4 启动LCD */
    *GPBDAT |= (1<<0);  /* 输出高电平,使能背光 */
    lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */
    lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD本身电源 */

    /* 4.注册 */
    register_framebuffer(s3c_lcd);
    return 0;
}

static void lcd_exit(void)
{
    iounmap(lcd_regs);
    iounmap(GPBCON);
    iounmap(GPCCON);
    iounmap(GPDCON);
    iounmap(GPGCON);
    *GPBDAT &= ~(1<<0);    /* 输出低电平,关闭背光 */
    lcd_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD控制器 */
    lcd_regs->lcdcon5 &= ~(1<<3); /* 关闭LCD本身电源 */
    framebuffer_release(s3c_lcd); // 释放fb_info
    dma_free_writecombine(NULL,s3c_lcd->fix.smem_len,s3c_lcd->screen_base,s3c_lcd->fix.smem_start); // 释放显存
    unregister_framebuffer(s3c_lcd); // 卸载
}

module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");

Makefile:

KERN_DIR = /work/system/linux-2.6.22.6

all:
    make -C $(KERN_DIR) M=`pwd` modules 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m += lcd.o
三、编译测试: ① 需要重新编译内核, make menuconfig去掉原来的驱动程序 -> Device Drivers   -> Graphics support      S3C2410 LCD framebuffer support

② make uImage 使用新的内核启动开发板
cp arch/arm/boot/uImage /work/nfs_root/czg/uImage_nolcd
nfs 30000000 192.168.2.3:/work/nfs_root/czg/uImage_nolcd
bootm 30000000


③ 加载三个附加模块,make modules
cp drivers/video/cfb*.ko /work/nfs_root/czg
insmod cfbcopyarea.ko 
insmod cfbfillrect.ko 
insmod cfbimgblt.ko 
insmod lcd.ko

④ 测试: 第一种方式:
ls /dev/fb*
echo hello_czg > /dev/tty1   //显示屏上显示
cat lcd.ko > /dev/fb0
第二种方式:
① echo tty1::askfirst:-/bin/sh >> /etc/inittab
② 用新内核重启开发板-重复上面②
③  insmod cfbcopyarea.ko 
    insmod cfbfillrect.ko 
    insmod cfbimgblt.ko 
    insmod lcd.ko
    insmod buttons_drv.ko
④ 通过按键在LCD显示屏上看到ls指令

buttons_drv.ko模块点我跳转

⑤ 查看进程
ps
ls /proc/*/fd -l



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

SAP(思爱普)近日发出的裁员计划,不仅涉及全球范围内约8000个职位,更是在中国区造成了近1500名正式员工和合同工不续的情况。

关键字: 软件 互联网

业内消息,近日Alphabet旗下谷歌公司发言人表示为控制成本正在进行最新裁员,但具体人数不详。该发言人表示,裁员并非全公司范围,受影响的员工将能够申请内部职位,但没有具体说明受影响的员工人数或涉及的团队。

关键字: 谷歌 裁员

几天前,以南印度组织零售商协会(ORA)为代表的20多家零售连锁店和4300家商店宣布将从5月1日起停止销售一加设备。4月17日,全印度移动零售商协会(AIMRA)代表印度15万多家线下智能手机零售商通知一加,其成员正在...

关键字: 印度 一加 小米 Poco

业内消息,近日光刻机制造商阿斯麦(ASML)公布了2024年第一季度业绩,财报显示,该公司当季总净销售额53亿欧元,环比下降27%;毛利率51.0%,上季度为51.4%;净利润12亿欧元(当前约92.4亿元人民币),环比...

关键字: 光刻机 ASML

近日有韩媒称,由于薪资谈判破裂,劳资双方未能缩小对涨薪的意见分歧,三星电子全国工会(NSEU)即日起将发起公司成立以来首次集体行动,工会当天在华城市(Hwaseong)京畿道华城园区的组件研究大楼(DSR)前举行文化活动...

关键字: 三星

昨天上午,华为终端官微宣布全新重磅新机开售,约一分钟线上即告售罄,线下门店排起长队,气势丝毫不输苹果,和 Mate 60 Pro 一样没有发布会,这次官方同样推出了 “HUAWEI Pura 70 系列 先锋计划”,可以...

关键字: 麒麟芯片 华为

上海2024年4月16日 /美通社/ -- 4月14日,为期四天的第89届中国国际医疗器械博览会(CMEF)盛大收官。澳鹏Appen很荣幸再次作为唯一的人工智能训练数据参展商参与此次"航母级"规模医疗...

关键字: APP 医疗器械 PEN 模型

基于大语言模型研发的品牌定制化AI客服解决方案,获得业界高度认可 上海2024年4月16日 /美通社/ -- transcosmos集团(中文名:大宇宙集团;以下简称:transcosmos)于2024年4月11日在C...

关键字: TRANS TI COSMOS AI

针对光伏优化器(MPPT)的非隔离DC-DC升压电路,推荐瑞森半导体低压MOS-SGT系列。极低导通电阻,低损耗,高雪崩耐量,高效率,非常适合高频应用。

关键字: 光伏优化器 MPPT

IDC近日发布的全球智能手机市场初步数据显示,苹果iPhone全球销量在今年一季度的销量下降了9.6%。

关键字: iPhone 苹果 端侧AI
关闭
关闭