1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > usb升级linux固件 Linux USB驱动(4)---CY68013固件加载驱动

usb升级linux固件 Linux USB驱动(4)---CY68013固件加载驱动

时间:2018-08-23 16:27:42

相关推荐

usb升级linux固件 Linux USB驱动(4)---CY68013固件加载驱动

CY68013的固件可以保存在主机上,当其被USB总线识别出来之后,可以通过驱动程序动态的加载USB固件,Linux内核中已经提供了完善的机制来加载设备的固件。

将需要加载的固件存放到/lib/firmware文件夹中,然后调用request_firmware函数,其中name为固件的名称(不需要路径)当固件成功加载到内核中会保存在struct firmware结构体中,size是固件的大小,data是固件中的内容(注意:固件内容是否正确以及固件如何解析需要在内核中完成)。当固件发送到设备之后,就可以调用release_firmware函数释放固件。

struct firmware {

size_t size;

u8 *data;

};

固件加载函数:

int request_firmware(const struct firmware **fw, char*name, struct device *device);

固件释放函数:

void release_firmware(struct firmware *fw);

当调用request_firmware函数成功获取CY68013的固件之后,在内核中需要对固件进行验证,检查加载到内核中的时候是有效的固件,然后将固件下载到USB设备中。

根据CY68013技术手册TRM上的说明下载固件到USB设备中需要按一下的步骤操作: 首先通过控制端点EP0,发送控制消息使8051核进入复位状态(CPUCS = 1);

然后根据HEX文件中的记录,通过EP0端点发送的控制消息下载数据到指定的地址;

待所有的HEX数据都下载完毕,再使8051恢复运行状态(CPUCS = 0);

如果新下载的固件中设置了USBCS中的RENUM位,则在8051核恢复运行状态之后会模拟USB设备断开与主机的连接,然后在连接主机重新进行设备的枚举。这时新下载的固件需要处理设备枚举中主机的各种请求。

按照CY68013 TRM上的说明,下载固件需要使用一下的请求:

则在USB的设备驱动中,需要通过USB core提供的API 进行操作,API的原型如下:

104 /**

105 * usb_control_msg - Builds a control urb, sends it off and waits for completion

106 * @dev: pointer to the usb device to send the message to

107 * @pipe: endpoint "pipe" to send the message to

108 * @request: USB message request value

109 * @requesttype: USB message request type value

110 * @value: USB message value

111 * @index: USB message index value

112 * @data: pointer to the data to send

113 * @size: length in bytes of the data to send

114 * @timeout: time in msecs to wait for the message to complete before timing

115 * out (if 0 the wait is forever)

116 *

117 * Context: !in_interrupt ()

118 *

119 * This function sends a simple control message to a specified endpoint and

120 * waits for the message to complete, or timeout.

121 *

122 * If successful, it returns the number of bytes transferred, otherwise a

123 * negative error number.

124 *

125 * Don't use this function from within an interrupt context, like a bottom half

126 * handler. If you need an asynchronous message, or need to send a message

127 * from within interrupt context, use usb_submit_urb().

128 * If a thread in your driver uses this call, make sure your disconnect()

129 * method can wait for it to complete. Since you don't have a handle on the

130 * URB used, you can't cancel the request.

131 */

132 int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,

133 __u8 requesttype, __u16 value, __u16 index, void *data,

134 __u16 size, int timeout)

usb_control_msg参数中的pipe必须通过usb_sndctrlpipe函数进行处理之后才能使用,request对应表3-8中的bRequest, requesttype对应表3-8中的bmRequest, value则是要下载到USB设备RAM中的起始地址(例如CPUCS寄存器的地址为0XE600),index按照表的说明始终为0, data则是要下载的数据,而size指明数据的大小,timeout则指明超时的时间,通常以HZ为参考处理。

一下是驱动程序中的相关代码,将usb_control_msg封装为3个函数,分别用来完成固件下载的3个步骤:

3 #define CY68013_VENDOR_REQ 0xa0 /* Cypress vendor bRequest */

4 #define CY68013_REQ_T_OUT 0x40 /* Cypress firmware download bmRequest */

5 #define CY68013_REG_CPUCS 0xE600 /* CY68013 CPUCS register address it control 8051 core reset and out of reset */

6 #define CY68013_RUN_CMD 0x00 /* Write this value to cy68013 CPUCS registermake 8051 core run */

7 #define CY68013_RESET_CMD 0x01 /* Write this value to cy68013 CPUCS register mak e 8051 core reset */

35 /* Make CY68013 out of reset */

36 static int cy68013_run(struct kref *kref)

37 {

38 unsigned char run = CY68013_RUN_CMD;

39

40 /* Write 0x0(run) to CPUCS bit0 make cy68013 out of reset */

41 return cy68013_control_msg(kref, CY68013_REG_CPUCS, (void *)&run, sizeof(run));

42 }

43

44 /* Make CY68013 into reset */

45 static int cy68013_reset(struct kref *kref)

46 {

47 unsigned char reset = CY68013_RESET_CMD;

48

49 /* Write 0x1 to CPUCS bit0 make cy68013 into reset*/

50 return cy68013_control_msg(kref, CY68013_REG_CPUCS, (void *)&reset, sizeof(reset));

51 }579 /* Download data specify data to cy68013, data size speicied by size, download address specify by addr */

580 static int cy68013_control_msg(struct kref *kref, __u16 addr, void *data, __u16 size)

581 {

582 int retval = 0;

583

584 /* According usb_device pointer get struct usb_cy68013 data structure pointer */

585 struct usb_cy68013 *cyusb = to_cy68013_dev(kref);

586

587 /* Make sure only once can send contol message to device */

588 mutex_lock(&cyusb->io_mutex);

589

590 /* Check current usb is connect to bus */

591 if (!cyusb->interface){

592 mutex_unlock(&cyusb->io_mutex);

593 return -ENODEV;

594 }

595

596 /* Send control message to cy68013 */

597 retval = usb_control_msg(cyusb->udev, usb_sndctrlpipe(cyusb->udev, 0), CY68013_VENDOR_REQ, CY68013_REQ_T_OUT, addr, 0, data, size, HZ);

598

599 mutex_unlock(&cyusb->io_mutex);

600

601 return retval < 0 ? retval : 0;

602 }

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。