在ARM Linux下使用GPIO模擬SPI時序詳解

Author:楊正? Data2016.1.1 ?Mailyz2012ww@gmail.com

一、???????概述

SPI是英文SerialPeripheral Interface的縮寫,顧名思義就是串行外圍設備接口。SPI是一種高速、全雙工、同步通信總線,標準的SPI有4個引腳,常用于單片機和EEPROM、FLASH、實時時鐘、數字信號處理等器件的通信。SPI通信原理要比I2C簡單,它主要是主從方式通信,這種通信方式通常只有一個主機和一個或多個從機,標準的SPI是4根線,分別是SSEL(片選)、SCLK(時鐘,也寫作SCK)、MOSI(主機輸入,從機輸出)和MISO(主機輸入,從機輸出)。

SSEL:從設備片選使能信號。譬如從設備是低電平使能的話,當拉低這個引腳,從設備就會被選中,主機和這個被選中的從設備通信。

SCLK:時鐘信號,即主機產生。

MOSI:主機給從機發送指令或者數據的通道。

MISO:主機讀取從機的狀態或者數據的通道。

?

在某些情況下,也可以用3根或者2根線的SPI進行通信。譬如,主機只給從機發送指令,從機不需要回復數據的時候,MISO就可以不要;而主機只讀從機的數據,不需要給從機發送數據的時候,MOSI就可以不要;當一個主機與一個從機通信時,從機的片選有時可以固定為有效電平而一直處于使能狀態,那么SSEL可以不要,此時如果主機只給從機發數據,那么SSEL和MISO都可以不要;如果主機只讀取從機發送來的數據,那么SSEL和MOSI都可以不要。當然一般情況下說的SPI都指的是標準的SPI,有4根線進行通信。

?

?

二、? 時序分析

眾所周知,SPI時序有4種模式,在講解4種模式之前先學習兩個單詞,即PolarityPhase,這兩個單詞分別是SPI的時鐘極性(Polarity)和相位(Phase),最常見的寫法CPOLCPHA,也有其它的一些寫法,如:

(1) CKPOL (Clock Polarity) = CPOL = POL = Polarity =(時鐘)極性
(2) CKPHA (Clock Phase) ??= CPHA = PHA = Phase =
(時鐘)相位

?

那么時鐘極性是什么概念呢?SPI通信過程分為空閑狀態和通信狀態,空閑狀態是指SCLK在數據發送之前和發送完之后的狀態,通信狀態當然就是指發送數據的狀態。CPOL=1,那么空閑狀態SCLK為高電平,反之,CPOL=0,則空閑狀態SCLK為低電平。

?

SPI是一個環形的總線結構,主要是在SCLK的控制下,兩個雙向移位寄存器進行數據交換。那么主機和從機在進行交換數據的時候就設計到一個問題,即主機在什么時刻輸出到MOSI上而從機在什么時刻采樣這個數據,或者從機什么時刻輸出到MISO上而主機什么時刻采樣這個數據。同步通信的一個特點就是所有數據的變化和采樣都是伴隨著時鐘沿進行的,也就是說數據總是在時鐘的邊沿附近變化或被采樣,而一個完整的時鐘周期必定包含了一個上升沿和一個下降沿,這是周期的定義所決定的,只是這兩個沿的先后并無規定。又因為數據從產生到它穩定是需要一定的時間,那么如果主機在上升沿輸出數據到MOSI,從機就只能在下降沿去采樣這個數據了。反之,如果一方在下降沿輸出數據,那么另一方就必須在上升沿采樣這個數據。那么由誰來決定上升沿采樣還是下降沿采樣,上升沿輸出還是下降沿輸出呢?

?

CPHA=1時,表示數據的輸出在一個時鐘周期的第一個沿上,至于這個沿是上升沿還是下降沿,就得由CPOL來決定。CPOL=1那就是下降沿,反之就是上升沿。那么數據采樣自然就是第二個沿上了。

