Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
K210
SPI
60
RTT下K210两路SPI不能同时使用问题,求大神
发布于 2021-02-08 15:16:49 浏览:1481
订阅该版
首先作为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.5k
关于作者
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
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
简单两步配置RTT源码阅读环境 vsc+clangd
2
恩智浦[FRDM-MCXN947]初探 之 ADC与DAC
3
LVGL使用字库IC芯片显示中文
4
基于STM32H750和Rt-Thread的CANFD通信实现的记录(一)
5
freemodbus主机在freertos的适配,参考rtthread例程
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部