Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
K210
SPI
60
RTT下K210两路SPI不能同时使用问题,求大神
发布于 2021-02-08 15:16:49 浏览:1224
订阅该版
首先作为RTT的热衷粉丝来讲,真的感谢论坛的支持以及各位开发者老师的支持。**这个问题卡我好几天了,**是在是没有办法解决了,望请大佬帮我解决下。 问题详情: 硬件是sipeed的开发板,问题是这样的,K210开放出来两路独立的SPI,分别是0路和1路,0路spi接的屏幕,1路spi接的rw007,我单独控制其原件是没问题的。但是两者同时使用就发现有问题,问题是rw007 通信没响应还有lcd屏幕无法控制(例如clear color),LCD的驱动是直接裸跑的用的官方的驱动,rw007是用的bsp底下的drv_spi,同样的把rw007换成sd卡还是同样的效果,lcd无法控制。 ```c /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-03-18 ZYH first version */ #include
#include
#ifdef RT_USING_SPI #include "drv_spi.h" #include
#include
#include
#include
#include
#include
#include "utils.h" #define DRV_SPI_DEVICE(spi_bus) (struct drv_spi_bus *)(spi_bus) #define MAX_CLOCK (40000000UL) struct drv_spi_bus { struct rt_spi_bus parent; spi_device_num_t spi_instance; dmac_channel_number_t dma_send_channel; dmac_channel_number_t dma_recv_channel; }; struct drv_cs { int cs_index; int cs_pin; }; static volatile spi_t *const spi_instance[4] = { (volatile spi_t *)SPI0_BASE_ADDR, (volatile spi_t *)SPI1_BASE_ADDR, (volatile spi_t *)SPI_SLAVE_BASE_ADDR, (volatile spi_t *)SPI3_BASE_ADDR }; static rt_err_t drv_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration) { rt_err_t ret = RT_EOK; int freq = 0; struct drv_spi_bus *bus = DRV_SPI_DEVICE(device->bus); struct drv_cs * cs = (struct drv_cs *)device->parent.user_data; RT_ASSERT(bus != RT_NULL); gpiohs_set_drive_mode(cs->cs_pin, GPIO_DM_OUTPUT); gpiohs_set_pin(cs->cs_pin, GPIO_PV_HIGH); #ifdef BSP_USING_SPI1_AS_QSPI /* Todo:QSPI*/ #else spi_init(bus->spi_instance, configuration->mode & RT_SPI_MODE_3, SPI_FF_STANDARD, configuration->data_width, 0); #endif freq = spi_set_clk_rate(bus->spi_instance, configuration->max_hz > MAX_CLOCK ? MAX_CLOCK : configuration->max_hz); rt_kprintf("\nset spi freq %d\n", freq); return ret; } void __spi_set_tmod(uint8_t spi_num, uint32_t tmod) { RT_ASSERT(spi_num < SPI_DEVICE_MAX); volatile spi_t *spi_handle = spi[spi_num]; uint8_t tmod_offset = 0; switch(spi_num) { case 0: case 1: case 2: tmod_offset = 8; break; case 3: default: tmod_offset = 10; break; } set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset); } static rt_uint32_t drv_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) { struct drv_spi_bus *bus = DRV_SPI_DEVICE(device->bus); struct drv_cs * cs = (struct drv_cs *)device->parent.user_data; struct rt_spi_configuration *cfg = &device->config; uint32_t * tx_buff = RT_NULL; uint32_t * rx_buff = RT_NULL; int i; rt_ubase_t dummy = 0xFFFFFFFFU; __spi_set_tmod(bus->spi_instance, SPI_TMOD_TRANS_RECV); RT_ASSERT(bus != RT_NULL); if(message->cs_take) { gpiohs_set_pin(cs->cs_pin, GPIO_PV_LOW); } if(message->length) { spi_instance[bus->spi_instance]->dmacr = 0x3; spi_instance[bus->spi_instance]->ssienr = 0x01; sysctl_dma_select(bus->dma_send_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + bus->spi_instance * 2); sysctl_dma_select(bus->dma_recv_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + bus->spi_instance * 2); if(!message->recv_buf) { dmac_set_single_mode(bus->dma_recv_channel, (void *)(&spi_instance[bus->spi_instance]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, message->length); } else { rx_buff = rt_calloc(message->length * 4, 1); if(!rx_buff) { goto transfer_done; } dmac_set_single_mode(bus->dma_recv_channel, (void *)(&spi_instance[bus->spi_instance]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, message->length); } if(!message->send_buf) { dmac_set_single_mode(bus->dma_send_channel, &dummy, (void *)(&spi_instance[bus->spi_instance]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE, DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, message->length); } else { tx_buff = rt_malloc(message->length * 4); if(!tx_buff) { goto transfer_done; } for(i = 0; i < message->length; i++) { tx_buff[i] = ((uint8_t *)message->send_buf)[i]; } dmac_set_single_mode(bus->dma_send_channel, tx_buff, (void *)(&spi_instance[bus->spi_instance]->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE, DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, message->length); } spi_instance[bus->spi_instance]->ser = 1U << cs->cs_index; dmac_wait_done(bus->dma_send_channel); dmac_wait_done(bus->dma_recv_channel); spi_instance[bus->spi_instance]->ser = 0x00; spi_instance[bus->spi_instance]->ssienr = 0x00; if(message->recv_buf) { for(i = 0; i < message->length; i++) { ((uint8_t *)message->recv_buf)[i] = (uint8_t)rx_buff[i]; } } transfer_done: if(tx_buff) { rt_free(tx_buff); } if(rx_buff) { rt_free(rx_buff); } } if(message->cs_release) { gpiohs_set_pin(cs->cs_pin, GPIO_PV_HIGH); } return message->length; } const static struct rt_spi_ops drv_spi_ops = { drv_spi_configure, drv_spi_xfer }; int rt_hw_spi_init(void) { rt_err_t ret = RT_EOK; #ifdef BSP_USING_SPI1 { static struct drv_spi_bus spi_bus1; spi_bus1.spi_instance = SPI_DEVICE_1; spi_bus1.dma_send_channel = DMAC_CHANNEL1; spi_bus1.dma_recv_channel = DMAC_CHANNEL2; ret = rt_spi_bus_register(&spi_bus1.parent, "spi1", &drv_spi_ops); #ifdef BSP_SPI1_USING_SS0 { static struct rt_spi_device spi_device10; static struct drv_cs cs10 = { .cs_index = SPI_CHIP_SELECT_0, .cs_pin = SPI1_CS0_PIN }; rt_spi_bus_attach_device(&spi_device10, "spi10", "spi1", (void *)&cs10); } #endif #ifdef BSP_SPI1_USING_SS1 { static struct rt_spi_device spi_device11; static struct drv_cs cs11 = { .cs_index = SPI_CHIP_SELECT_1, .cs_pin = SPI1_CS1_PIN }; rt_spi_bus_attach_device(&spi_device11, "spi11", "spi1", (void *)&cs11); } #endif #ifdef BSP_SPI1_USING_SS2 { static struct rt_spi_device spi_device12; static struct drv_cs cs12 = { .cs_index = SPI_CHIP_SELECT_2, .cs_pin = SPI1_CS2_PIN }; rt_spi_bus_attach_device(&spi_device12, "spi12", "spi1", (void *)&cs12); } #endif #ifdef BSP_SPI1_USING_SS3 { static struct rt_spi_device spi_device13; static struct drv_cs cs13 = { .cs_index = SPI_CHIP_SELECT_2, .cs_pin = SPI1_CS2_PIN }; rt_spi_bus_attach_device(&spi_device13, "spi13", "spi1", (void *)&cs13); } #endif } #endif return ret; } INIT_DEVICE_EXPORT(rt_hw_spi_init); #endif ``` ```c /* Copyright 2018 Canaan Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include
#ifdef BSP_USING_LCD #include
#include
#include
#include
#include
#include
#define DBG_TAG "LCD" #define DBG_LVL DBG_LOG #include
static lcd_ctl_t lcd_ctl; static void init_dcx(void) { gpiohs_set_drive_mode(DCX_GPIONUM, GPIO_DM_OUTPUT); gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_HIGH); } static void set_dcx_control(void) { gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_LOW); } static void set_dcx_data(void) { gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_HIGH); } static void init_rst(void) { gpiohs_set_drive_mode(RST_GPIONUM, GPIO_DM_OUTPUT); gpiohs_set_pin(RST_GPIONUM, GPIO_PV_LOW); usleep(100000); gpiohs_set_pin(RST_GPIONUM, GPIO_PV_HIGH); usleep(100000); } void tft_hard_init(void) { init_dcx(); spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); init_rst(); spi_set_clk_rate(SPI_CHANNEL, 20000000); } void tft_write_command(uint8_t cmd) { set_dcx_control(); spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); spi_init_non_standard(SPI_CHANNEL, 8/*instrction length*/, 0/*address length*/, 0/*wait cycles*/, SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT, (uint8_t *)(&cmd), 1,SPI_TRANS_CHAR); } void tft_write_byte(uint8_t *data_buf, uint32_t length) { set_dcx_data(); spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); spi_init_non_standard(SPI_CHANNEL, 8/*instrction length*/, 0/*address length*/, 0/*wait cycles*/, SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT, data_buf, length, SPI_TRANS_CHAR); } void tft_write_half(uint16_t *data_buf, uint32_t length) { set_dcx_data(); spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0); spi_init_non_standard(SPI_CHANNEL, 16/*instrction length*/, 0/*address length*/, 0/*wait cycles*/, SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length, SPI_TRANS_SHORT); } void tft_write_word(uint32_t *data_buf, uint32_t length, uint32_t flag) { set_dcx_data(); spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0); spi_init_non_standard(SPI_CHANNEL, 0/*instrction length*/, 32/*address length*/, 0/*wait cycles*/, SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length, SPI_TRANS_INT); } void tft_fill_data(uint32_t *data_buf, uint32_t length) { set_dcx_data(); spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0); spi_init_non_standard(SPI_CHANNEL, 0/*instrction length*/, 32/*address length*/, 0/*wait cycles*/, SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); spi_fill_data_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length); } void lcd_polling_enable(void) { lcd_ctl.mode = 0; } void lcd_interrupt_enable(void) { lcd_ctl.mode = 1; } int lcd_init(void) { uint8_t data = 0; tft_hard_init(); /*soft reset*/ tft_write_command(SOFTWARE_RESET); usleep(100000); /*exit sleep*/ tft_write_command(SLEEP_OFF); usleep(100000); /*pixel format*/ tft_write_command(PIXEL_FORMAT_SET); data = 0x55; tft_write_byte(&data, 1); /*display on*/ tft_write_command(DISPALY_ON); lcd_polling_enable(); lcd_clear(PINK); lcd_set_direction(DIR_YX_RLDU); LOG_I("LCD initialization successfully"); } INIT_APP_EXPORT(lcd_init); void lcd_set_direction(lcd_dir_t dir) { lcd_ctl.dir = dir; if (dir & DIR_XY_MASK) { lcd_ctl.width = LCD_Y_MAX - 1; lcd_ctl.height = LCD_X_MAX - 1; } else { lcd_ctl.width = LCD_X_MAX - 1; lcd_ctl.height = LCD_Y_MAX - 1; } tft_write_command(MEMORY_ACCESS_CTL); tft_write_byte((uint8_t *)&dir, 1); } void lcd_set_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { uint8_t data[4] = {0}; data[0] = (uint8_t)(x1 >> 8); data[1] = (uint8_t)(x1); data[2] = (uint8_t)(x2 >> 8); data[3] = (uint8_t)(x2); tft_write_command(HORIZONTAL_ADDRESS_SET); tft_write_byte(data, 4); data[0] = (uint8_t)(y1 >> 8); data[1] = (uint8_t)(y1); data[2] = (uint8_t)(y2 >> 8); data[3] = (uint8_t)(y2); tft_write_command(VERTICAL_ADDRESS_SET); tft_write_byte(data, 4); tft_write_command(MEMORY_WRITE); } void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color) { lcd_set_area(x, y, x, y); tft_write_half(&color, 1); } void lcd_draw_char(uint16_t x, uint16_t y, char c, uint16_t color) { uint8_t i = 0; uint8_t j = 0; uint8_t data = 0; for (i = 0; i < 16; i++) { data = ascii0816[c * 16 + i]; for (j = 0; j < 8; j++) { if (data & 0x80) lcd_draw_point(x + j, y, color); data <<= 1; } y++; } } void lcd_draw_string(uint16_t x, uint16_t y, char *str, uint16_t color) { while (*str) { lcd_draw_char(x, y, *str, color); str++; x += 8; } } void lcd_ram_draw_string(char *str, uint32_t *ptr, uint16_t font_color, uint16_t bg_color) { uint8_t i = 0; uint8_t j = 0; uint8_t data = 0; uint8_t *pdata = NULL; uint16_t width = 0; uint32_t *pixel = NULL; width = 4 * strlen(str); while (*str) { pdata = (uint8_t *)&ascii0816[(*str) * 16]; for (i = 0; i < 16; i++) { data = *pdata++; pixel = ptr + i * width; for (j = 0; j < 4; j++) { switch (data >> 6) { case 0: *pixel = ((uint32_t)bg_color << 16) | bg_color; break; case 1: *pixel = ((uint32_t)bg_color << 16) | font_color; break; case 2: *pixel = ((uint32_t)font_color << 16) | bg_color; break; case 3: *pixel = ((uint32_t)font_color << 16) | font_color; break; default: *pixel = 0; break; } data <<= 2; pixel++; } } str++; ptr += 4; } } void lcd_clear(uint16_t color) { uint32_t data = ((uint32_t)color << 16) | (uint32_t)color; lcd_set_area(0, 0, lcd_ctl.width, lcd_ctl.height); tft_fill_data(&data, LCD_X_MAX * LCD_Y_MAX / 2); } void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width, uint16_t color) { uint32_t data_buf[640] = {0}; uint32_t *p = data_buf; uint32_t data = color; uint32_t index = 0; data = (data << 16) | data; for (index = 0; index < 160 * width; index++) *p++ = data; lcd_set_area(x1, y1, x2, y1 + width - 1); tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2, 0); lcd_set_area(x1, y2 - width + 1, x2, y2); tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2, 0); lcd_set_area(x1, y1, x1 + width - 1, y2); tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2, 0); lcd_set_area(x2 - width + 1, y1, x2, y2); tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2, 0); } void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t *ptr) { lcd_set_area(x1, y1, x1 + width - 1, y1 + height - 1); tft_write_word(ptr, width * height / 2, lcd_ctl.mode ? 2 : 0); } void lcd_pre() { fpioa_set_function(38, FUNC_GPIOHS0 + DCX_GPIONUM); fpioa_set_function(36, FUNC_SPI0_SS3); fpioa_set_function(39, FUNC_SPI0_SCLK); fpioa_set_function(37, FUNC_GPIOHS0 + RST_GPIONUM); } void lcd_test0() { char test[]={"xuos-intelligence framwork"}; lcd_draw_string(0,0,test,BLUE); } MSH_CMD_EXPORT(lcd_test0,lcd show string); void lcd_test1() { lcd_clear(YELLOW); } MSH_CMD_EXPORT(lcd_test1,lcd_clear(YELLOW)); #endif ```
查看更多
3
个回答
默认排序
按发布时间排序
xiaoyu
2021-02-08
这家伙很懒,什么也没写!
跪求大佬帮我解决下,解决了加微信发大红包
aozima
2021-02-08
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
可以加个互斥看看,也许哪里冲突了。 比如DMA?但看你代码两边用的不同的DMA通道。 或顺着这个思路检查下。
james_s
2021-04-13
这家伙很懒,什么也没写!
如果pin用的都对, 那么应该是bug, 我也遇到过drv_spi.c的bug, 也在调试.
撰写答案
登录
注册新账号
关注者
0
被浏览
1.2k
关于作者
xiaoyu
这家伙很懒,什么也没写!
提问
27
回答
27
被采纳
1
关注TA
发私信
相关问题
1
BBB的SPI驱动
2
求个SPI上挂两个或多个设备的使用例子
3
SPI设备有个bug
4
spi flash 的fatfs使用一段时间后读写文件出现故障
5
SPI驱动
6
请教rt_spi_configure函数理解
7
SPI FLASH挂载的问题
8
SPI-FLASH 文件系统 SPIFFS
9
求助一个完整的 spi flash 驱动
10
关于同时使用文件系统与SPI FLASH的问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
五分钟玩转RT-Thread新社区
5
国产MCU移植系列教程汇总,欢迎查看!
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
github高阶加速,速度可达带宽峰值,测试到146Mbit/s
2
英飞凌携手RT-Thread举办嵌入式网络应用开发沙龙,带你从0到1搭建智能数据网关
3
BL808 RT-Thread Wi-Fi 驱动适配
4
rt-thread 系统运行期改变网卡配置
5
简单的步进电机驱动调试
热门标签
RT-Thread Studio
串口
LWIP
Env
AT
SPI
Bootloader
FinSH
ART-Pi
CAN总线
Hardfault
USB
文件系统
RT-Thread
DMA
SCons
线程
MQTT
RT-Thread Nano
STM32
RTC
ESP8266
rt-smart
flash
ota在线升级
WIZnet_W5500
FAL
I2C
packages_软件包
UART
cubemx
freemodbus
潘多拉开发板_Pandora
定时器
BSP
PWM
ADC
socket
中断
rt_mq_消息队列_msg_queue
keil_MDK
SDIO
Debug
AB32VG1
MicroPython
C++_cpp
编译报错
msh
QEMU
ulog
本月问答贡献
出出啊
1500
个答案
338
次被采纳
小小李sunny
1389
个答案
276
次被采纳
张世争
714
个答案
157
次被采纳
crystal266
522
个答案
153
次被采纳
whj467467222
1216
个答案
146
次被采纳
本月文章贡献
出出啊
1
篇文章
12
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
2
篇文章
1
次点赞
crystal266
2
篇文章
5
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部