CPHA=0時,表示數據采樣在一個時鐘周期的第一個沿上,至于這個沿是上升沿還是下降沿,就得由CPOL來決定。CPOL=1那就是下降沿,反之就是上升沿。那么數據輸出自然就是第二個沿上了。

?

通過以上的學習,SPI的4中模式其實已經浮現出來了,下面對此做一總結:

Mode0

CPOL=0CPHA=0

Mode1

CPOL=0CPHA=1

Mode2

CPOL=1CPHA=0

Mode3

CPOL=1CPHA=1

?

圖形比文字更容易看懂,所以SPI4種模式的時序圖如下:


再進一步說明模式1SPI處于使能狀態,而且發送FIFO內有有效數據時,設置SSEL信號為低,表示開始傳輸數據。來自Slave的數據立刻發送到Master的接收數據線MISO。半個SCLK時鐘周期之后,有效的Master數據傳輸到MOSI。此時MasterSlave數據都已經有效,SCLK管腳在接下來的半個SCLK時鐘周期之后變為高電平。數據在SCLK時鐘的上升沿被捕獲(采樣),在時鐘的下降沿被傳送(輸出),傳輸完成后SSEL恢復為高電平。

?

再進一步說明模式2。當SPI為使能狀態,而且發送FIFO內有有效數據時,設置SSEL信號為低表示開始傳輸數據。半個SCLK時鐘周期之后,MasterSlave的有效數據分別在各自的傳輸線上有效。同時,SCLK從第一個上升沿開始有效。數據在SCLK時鐘的下降沿被捕獲,在時鐘的上升沿被傳送,傳輸完成后SSEL恢復為高電平。

?

再進一步的說明模式3。當SPI為使能狀態,而且發送FIFO內有有效數據時,設置SSEL信號為低表示開始傳輸數據。此時Slave的數據立刻發送到Master的接收數據線MISO。半個SCLK周期之后,Master的有效數據傳送到MOSI。再過半個SCLK時鐘周期之后,SCLK管腳設置為低。這表示數據在SCLK時鐘的下降沿被捕獲,在SCLK時鐘的上升沿被傳送,傳輸完成后SSEL恢復為高電平。

?

再進一步的說明模式4。當SPI為使能狀態,而且發送FIFO內有有效數據時,設置SSEL信號為低表示開始傳輸數據。半個SCLK時鐘周期后,MasterSlave數據在各自的傳輸線上有效。同時,時鐘SCLK1個下降沿開始有效。數據在SCLK時鐘的上升沿被捕獲,在時鐘的下降沿被傳送,傳輸完成后SSEL恢復為高電平。

?

?

?

三、? SPI訪問寄存器模式

?

常見的SPI訪問寄存器模式有3種,分別是SingleAccess(單次訪問)、Burst Access(突發訪問)、FIFO Access(FIFO訪問)。

?

SingleAccess:通過寫訪問發送一個地址字節后跟一個數據字節,或者發送一個地址字節,再通過讀訪問接收一個數據字節。發送幀時SSEL為低,發送完最后一個字節后SSEL變為高。如下圖,將0x0A寫到寄存器0x02上,再從該寄存器上讀其值。


W + addr. 0x02 Data: 0x0A ?????????????????????R + addr. 0x02 Data:

注意:SSEL第一次為低電平使能時,MISO變為高電平,然后立即變為低電平,這表示從設備芯片已經裝備好(Thefirst time CSn goes low, MISO goes high and then low again immediately,indicating that the chip is ready.)。


Single Byte Access (Write and Read)

?

?

BurstAccess:一個地址字節后跟多個數據字節。在每個數據字節之間地址字節會在內部自動增加,并且片選信號SSEL在發送幀時為低電平,在每個數據字節之間也保持低電平,當發送完最后一個字節后變為高電平。如:

BYTE xdata regValues[] = {1,2,3};

halSpiWriteBurstReg(0x00, regValues,sizeof(regValues));

halSpiReadReg(0x00);

halSpiReadReg(0x01);

halSpiReadReg(0x02);


BurstWrite Followed by Single Read

?

?

FIFO Access:如果地址字節對應的是FIFO地址,那么隨后的數據字節將針對FIFO。該地址字節沒有自動遞增而被存儲,并且不需要在每個數據字節之間發送該地址。片選信號SSEL在發送幀時為低電平,在每個數據字節之間也保持低電平,當發送完最后一個字節后變為高電平。

?

特別說明不同的SPI從設備地址字節的內容不一定相同,需要查看相關手冊,才能知道地址字節的構成是什么樣的。例如:RFM69H這個模塊SPI的地址字節的組成如下:

The first byteis the address byte. It is made of:

u? wnr bit, whichis 1 for write access and 0 for read access

u?7 bits of address, MSB first

?

又如CCXX00的地址字節組成如下:

The R/W bit in the address header controlsif the register should be written or read, and the burst bit controls if it

is a single access or a burst access.

R/W

Burst

A5

A4

A3

A2

A1

A0

:其實地址位只有5位,最高位為讀寫位,1為讀,0為寫;后面一位是burstAccess的使能位,當為1時使能。

?

?

四、? 例程解析

特別注意:在主設備這邊配置SPI接口時鐘的時候一定要弄清楚從設備的時鐘要求,因為主設備這邊的時鐘極性和相位都是以從設備為基準的。因此在時鐘極性的配置上一定要搞清楚從設備是在時鐘的上升沿還是下降沿接收數據,是在時鐘的下降沿還是上升沿輸出數據。但要注意的是,由于主設備的SDO連接從設備的SDI,從設備的SDO連接主設備的SDI,從設備SDI接收的數據是主設備的SDO發送過來的,主設備SDI接收的數據是從設備SDO發送過來的,所以主設備這邊SPI時鐘極性的配置(即SDO的配置)跟從設備的SDI接收數據的極性是相反的,跟從設備SDO發送數據的極性是相同的。

?

通過手冊得知(MOSI is generated by the master on the falling edge ofSCK and is sampled by the slave (i.e. this SPI interface) on the rising edge ofSCK. MISO is generated by the slave on the falling edge of SCK.A transferalways starts by the NSS pin going low. MISO is high impedance when NSS ishigh.),本例程使用的從設備的SPI工作在Mode1,即CPOL= 0 and CPHA = 0,且SSEL低電平使能,當SSEL為高電平時,MISO為高。故主機的MOSI在空閑狀態時為高。

/*********************************************************************************
*     Copyright:  (C) 2015 YangZheng<yz2012ww@gmail.com> 
*                  All rights reserved.
*
*      Filename:  dev_rfm69h.c
*   Description:  This file
*                
*       Version:  1.0.0(12/28/2015~)
*        Author:  Yang Zheng<yz2012ww@gmail.com>
*     ChangeLog:  1, Release initialversion on "12/28/2015 07:46:07 PM"
*                
********************************************************************************/
#include<linux/kernel.h>
#include<linux/version.h>
#include<linux/module.h>
#include<linux/types.h>
#include<linux/errno.h>
#include<linux/fcntl.h>
#include<linux/mm.h>
#include<linux/proc_fs.h>
#include<linux/fs.h>
#include<linux/slab.h>
#include<linux/init.h>
#include<asm/uaccess.h>
#include<asm/io.h>
#include <asm/system.h>
#include<linux/miscdevice.h>
#include<linux/delay.h>
#include<linux/sched.h>
#include<linux/proc_fs.h>
#include<linux/poll.h>
#include<asm/bitops.h>
#include<asm/uaccess.h>
#include<asm/irq.h>
#include<linux/moduleparam.h>
#include <linux/ioport.h>
#include<linux/interrupt.h>
#include<linux/cdev.h>
#include<linux/semaphore.h>
#include<linux/wait.h>
#define IOCONFIG4_4                                 IO_ADDRESS(0x200f0000+ 0x054)          //復用管腳gpio4_4
#define IOCONFIG4_5                                 IO_ADDRESS(0x200f0000+ 0x050)          //復用管腳gpio4_5
#define IOCONFIG4_6                                 IO_ADDRESS(0x200f0000+ 0x04c)          //復用管腳gpio4_6
#define IOCONFIG4_7                                 IO_ADDRESS(0x200f0000+ 0x048)          //復用管腳gpio4_7
#define GPIO4_BASE                                    0x20180000                        //gpio基地址
#define GPIO4_SIZE                                     0x10000             // 64KB
#define GPIO4_DIR                                      IO_ADDRESS(GPIO4_BASE + 0x400)     //gpio4方向寄存器
#defineGPIO_SPI_CS_REG                         IO_ADDRESS(GPIO4_BASE+ 0x40)          //gpio4_4數據寄存器
#defineGPIO4_SPI_SCK_REG                    IO_ADDRESS(GPIO4_BASE + 0x80)          //gpio4_5數據寄存器
#defineGPIO4_SPI_MOSI_REG                 IO_ADDRESS(GPIO4_BASE+ 0x100)     //gpio4_6數據寄存器
#defineGPIO4_SPI_MISO_REG                 IO_ADDRESS(GPIO4_BASE+ 0x200)     //gpio4_7數據寄存器
#define GPIO4_4                                           (1<< 4)   //gpio4_4
#define GPIO4_5                                           (1<< 5)   //gpio4_5
#define GPIO4_6                                           (1<< 6)   //gpio4_6
#define GPIO4_7                                           (1<< 7)   //gpio4_7
#define DATA_LENGTH                                21
#define DRV_AUTHOR                                "Yang Zheng<yz2012ww@gmail.com>"
#define DRV_DESC                                       "spi driver"                                                                                
#define DRV_VERSION                                "v0.0.1"
#if 0
#defineDBG(x...)   printk(x)
#define DBG_PRINT
#else
#defineDBG(x...)   do {} while (0)
#endif
staticDECLARE_WAIT_QUEUE_HEAD(spi_waitq);
unsigned char                                       read_tmp_data[DATA_LENGTH] = {0};
void __iomem                                       *reg_ssp_base_va;
typedef unsignedchar                       byte;
typedef unsignedshort                      word;
static int                                                read_flag = 0;
/******************************************************************************
**函數名稱:Set_nCS
**函數功能:禁用片選
**輸入參數:無
**輸出參數:無
**注意:   高電平為禁用片選,低電平為使能片選
******************************************************************************/
void Set_nCS(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_4);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸出
regvalue |= GPIO4_4;
writel(regvalue, GPIO4_DIR);
regvalue = readl(GPIO_SPI_CS_REG); 
regvalue |= GPIO4_4;
writel(regvalue, GPIO_SPI_CS_REG);  //禁用片選
}
/******************************************************************************
**函數名稱:Clr_nCS
**函數功能:使能片選
**輸入參數:無
**輸出參數:無
**注意:   高電平為禁用片選,低電平為使能片選
******************************************************************************/
void Clr_nCS(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_4);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸出
regvalue |= GPIO4_4;
writel(regvalue, GPIO4_DIR);
regvalue = readl(GPIO_SPI_CS_REG); 
regvalue &= ~GPIO4_4;
writel(0, GPIO_SPI_CS_REG);  //使能片選
}
/******************************************************************************
**函數名稱:Set_SCK
**函數功能:SCK為高電平
**輸入參數:無
**輸出參數:無
**注意:    
******************************************************************************/
void Set_SCK(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_5);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸出
regvalue |= GPIO4_5;
writel(regvalue, GPIO4_DIR);
regvalue =readl(GPIO4_SPI_SCK_REG);  //設置gpio輸出高電平
regvalue |= GPIO4_5;
writel(regvalue, GPIO4_SPI_SCK_REG);
}
/******************************************************************************
**函數名稱:Set_SCK
**函數功能:SCK為高電平
**輸入參數:無
**輸出參數:無
**注意:    
******************************************************************************/
void Clr_SCK(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_5);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸出
regvalue |= GPIO4_5;
writel(regvalue, GPIO4_DIR);
regvalue =readl(GPIO4_SPI_SCK_REG);  //設置gpio輸出低電平
regvalue &= ~GPIO4_5;
writel(regvalue,GPIO4_SPI_SCK_REG); 
}
/******************************************************************************
**函數名稱:Set_MOSI
**函數功能:MOSI為高電平
**輸入參數:無
**輸出參數:無
**注意:    
******************************************************************************/
void Set_MOSI(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_6);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸出
regvalue |= GPIO4_6;
writel(regvalue, GPIO4_DIR);
regvalue = readl(GPIO4_DIR);  //設置gpio輸出高電平
regvalue |= GPIO4_6;
writel(regvalue, GPIO4_SPI_MOSI_REG);
}
/******************************************************************************
**函數名稱:Set_MOSI
**函數功能:MOSI為低電平
**輸入參數:無
**輸出參數:無
**注意:    
******************************************************************************/
void Clr_MOSI(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_6);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸出
regvalue |= GPIO4_6;
writel(regvalue, GPIO4_DIR);
regvalue = readl(GPIO4_DIR);  //設置gpio輸出低電平
regvalue &= ~GPIO4_6;
writel(regvalue, GPIO4_SPI_MOSI_REG);
}
/******************************************************************************
**函數名稱:MISO_H
**函數功能:讀取MISO_H的值
**輸入參數:無
**輸出參數:無
**注意:    
******************************************************************************/
unsigned charMISO_H(void)
{
unsigned char regvalue;
writel(0, IOCONFIG4_7);   //gpio模式
regvalue = readl(GPIO4_DIR);  //設置gpio輸入
regvalue &= ~GPIO4_7;
writel(regvalue, GPIO4_DIR);
regvalue =readl(GPIO4_SPI_MISO_REG);  //讀取輸入值
//DBG("regvalue = %x\n",regvalue);
return regvalue;
}
/******************************************************************************
**函數名稱:SPICmd8bit
**函數功能:SPI寫入參數8bit
**輸入參數:WrPara
**輸出參數:無
**注意:   保留nCS輸出Low
******************************************************************************/
voidSPICmd8bit(byte WrPara)
{
byte bitcnt;     
Clr_nCS();
Clr_SCK();
for(bitcnt = 8; bitcnt != 0; bitcnt--)
{
Clr_SCK();
if(WrPara&0x80)
{
Set_MOSI();
}
else
{
Clr_MOSI();
}
Set_SCK();
WrPara <<= 1;
}
Clr_SCK();
Set_MOSI();
//Set_nCS();            //*此處不關閉nCS,使用連續模式*
}
/******************************************************************************
**函數名稱:SPIRead8bitt
**函數功能:SPI讀取參數8bit
**輸入參數:讀取8bit數據——RdPara
**輸出參數:無
**注意:   保留nCS輸出Low
******************************************************************************/
byte SPIRead8bit(void)
{
byte RdPara = 0;
byte bitcnt;
Clr_nCS();
Set_MOSI();               //讀FIFO,維持SDI為H 
for(bitcnt=8; bitcnt!=0; bitcnt--)
{
Clr_SCK();
RdPara <<= 1;
Set_SCK();
if(MISO_H())
{
RdPara |= 0x01;
}
else
{
;
}
}
Clr_SCK();
//Set_nCS();               //*此處不關閉nCS,使用連續模式*
//DBG("RdPara = %x\n",RdPara);
return(RdPara);
}
/******************************************************************************
**函數名稱:SPIRead
**函數功能:SPI讀取一個地址數據
**輸入參數:adr
**輸出參數:無
******************************************************************************/
byte SPIRead(byteadr)
{
byte tmp;         
SPICmd8bit(adr);               //發送要讀取的地址
tmp = SPIRead8bit();    //讀取數據    
Set_nCS();
return(tmp);
}
/******************************************************************************
**函數名稱:SPIWrite
**函數功能:SPI寫入一個16數據(高8位地址,低8位數據)
**輸入參數:WrPara
**輸出參數:無
******************************************************************************/
void SPIWrite(wordWrPara)                                                                    
{                                                      
byte bitcnt;   
Clr_SCK();                           //注意SCK先清0,保持低
Clr_nCS();
WrPara |= 0x8000;           //寫數據高位置1
for(bitcnt=16; bitcnt!=0; bitcnt--)
{
Clr_SCK();
if(WrPara&0x8000)
{
Set_MOSI();
}
else
{
Clr_MOSI();
}
Set_SCK();
WrPara <<= 1;
}
Clr_SCK();
Set_MOSI();
Set_nCS();
}         
/******************************************************************************
**函數名稱:SPIBurstRead
**函數功能:SPI連續讀取模式
**輸入參數:adr——讀取地址
**          ptr——存儲數據指針
**          length 讀取長度
**輸出參數:無,數據存在ptr中
******************************************************************************/
voidSPIBurstRead(byte adr, byte *ptr, byte length)
{
byte i;
if(length<=1)                       //讀取長度必須大于1
{
return;
}
else
{
Clr_SCK();                          //注意SCK先清0,保持低
Clr_nCS();
SPICmd8bit(adr);               //讀取地址
for(i=0;i<length;i++)
{
ptr[i]= SPIRead8bit();
}
Set_nCS();        
}
}
/******************************************************************************
**函數名稱:SPIBurstWrite
**函數功能:SPI連續寫入模式
**輸入參數:adr——寫入地址
**          ptr——存儲數據指針
**          length 寫入長度
**輸出參數:無
******************************************************************************/
voidBurstWrite(byte adr, byte *ptr, byte length)
{
byte i;
if(length<=1)                       //讀取長度不為0或1
{
return;
}
else 
{      
Clr_SCK();                           //注意SCK先清0,保持低
Clr_nCS();                                             
SPICmd8bit(adr|0x80);    //連續寫
for(i=0;i<length;i++)
{
SPICmd8bit(ptr[i]);
}
Set_nCS();        
}
}
longspi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
……
switch(cmd)
{
case SSP_READ_ALT:
…...
val = *(unsigned int*)arg;
addr = (unsignedchar)(val&0xff);
data =SPIRead(addr);
……
*(unsigned int *)arg= (unsigned int)(data&0x0000ff);
break;
case SSP_READ_BURST:
{
unsignedchar          addr = 0x00;
……
/*讀取數據 */
SPIBurstRead(addr,read_tmp_data, DATA_LENGTH);
…...
break;
}
case SSP_WRITE_ALT:
data = 0;
val  = *(unsigned int *)arg;
tmp = (unsignedshort)((val&0xff0000)>>8);      
tmp |= (unsignedshort)((val&0x0000ff)>>0);
……
SPIWrite(tmp);
break; 
case SSP_WRITE_BURST:
res =copy_from_user(tmp_str, (unsigned char *)arg, sizeof(tmp_str));
if (res != 0)
{
printk("copydata from the user space error\n");
}
……
BurstWrite(addr,data, DATA_LENGTH);
break;
default:
{
printk("Nosuch spi command %#x!\n", cmd);
return -1;
}
}
return 0;
}
int spi_open(structinode * inode, struct file * file)
{
……
return 0;
}
intspi_close(struct inode * inode, struct file * file)
{
return 0;
}
static structfile_operations spi_fops = {
.owner          =THIS_MODULE,
.unlocked_ioctl        = spi_ioctl,
.open           =spi_open,
.release           =spi_close
};
static structmiscdevice spi_dev = {
.minor                =MISC_DYNAMIC_MINOR,                                                                                      
.name               =DEV_NAME,
.fops                           =&spi_fops,
};
static int __initspi_gpio_init(void)
{
int ret;
ret = misc_register(&spi_dev);
if (ret < 0)
{
printk("registerspi_gpio device failed!\n");
return -1;
}
printk("SPI driver initializesuccessful! .\n");
return 0;
}
static void __exitspi_gpio_exit(void)
{
misc_deregister(&spi_dev);
printk("SPI driver exit!\n");
}
module_init(spi_gpio_init);
module_exit(spi_gpio_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION(DRV_DESC);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252956.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252956.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252956.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git clone時出現 error:inflate:data stream error(incorrect data check)

git clone時出現 error:inflate:data stream error(incorrect data check) fatal:serrious inflate inconsistency fatal:index-pack failed 經了解&#xff0c;此問題是遺留問題&#xff0c;之前是因為公司對gitlab服務器進行數據遷移而引起這種git clone失敗的原因&#xff0…

CentOS 7.5 使用 yum 安裝 Kubernetes 集群(二)

一、安裝方式介紹 1、yum 安裝 目前CentOS官方已經把Kubernetes源放入到自己的默認 extras 倉庫里面&#xff0c;使用 yum 安裝&#xff0c;好處是簡單&#xff0c;壞處也很明顯&#xff0c;需要官方更新 yum 源才能獲得最新版本的軟件&#xff0c;而所有軟件的依賴又不能自己指…

zbb20171108 tomcat 性能優化

原文地址http://www.cnblogs.com/NiceTime/p/6665416.html 1)內存優化(調整配置堆的大小&#xff0c;修改文件&#xff1a;catalina.sh) JAVA_OPTS"-Djava.awt.headlesstrue -Dfile.encodingUTF-8 -server -XX:MinHeapFreeRatio80 -XX:MaxHeapFreeRatio80 -XX:ThreadStack…

深入理解pthread_cond_wait、pthread_cond_signal

man pthread_cond_wait的解釋 LINUX環境下多線程編程肯定會遇到需要條件變量的情況&#xff0c;此時必然要使用pthread_cond_wait()函數。但這個函數的執行過程比較難于理解。 pthread_cond_wait()的工作流程如下&#xff08;以MAN中的EXAMPLE為例&#xff09;&#xff1a;…

LeetCode算法題-Factorial Trailing Zeroes(Java實現)

這是悅樂書的第183次更新&#xff0c;第185篇原創 01 看題和準備 今天介紹的是LeetCode算法題中Easy級別的第42題&#xff08;順位題號是172&#xff09;。給定一個整數n&#xff0c;返回n&#xff01;中的尾隨零數。例如&#xff1a; 輸入&#xff1a;3 輸出&#xff1a;0 說明…

JavaWeb基礎—JS學習小結

JavaScript是一種運行在瀏覽器中的解釋型的編程語言 推薦&#xff1a;菜鳥教程一、簡介js:javascript是基于對象【哪些基本對象呢】和和事件驅動【哪些主要事件呢】的語言&#xff0c;應用在客戶端&#xff08;注意與面向對象的區分&#xff09; js的三大特點&#xff1a;  交…

Asp.Net 設計模式 之 “簡單工廠”模式

主要思想&#xff1a;public static Operation CreateFactory(string ope) { //實例化空父類&#xff0c;讓父類指向子類 Operation op null; switch (ope) { case "": op …

UBuntu國內鏡像地址下載

http://www.oschina.net/p/ubuntu http://releases.ubuntu.com/ http://mirrors.163.com/ubuntu-releases/14.04/

Effective_STL 學習筆記(十九) 了解相等和等價的區別

find 算法和 set 的 insert 成員函數是很多必須判斷兩個值是否相同的函數代表&#xff0c; find 對 “相同” 的定義是相等&#xff0c;基于 operator &#xff0c; set::insert 對 “相同” 的定義是等價&#xff0c;通常基于 operator< 。 操作上來說&#xff0c;相等的概…

判斷是否獲取到手機相機權限

實際運用場景&#xff1a; 上傳圖片&#xff0c;查看相機設備&#xff0c;使用相機 在做這些操作的時候先調用這段話 AVAuthorizationStatus authStatus [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (authStatus AVAuthorizationStatusRestric…

事物筆記

什么是事務&#xff1a; 一件事情有N個組成單元&#xff0c;執行之后要么同時成功&#xff0c;要么同時失敗。 MySQL是一條默認的事務&#xff0c;一條sql語句就是一條事務。------------------------------------------------------------MySQL事務&#xff1a; 1、開啟一個事…

Python Socket通信黏包問題分析及解決方法

參考&#xff1a;http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5 1.黏包的表現(以客戶端遠程操作服務端命令為例) 注&#xff1a;只有在TCP協議通信的情況下&#xff0c;才會產生黏包問題 基于TCP協議實現的黏包 #!/usr/bin/env python # -*- coding: utf-8 -*- …

Django 路由

定義&#xff1a; URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要為該URL調用的視圖函數之間的映射表&#xff1b;你就是以這種方式告訴Django&#xff0c;對于這個URL調用這段代碼&#xff0c;對于那個URL調用那段代碼。 URL配置格式&#xff1a; urlpatter…

Ubuntu默認不進入圖形界面

修改 /etc/X11/default-display-manager如果值為/usr/sbin/gdm&#xff0c;(ubuntu12.04 為/usr/sbin/lightdm)則進入圖形界面 如果值為false&#xff0c;則進入控制臺&#xff08;命令行方式&#xff09;。如果想從控制臺進入圖形界面&#xff0c;可以在控制臺上輸入命令 sudo…

讀《構建之法》的心得體會

前段時間&#xff0c;我看了《構建之法》的一些內容&#xff0c;有了一些心得體會。 軟件工程所討論的是代碼量巨大、涉及人數眾多、項目需求多變時所要解決的問題。而在校學生根本就沒有這樣的環境。而鄒欣老師的《構建之法》是我讀過的書中最淺顯易懂的軟件工程書。 在緒論中…

2440內存管理

title: 2440內存管理 tags: ARM date: 2018-10-17 19:08:49 --- 2440內存管理 特性 大/小端&#xff08;通過軟件選擇&#xff09;地址空間&#xff1a;每個 Bank 有 128M 字節(總共 1G/8 個 Bank)除了 BANK0&#xff08;16/32 位&#xff09;之外【引導ROM&#xff0c;其總線寬…

C#設計模式之十二代理模式(Proxy Pattern)【結構型】

一、引言 今天我們要講【結構型】設計模式的第七個模式&#xff0c;也是“結構型”設計模式中的最后一個模式&#xff0c;該模式是【代理模式】&#xff0c;英文名稱是&#xff1a;Proxy Pattern。還是老套路&#xff0c;先從名字上來看看。“代理”可以理解為“代替”&#…

IPv6檢測

1&#xff09;判斷服務器是否支持IPv6 &#xff1a; http://ipv6-test.com/validate.php 2&#xff09;檢測當前設備打開網站的連接方式是IPv4還是IPv6&#xff1a; http://ipv6.sjtu.edu.cn/ 轉載于:https://www.cnblogs.com/superbobo/p/6687605.html

百度首席科學家吳恩達宣布將從百度離職

海外網3月22日電 據媒體消息&#xff0c;百度首席科學家吳恩達&#xff08;Andrew Ng&#xff09;在英文自媒體平臺Medium及微博、Twitter等個人社交平臺發布公開信&#xff0c;宣布自己將從百度離職&#xff0c;開啟自己在人工智能領域的新篇章。 吳恩達是人工智能和機器學習…

CentOS7.5 使用二進制程序部署Kubernetes1.12.2(三)

一、安裝方式介紹 1、yum 安裝 目前CentOS官方已經把Kubernetes源放入到自己的默認 extras 倉庫里面&#xff0c;使用 yum 安裝&#xff0c;好處是簡單&#xff0c;壞處也很明顯&#xff0c;需要官方更新 yum 源才能獲得最新版本的軟件&#xff0c;而所有軟件的依賴又不能自己指…